Re: Seminar on Dia
- From: Lennon Day-Reynolds <lennon kestrel edu>
- To: Andre Kloss <kloss rbg informatik tu-darmstadt de>
- Cc: dia-list gnome org
- Subject: Re: Seminar on Dia
- Date: Tue, 29 May 2001 09:14:01 -0700
Attached is the main source file for the 'subdiagram' object type --
visually, it's just rendered as a labelled box, but under its properties
view you'll see a field called 'Target'. Select a Dia diagram file for
that field, and open the object's middle-click menu, and you'll be able
to select 'Show Target...', which should open the diagram in a new window.
Nothing fancy, but not a bad starting point for more work, I hope.
Lennon Day-Reynolds
Software Engineer
Kestrel Institute
Andre Kloss wrote:
Hi, Lennon.
Cool, anyway - since I anyway need my own (very minimal) backend. I
only wanted to use Dia as the first editor of choice until I come up
with a native solution.
What I'd really appreciate is code for nested objects. I've had a
glance at the dia code and haven't found the point on which to start.
And for you being the "average Joe programmer": That's good, because I
have a certain dislike for theoreticians ;)
How far have you come with the dia-related code? Since I have a early
deadline I wonder if I could use it or if I have to come up with my
own solution here.
cu Andre
--
while(!asleep()) sheep++; -- Unknown
.
/* Dia -- an diagram creation/manipulation program
* Copyright (C) 1998 Alexander Larsson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <gtk/gtk.h>
#include <math.h>
#include <string.h>
#include "intl.h"
#include "object.h"
#include "objchange.h"
#include "element.h"
#include "connectionpoint.h"
#include "render.h"
#include "attributes.h"
#include "widgets.h"
#include "properties.h"
#include "diamenu.h"
#include "diagram.h"
#include "display.h"
#include "message.h"
#include "layer_dialog.h"
#include "pixmaps/subdiagram.xpm"
#define DEFAULT_WIDTH 2.0
#define DEFAULT_HEIGHT 1.0
#define TEXT_BORDER_WIDTH_X 0.7
#define TEXT_BORDER_WIDTH_Y 0.5
#define WEAK_BORDER_WIDTH 0.25
#define FONT_HEIGHT 0.8
typedef struct _Subdiagram Subdiagram;
typedef struct _SubdiagramState SubdiagramState;
typedef struct _SubdiagramChange SubdiagramChange;
struct _Subdiagram {
Element element;
ConnectionPoint connections[8];
real border_width;
Color border_color;
Color inner_color;
Font *font;
char *label;
real label_width;
char *filename;
};
struct _SubdiagramState {
//TODO: Add full state management for undo/redo?
};
struct _SubdiagramChange {
ObjectChange obj_change;
SubdiagramState *state;
// See comment in _SubdiagramState def above
};
static real subdiagram_distance_from(Subdiagram *subdiagram, Point *point);
static void subdiagram_select(Subdiagram *subdiagram, Point *clicked_point,
Renderer *interactive_renderer);
static void subdiagram_move_handle(Subdiagram *subdiagram, Handle *handle,
Point *to, HandleMoveReason reason, ModifierKeys modifiers);
static void subdiagram_move(Subdiagram *subdiagram, Point *to);
static void subdiagram_draw(Subdiagram *subdiagram, Renderer *renderer);
static void subdiagram_update_data(Subdiagram *subdiagram);
static Object *subdiagram_create(Point *startpoint,
void *user_data,
Handle **handle1,
Handle **handle2);
static void subdiagram_destroy(Subdiagram *subdiagram);
static Object *subdiagram_copy(Subdiagram *subdiagram);
static PropDescription *
subdiagram_describe_props(Subdiagram *subdiagram);
static void
subdiagram_get_props(Subdiagram *subdiagram, Property *props, guint nprops);
static void
subdiagram_set_props(Subdiagram *subdiagram, Property *props, guint nprops);
static void subdiagram_save(Subdiagram *subdiagram, ObjectNode obj_node,
const char *filename);
static Object *subdiagram_load(ObjectNode obj_node, int version,
const char *filename);
static DiaMenu *subdiagram_get_object_menu(Subdiagram *subdiagram);
static SubdiagramState *subdiagram_get_state(Subdiagram *subdiagram);
static void subdiagram_set_state(Subdiagram *subdiagram,
SubdiagramState *sstate);
static void subdiagram_free_state(SubdiagramState *sstate);
static ObjectTypeOps subdiagram_type_ops =
{
(CreateFunc) subdiagram_create,
(LoadFunc) subdiagram_load,
(SaveFunc) subdiagram_save
};
ObjectType subdiagram_type =
{
"Specware - Subdiagram", /* name */
0, /* version */
(char **) subdiagram_xpm, /* pixmap */
&subdiagram_type_ops /* ops */
};
ObjectType *_subdiagram_type = (ObjectType *) &subdiagram_type;
static ObjectOps subdiagram_ops = {
(DestroyFunc) subdiagram_destroy,
(DrawFunc) subdiagram_draw,
(DistanceFunc) subdiagram_distance_from,
(SelectFunc) subdiagram_select,
(CopyFunc) subdiagram_copy,
(MoveFunc) subdiagram_move,
(MoveHandleFunc) subdiagram_move_handle,
(GetPropertiesFunc) object_create_props_dialog,
(ApplyPropertiesFunc) object_apply_props_from_dialog,
(ObjectMenuFunc) subdiagram_get_object_menu,
(DescribePropsFunc) subdiagram_describe_props,
(GetPropsFunc) subdiagram_get_props,
(SetPropsFunc) subdiagram_set_props,
};
static PropDescription subdiagram_props[] = {
ELEMENT_COMMON_PROPERTIES,
{ "label", PROP_TYPE_STRING, PROP_FLAG_VISIBLE,
N_("Label:"), NULL, NULL },
{ "filename", PROP_TYPE_FILE, PROP_FLAG_VISIBLE,
N_("File:"), NULL, NULL },
PROP_STD_LINE_WIDTH,
PROP_STD_LINE_COLOUR,
PROP_STD_FILL_COLOUR,
PROP_DESC_END
};
static PropDescription *
subdiagram_describe_props(Subdiagram *subdiagram)
{
if (subdiagram_props[0].quark == 0)
prop_desc_list_calculate_quarks(subdiagram_props);
return subdiagram_props;
}
static PropOffset subdiagram_offsets[] = {
ELEMENT_COMMON_PROPERTIES_OFFSETS,
{ "label", PROP_TYPE_STRING, offsetof(Subdiagram, label) },
{ "filename", PROP_TYPE_FILE, offsetof(Subdiagram, filename) },
{ "line_width", PROP_TYPE_REAL, offsetof(Subdiagram, border_width) },
{ "line_colour", PROP_TYPE_COLOUR, offsetof(Subdiagram, border_color) },
{ "fill_colour", PROP_TYPE_COLOUR, offsetof(Subdiagram, inner_color) },
{ NULL, 0, 0}
};
static void
subdiagram_get_props(Subdiagram *subdiagram, Property *props, guint nprops)
{
object_get_props_from_offsets(&subdiagram->element.object,
subdiagram_offsets, props, nprops);
}
static void
subdiagram_set_props(Subdiagram *subdiagram, Property *props, guint nprops)
{
object_set_props_from_offsets(&subdiagram->element.object,
subdiagram_offsets, props, nprops);
subdiagram_update_data(subdiagram);
}
static real
subdiagram_distance_from(Subdiagram *subdiagram, Point *point)
{
Element *elem = &subdiagram->element;
Rectangle rect;
rect.left = elem->corner.x - subdiagram->border_width/2;
rect.right = elem->corner.x + elem->width + subdiagram->border_width/2;
rect.top = elem->corner.y - subdiagram->border_width/2;
rect.bottom = elem->corner.y + elem->height + subdiagram->border_width/2;
return distance_rectangle_point(&rect, point);
}
static void
subdiagram_select(Subdiagram *subdiagram, Point *clicked_point,
Renderer *interactive_renderer)
{
element_update_handles(&subdiagram->element);
}
static void
subdiagram_move_handle(Subdiagram *subdiagram, Handle *handle,
Point *to, HandleMoveReason reason, ModifierKeys modifiers)
{
assert(subdiagram!=NULL);
assert(handle!=NULL);
assert(to!=NULL);
element_move_handle(&subdiagram->element, handle->id, to, reason);
subdiagram_update_data(subdiagram);
}
static void
subdiagram_move(Subdiagram *subdiagram, Point *to)
{
subdiagram->element.corner = *to;
subdiagram_update_data(subdiagram);
}
static void
subdiagram_draw(Subdiagram *subdiagram, Renderer *renderer)
{
Point ul_corner, lr_corner;
Point p;
Element *elem;
assert(subdiagram != NULL);
assert(renderer != NULL);
elem = &subdiagram->element;
ul_corner.x = elem->corner.x;
ul_corner.y = elem->corner.y;
lr_corner.x = elem->corner.x + elem->width;
lr_corner.y = elem->corner.y + elem->height;
renderer->ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
renderer->ops->fill_rect(renderer,
&ul_corner,
&lr_corner,
&subdiagram->inner_color);
renderer->ops->set_linewidth(renderer, subdiagram->border_width);
renderer->ops->set_linestyle(renderer, LINESTYLE_SOLID);
renderer->ops->set_linejoin(renderer, LINEJOIN_MITER);
renderer->ops->draw_rect(renderer,
&ul_corner,
&lr_corner,
&subdiagram->border_color);
p.x = elem->corner.x + elem->width / 2.0;
p.y = elem->corner.y + (elem->height - FONT_HEIGHT)/2.0 + font_ascent(subdiagram->font, FONT_HEIGHT);
renderer->ops->set_font(renderer,
subdiagram->font, FONT_HEIGHT);
renderer->ops->draw_string(renderer,
subdiagram->label,
&p, ALIGN_CENTER,
&color_black);
}
static void
subdiagram_update_data(Subdiagram *subdiagram)
{
Element *elem = &subdiagram->element;
Object *obj = &elem->object;
ElementBBExtras *extra = &elem->extra_spacing;
subdiagram->label_width =
font_string_width(subdiagram->label, subdiagram->font, FONT_HEIGHT);
elem->width = subdiagram->label_width + 2*TEXT_BORDER_WIDTH_X;
elem->height = FONT_HEIGHT + 2*TEXT_BORDER_WIDTH_Y;
/* Update connections: */
subdiagram->connections[0].pos = elem->corner;
subdiagram->connections[1].pos.x = elem->corner.x + elem->width / 2.0;
subdiagram->connections[1].pos.y = elem->corner.y;
subdiagram->connections[2].pos.x = elem->corner.x + elem->width;
subdiagram->connections[2].pos.y = elem->corner.y;
subdiagram->connections[3].pos.x = elem->corner.x;
subdiagram->connections[3].pos.y = elem->corner.y + elem->height / 2.0;
subdiagram->connections[4].pos.x = elem->corner.x + elem->width;
subdiagram->connections[4].pos.y = elem->corner.y + elem->height / 2.0;
subdiagram->connections[5].pos.x = elem->corner.x;
subdiagram->connections[5].pos.y = elem->corner.y + elem->height;
subdiagram->connections[6].pos.x = elem->corner.x + elem->width / 2.0;
subdiagram->connections[6].pos.y = elem->corner.y + elem->height;
subdiagram->connections[7].pos.x = elem->corner.x + elem->width;
subdiagram->connections[7].pos.y = elem->corner.y + elem->height;
extra->border_trans = subdiagram->border_width/2.0;
element_update_boundingbox(elem);
obj->position = elem->corner;
element_update_handles(elem);
}
static Object *
subdiagram_create(Point *startpoint,
void *user_data,
Handle **handle1,
Handle **handle2)
{
Subdiagram *subdiagram;
Element *elem;
Object *obj;
int i;
subdiagram = g_malloc0(sizeof(Subdiagram));
elem = &subdiagram->element;
obj = &elem->object;
obj->type = &subdiagram_type;
obj->ops = &subdiagram_ops;
elem->corner = *startpoint;
elem->width = DEFAULT_WIDTH;
elem->height = DEFAULT_WIDTH;
subdiagram->border_width = attributes_get_default_linewidth();
subdiagram->border_color = attributes_get_foreground();
subdiagram->inner_color = attributes_get_background();
element_init(elem, 8, 8);
for (i=0;i<8;i++) {
obj->connections[i] = &subdiagram->connections[i];
subdiagram->connections[i].object = obj;
subdiagram->connections[i].connected = NULL;
}
subdiagram->font = font_getfont("Courier");
subdiagram->label = g_strdup(_("<unknown>"));
subdiagram->filename = g_strdup(_(""));
subdiagram->label_width =
font_string_width(subdiagram->label, subdiagram->font, FONT_HEIGHT);
subdiagram_update_data(subdiagram);
for (i=0;i<8;i++) {
obj->handles[i]->type = HANDLE_NON_MOVABLE;
}
*handle1 = NULL;
*handle2 = obj->handles[0];
return &subdiagram->element.object;
}
static void
subdiagram_destroy(Subdiagram *subdiagram)
{
element_destroy(&subdiagram->element);
g_free(subdiagram->label);
g_free(subdiagram->filename);
}
static Object *
subdiagram_copy(Subdiagram *subdiagram)
{
int i;
Subdiagram *newsubdiagram;
Element *elem, *newelem;
Object *newobj;
elem = &subdiagram->element;
newsubdiagram = g_malloc0(sizeof(Subdiagram));
newelem = &newsubdiagram->element;
newobj = &newelem->object;
element_copy(elem, newelem);
newsubdiagram->border_width = subdiagram->border_width;
newsubdiagram->border_color = subdiagram->border_color;
newsubdiagram->inner_color = subdiagram->inner_color;
for (i=0;i<8;i++) {
newobj->connections[i] = &newsubdiagram->connections[i];
newsubdiagram->connections[i].object = newobj;
newsubdiagram->connections[i].connected = NULL;
newsubdiagram->connections[i].pos = subdiagram->connections[i].pos;
newsubdiagram->connections[i].last_pos = subdiagram->connections[i].last_pos;
}
newsubdiagram->font = subdiagram->font;
newsubdiagram->label = strdup(subdiagram->label);
newsubdiagram->label_width = subdiagram->label_width;
newsubdiagram->filename = strdup(subdiagram->filename);
return &newsubdiagram->element.object;
}
static void
subdiagram_save(Subdiagram *subdiagram, ObjectNode obj_node, const char *filename)
{
element_save(&subdiagram->element, obj_node);
data_add_real(new_attribute(obj_node, "border_width"),
subdiagram->border_width);
data_add_color(new_attribute(obj_node, "border_color"),
&subdiagram->border_color);
data_add_color(new_attribute(obj_node, "inner_color"),
&subdiagram->inner_color);
data_add_string(new_attribute(obj_node, "label"),
subdiagram->label);
data_add_string(new_attribute(obj_node, "filename"),
subdiagram->filename);
}
static Object *
subdiagram_load(ObjectNode obj_node, int version, const char *filename)
{
Subdiagram *subdiagram;
Element *elem;
Object *obj;
int i;
AttributeNode attr;
subdiagram = g_malloc0(sizeof(Subdiagram));
elem = &subdiagram->element;
obj = &elem->object;
obj->type = &subdiagram_type;
obj->ops = &subdiagram_ops;
element_load(elem, obj_node);
subdiagram->border_width = 0.1;
attr = object_find_attribute(obj_node, "border_width");
if (attr != NULL)
subdiagram->border_width = data_real( attribute_first_data(attr) );
subdiagram->border_color = color_black;
attr = object_find_attribute(obj_node, "border_color");
if (attr != NULL)
data_color(attribute_first_data(attr), &subdiagram->border_color);
subdiagram->inner_color = color_white;
attr = object_find_attribute(obj_node, "inner_color");
if (attr != NULL)
data_color(attribute_first_data(attr), &subdiagram->inner_color);
subdiagram->label = NULL;
attr = object_find_attribute(obj_node, "label");
if (attr != NULL)
subdiagram->label = data_string(attribute_first_data(attr));
attr = object_find_attribute(obj_node, "filename");
if (attr != NULL)
subdiagram->filename = data_string(attribute_first_data(attr));
element_init(elem, 8, 8);
for (i=0;i<8;i++) {
obj->connections[i] = &subdiagram->connections[i];
subdiagram->connections[i].object = obj;
subdiagram->connections[i].connected = NULL;
}
subdiagram->font = font_getfont("Courier");
subdiagram->label_width =
font_string_width(subdiagram->label, subdiagram->font, FONT_HEIGHT);
subdiagram_update_data(subdiagram);
for (i=0;i<8;i++) {
obj->handles[i]->type = HANDLE_NON_MOVABLE;
}
return &subdiagram->element.object;
}
static ObjectChange *
subdiagram_create_change(Subdiagram *subdiagram)
{
ObjectChange *change;
SubdiagramState *sstate;
sstate = subdiagram_get_state(subdiagram);
change = new_object_state_change((Object *)subdiagram,
(ObjectState *)sstate,
(GetStateFunc)subdiagram_get_state,
(SetStateFunc)subdiagram_set_state );
return change;
}
static ObjectChange *
subdiagram_show_target(Subdiagram *subdiagram, gpointer data)
{
char *filename = subdiagram->filename;
Diagram *diagram = NULL;
DDisplay *ddisp = NULL;
if(filename!=NULL && strcmp(filename, "")) {
diagram = diagram_load(filename, NULL);
if(diagram!=NULL) {
diagram_update_extents(diagram);
layer_dialog_set_diagram(diagram);
ddisp = new_display(diagram);
display_set_active(ddisp);
} else {
message_error("Could not open subdiagram %s. Please insure that the file exists and
is readable", filename);
}
} else {
message_error("No file has been selected for this subdiagram.");
}
return (ObjectChange *)subdiagram_create_change(subdiagram);
}
static DiaMenuItem subdiagram_menu_items[] =
{
{
"Open...",
(DiaMenuCallback *)subdiagram_show_target,
NULL,
1
}
};
static DiaMenu subdiagram_menu =
{
"Subdiagram",
sizeof(subdiagram_menu_items)/sizeof(DiaMenuItem),
subdiagram_menu_items,
NULL
};
static DiaMenu *
subdiagram_get_object_menu(Subdiagram *subdiagram)
{
return &subdiagram_menu;
}
static SubdiagramState *
subdiagram_get_state (Subdiagram *subdiagram)
{
SubdiagramState *sstate;
sstate = g_new0(SubdiagramState, 1);
return sstate;
}
static void
subdiagram_set_state(Subdiagram *subdiagram, SubdiagramState *sstate)
{
// No-op
}
static void
subdiagram_free_state(SubdiagramState *sstate)
{
g_free(sstate);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]