1 /* Dia -- an diagram creation/manipulation program -*- c -*- 2 * Copyright (C) 1998 Alexander Larsson 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 /** @file object.h -- definitions for Dia objects, in particular the 'virtual' 20 * functions and the object and type structures. 21 */ 22 #ifndef OBJECT_H 23 #define OBJECT_H 24 25 #include "diatypes.h" 26 #include <gtk/gtk.h> 27 28 #include "geometry.h" 29 #include "connectionpoint.h" 30 #include "handle.h" 31 #include "diamenu.h" 32 #include "objchange.h" 33 #include "dia_xml.h" 34 #include "text.h" 35 36 G_BEGIN_DECLS 37 38 /** Flags for DiaObject */ 39 /** Set this if the DiaObject can 'contain' other objects that move with 40 * it, a.k.a. be a parent. A parent moves its children along and 41 * constricts its children to live inside its borders. 42 */ 43 #define DIA_OBJECT_CAN_PARENT 1 44 /** Set this if the DiaObject grabs all input destined for its children. 45 * This is typically used for group-like objects. 46 */ 47 #define DIA_OBJECT_GRABS_CHILD_INPUT 2 48 /** Set this if the DiaObject expands/contracts when children are 49 * moved/modified/added/deleted */ 50 #define DIA_OBJECT_EXPAND_WITH_CHILDREN 4 51 52 /** This enumeration gives a bitset of modifier keys currently held down. 53 */ 54 typedef enum { 55 MODIFIER_NONE, 56 MODIFIER_LEFT_SHIFT, 57 MODIFIER_RIGHT_SHIFT, 58 MODIFIER_SHIFT, 59 MODIFIER_LEFT_ALT = 4, 60 MODIFIER_RIGHT_ALT = 8, 61 MODIFIER_ALT = 12, 62 MODIFIER_LEFT_CONTROL = 16, 63 MODIFIER_RIGHT_CONTROL = 32, 64 MODIFIER_CONTROL = 48 65 } ModifierKeys; 66 67 /************************************ 68 ** Some general function prototypes 69 ** 70 ** These are the prototypes for the 71 ** functions that must be defined for 72 ** every object we can insert in a 73 ** diagram. 74 ** 75 ************************************/ 76 77 /*** Object type (class) operations ***/ 78 79 /** Function called to create an object. 80 * This function is responsible for allocation memory for the object. 81 * This is one of the object class functions. 82 * @param startpoint : initial position for the object 83 * @param user_data : Can be used to pass extra params to the creation 84 * of the object. Can be used to have two icons of 85 * the same object that are instansiated a bit different. 86 * @param handle1 : (return) Handle connected to startpoint 87 * @param handle2 : (return) Handle dragged on creation 88 * both handle1 and handle2 can be NULL 89 * @return A newly created object. 90 */ 91 typedef DiaObject* (*CreateFunc) (Point *startpoint, 92 void *user_data, 93 Handle **handle1, 94 Handle **handle2); 95 96 /** This function load the object's data from file fd. No header has to be 97 * skipped. The data should be read using the functions in lib/files.h 98 * The memory for the object has to be allocated (see CreateFunc) 99 * The version number is the version number of the DiaObjectType that was saved. 100 * This must be used to maintain backwards compatible if you change some 101 * in the save format. All objects must be capable of reading all earlier 102 * version. 103 * This is one of the object class functions. 104 * @param obj_node A node in an XML object to load from. 105 * @param version The version of the object found in the XML file. 106 * @param filename The name of the file we're loading from, for use in 107 * error messages. 108 */ 109 typedef DiaObject* (*LoadFunc) (ObjectNode obj_node, int version, 110 const char *filename); 111 112 /** This function save the object's data to file fd. No header is required. 113 * The data should be written using the functions in lib/files.h 114 * This is one of the object class functions. 115 * @param obj An object to save. 116 * @param obj_node An XML node to save it in. 117 * @param filename The name of the file we're saving to, for use in error 118 * messages. 119 */ 120 typedef void (*SaveFunc) (DiaObject* obj, ObjectNode obj_node, 121 const char *filename); 122 123 /** Function called when the user has double clicked on an Tool. 124 * When this function is called and the dialog already is created, 125 * make sure to update the values in the widgets so that it 126 * accurately describes the current state of the tool. 127 * This is one of the object class functions. 128 * @return a dialog that the user can use to edit the defaults for new 129 * objects of this type. 130 */ 131 typedef GtkWidget *(*GetDefaultsFunc) (); 132 133 /** Function called when the user clicks Apply on an edit defaults dialog. 134 * This is currently not used by any object. 135 * This is one of the object class functions. 136 */ 137 typedef void *(*ApplyDefaultsFunc) (); 138 139 /*** Object operations ***/ 140 141 /** Function called before an object is deleted. 142 * This function must call the parent class's DestroyFunc, and then free 143 * the memory associated with the object, but not the object itself 144 * Must also unconnect itself from all other objects. 145 * (This is by calling object_destroy, or letting the super-class call it) 146 * This is one of the object_ops functions. 147 * @param obj An object to destroy. 148 */ 149 typedef void (*DestroyFunc) (DiaObject* obj); 150 151 152 /** Function responsible for drawing the object. 153 * Every drawing must be done through the use of the Renderer, so that we 154 * can render the picture on screen, in an eps file, ... 155 * This is one of the object_ops functions. 156 * @param The object to draw. 157 * @param The renderer object to draw with. 158 */ 159 typedef void (*DrawFunc) (DiaObject* obj, DiaRenderer* ddisp); 160 161 162 /** This function must return the distance between the DiaObject and the Point. 163 * Several functions are provided in geometry.h to facilitate this calculus. 164 * This is one of the object_ops functions. 165 * @param obj The object. 166 * @param point A point to give the distance to. 167 * @return The distance from the point to the nearest part of the object. 168 * If the point is inside a closed object, return 0.0. 169 */ 170 typedef real (*DistanceFunc) (DiaObject* obj, Point* point); 171 172 173 /** Function called once the object has been selected. 174 * Basically, this function should update the object (position of the 175 * handles,...) This is one of the object_ops functions. 176 * This function should not redraw the object. 177 * @param obj An object that is being selected. 178 * @param clicked_point is the point on the screen where the user has clicked 179 * @param interactive_renderer is a renderer that has some extra functions 180 * most notably the possibility to get EXACT 181 * measures of strings. Used to place cursors 182 * and other interactive stuff. 183 * (Don't draw to the renderer) 184 */ 185 typedef void (*SelectFunc) (DiaObject* obj, 186 Point* clicked_point, 187 DiaRenderer* interactive_renderer); 188 189 /** Returns a copy of DiaObject. 190 * This must be an depth-copy (pointers must be duplicated and so on) 191 * as the initial object can be deleted any time. 192 * This is one of the object_ops functions. 193 * @param obj An object to make a copy of. 194 * @return A newly allocated object copied from `obj', but without any 195 * connections to other objects. 196 */ 197 typedef DiaObject* (*CopyFunc) (DiaObject* obj); 198 199 /** Function called to move the entire object. 200 * This is one of the object_ops functions. 201 * @param obj The object being moved. 202 * @param pos Where the object is being moved to. 203 * Its exact definition depends on the object. It is the point on the 204 * object that 'snaps' to the grid if that is enabled. (generally it 205 * is the upper left corner) 206 * @return An ObjectChange* with additional undo information, or 207 * (in most cases) NULL. Undo for moving the object itself is handled 208 * elsewhere. 209 */ 210 typedef ObjectChange* (*MoveFunc) (DiaObject* obj, Point * pos); 211 212 /** Function called to move one of the handles associated with the 213 * object. This is one of the object_ops functions. 214 * @param obj The object whose handle is being moved. 215 * @param handle The handle being moved. 216 * @param pos The position it has been moved to (corrected for 217 * vertical/horizontal only movement). 218 * @param cp If non-NULL, the connectionpoint found at this position. 219 * If @a cp is NULL, there may or may not be a connectionpoint. 220 * @param The reason the handle was moved. 221 * - HANDLE_MOVE_USER means the user is dragging the point. 222 * - HANDLE_MOVE_USER_FINAL means the user let go of the point. 223 * - HANDLE_MOVE_CONNECTED means it was moved because something 224 * it was connected to moved. 225 * @param modifiers gives a bitset of modifier keys currently held down 226 * - MODIFIER_SHIFT is either shift key 227 * - MODIFIER_ALT is either alt key 228 * - MODIFIER_CONTROL is either control key 229 * Each has MODIFIER_LEFT_* and MODIFIER_RIGHT_* variants 230 * @return An @a ObjectChange* with additional undo information, or 231 * (in most cases) NULL. Undo for moving the handle itself is handled 232 * elsewhere. 233 */ 234 typedef ObjectChange* (*MoveHandleFunc) (DiaObject* obj, 235 Handle* handle, 236 Point* pos, 237 ConnectionPoint* cp, 238 HandleMoveReason reason, 239 ModifierKeys modifiers); 240 241 /** Function called when the user has double clicked on an DiaObject. 242 * This is one of the object_ops functions. 243 * @param obj An obj that this dialog is being made for. 244 * @param is_default If true, this dialog is for object defaults, and 245 * the toolbox options should not be shown. 246 * @return A dialog to edit the properties of the object. 247 * When this function is called and the dialog already is created, 248 * make sure to update the values in the widgets so that it 249 * accurately describes the current state of the object. 250 * Remember to destroy this dialog when the object is destroyed! 251 252 * Note that if you want to use the same dialog multiple times, 253 * you should ref it first. Just run the following on the widget 254 * when you create it: 255 * gtk_object_ref(GTK_OBJECT(widget)); 256 * gtk_object_sink(GTK_OBJECT(widget)); / * optional, but recommended * / 257 * If you don't do this, the widget will be destroyed when the 258 * properties dialog is closed. 259 */ 260 typedef GtkWidget *(*GetPropertiesFunc) (DiaObject* obj, gboolean is_default); 261 262 /** This function is called when the user clicks on 263 * the "Apply" button. The widget parameter is the one created by 264 * the get_properties function. 265 * This is one of the object_ops functions. 266 * @param obj The object whose dialog has had its Apply button clicked. 267 * @param widget The properties dialog being applied. 268 * @return a Change that can be used for undo/redo. 269 * The returned change is already applied. 270 */ 271 typedef ObjectChange *(*ApplyPropertiesDialogFunc) (DiaObject* obj, GtkWidget *widget); 272 273 /** This function is used to apply a list of properties to the current 274 * object. It is typically called by ApplyPropertiesDialogFunc. This 275 * is different from SetPropsFunc since this is used to implement 276 * undo/redo. 277 * This is one of the object_ops functions. 278 * @param obj The object to which properties are to be applied 279 * @param props The list of properties that are to be applied 280 * @return a Change for undo/redo 281 */ 282 typedef ObjectChange *(*ApplyPropertiesListFunc) (DiaObject* obj, GPtrArray* props); 283 284 /** Desribe the properties that this object supports. 285 * This is one of the object_ops functions. 286 * @param obj The object whose properties we want described. 287 * @return a NULL-terminated array of property descriptions. 288 * As the const return implies the returned data is not owned by the 289 * caller. If this function returns a dynamically created description, 290 * then DestroyFunc must free the description. 291 */ 292 typedef const PropDescription *(* DescribePropsFunc) (DiaObject *obj); 293 294 /** Get the actual values of the properties given. 295 * Note that the props array need not contain all the properties 296 * defined for the object, nor do all the properties in the array need be 297 * defined for the object. All properties in the props array that are 298 * actually set will be set. 299 * This is one of the object_ops functions. 300 * @param obj An object that delivers the values. 301 * @param props A list of Property objects whose values are to be set based 302 * on the objects internal data. The types for the objects are 303 * also being set as a side-effect. 304 */ 305 typedef void (* GetPropsFunc) (DiaObject *obj, GPtrArray *props); 306 307 /** Set the object to have the values defined in the properties list. 308 * Note that the props array may contain more or fewer properties than the 309 * object defines, but only and all the ones defined for the object will 310 * be applied to the object. 311 * This is one of the object_ops functions. 312 * @param obj An object to update values on. 313 * @param props An array of Property objects whose values are to be set on 314 * the object. 315 */ 316 typedef void (* SetPropsFunc) (DiaObject *obj, GPtrArray *props); 317 318 /** Return an object-specific menu with toggles etc. properly set. 319 * This is one of the object_ops functions. 320 * @param obj The object that is selected when the object menu is asked for. 321 * @param position Where the user clicked. This can be used to place whatever 322 * the menu point may create, such as new segment corners. 323 * @return A menu description with values set appropriately for this object. 324 * The description object must not be freed by the caller. 325 */ 326 typedef DiaMenu *(*ObjectMenuFunc) (DiaObject* obj, Point *position); 327 328 /** Function for updates on a text part of an object. This function, if 329 * not null, will be called every time the text is changed or editing 330 * starts or stops. 331 * This is one of the object_ops functions. 332 * @param obj The self object 333 * @param text The text entry being edited 334 * @param state The state of the editing, either TEXT_EDIT_START, 335 * TEXT_EDIT_INSERT, TEXT_EDIT_DELETE, or TEXT_EDIT_END. 336 * @param textchange For TEXT_EDIT_INSERT, the text about to be inserted. 337 * For TEXT_EDIT_DELETE, the text about to be deleted. 338 * @return For TEXT_EDIT_INSERT and TEXT_EDIT_DELETE, TRUE this change 339 * will be allowed, FALSE otherwise. For TEXT_EDIT_START and TEXT_EDIT_END, 340 * the return value is ignored. 341 */ 342 typedef gboolean (*TextEditFunc) (DiaObject *obj, Text *text, TextEditState state, gchar *textchange); 343 344 /************************************* 345 ** The functions provided in object.c 346 *************************************/ 347 348 void object_init(DiaObject *obj, int num_handles, int num_connections); 349 void object_destroy(DiaObject *obj); /* Unconnects handles, so don't 350 free handles before calling. */ 351 void object_copy(DiaObject *from, DiaObject *to); 352 353 void object_save(DiaObject *obj, ObjectNode obj_node); 354 void object_load(DiaObject *obj, ObjectNode obj_node); 355 356 GList *object_copy_list(GList *list); 357 ObjectChange* object_list_move_delta_r(GList *objects, Point *delta, gboolean affected); 358 ObjectChange* object_list_move_delta(GList *objects, Point *delta); 359 /** Rotate an object around a point. If center is NULL, the position of 360 * the object is used. */ 361 ObjectChange* object_list_rotate(GList *objects, Point *center, real angle); 362 /** Scale an object around a point. If center is NULL, the position of 363 * the object is used. */ 364 ObjectChange* object_list_scale(GList *objects, Point *center, real factor); 365 void destroy_object_list(GList *list); 366 void object_add_handle(DiaObject *obj, Handle *handle); 367 void object_add_handle_at(DiaObject *obj, Handle *handle, int pos); 368 void object_remove_handle(DiaObject *obj, Handle *handle); 369 void object_add_connectionpoint(DiaObject *obj, ConnectionPoint *conpoint); 370 void object_remove_connectionpoint(DiaObject *obj, 371 ConnectionPoint *conpoint); 372 void object_add_connectionpoint_at(DiaObject *obj, 373 ConnectionPoint *conpoint, 374 int pos); 375 void object_connect(DiaObject *obj, Handle *handle, 376 ConnectionPoint *conpoint); 377 void object_unconnect(DiaObject *connected_obj, Handle *handle); 378 void object_remove_connections_to(ConnectionPoint *conpoint); 379 void object_unconnect_all(DiaObject *connected_obj); 380 void object_registry_init(void); 381 void object_register_type(DiaObjectType *type); 382 void object_registry_foreach(GHFunc func, gpointer user_data); 383 DiaObjectType *object_get_type(char *name); 384 gchar *object_get_displayname (DiaObject* obj); 385 gboolean object_flags_set(DiaObject* obj, gint flags); 386 387 /* These functions can be used as a default implementation for an object which 388 can be completely described, loaded and saved through standard properties. 389 */ 390 DiaObject *object_load_using_properties(const DiaObjectType *type, 391 ObjectNode obj_node, int version, 392 const char *filename); 393 void object_save_using_properties(DiaObject *obj, ObjectNode obj_node, 394 int version, const char *filename); 395 DiaObject *object_copy_using_properties(DiaObject *obj); 396 397 /***************************************** 398 ** The structures used to define an object 399 *****************************************/ 400 401 /** 402 * \private This is currently unused 403 * 404 * This structure defines an affine transformation that has been applied 405 * to this object. Affine transformations done on a group are performed 406 * on all objects in the group. 407 */ 408 typedef struct _Affine { 409 real rotation; 410 real scale; 411 real translation; 412 } Affine; 413 414 415 /*! 416 \brief _DiaObject vtable 417 418 This structure gives access to the functions used to manipulate an object 419 See information above on the use of the functions 420 */ 421 struct _ObjectOps { 422 DestroyFunc destroy; 423 DrawFunc draw; 424 DistanceFunc distance_from; 425 SelectFunc selectf; 426 CopyFunc copy; 427 MoveFunc move; 428 MoveHandleFunc move_handle; 429 GetPropertiesFunc get_properties; 430 ApplyPropertiesDialogFunc apply_properties_from_dialog; 431 ObjectMenuFunc get_object_menu; 432 433 DescribePropsFunc describe_props; 434 GetPropsFunc get_props; 435 SetPropsFunc set_props; 436 437 TextEditFunc edit_text; 438 439 ApplyPropertiesListFunc apply_properties_list; 440 441 /*! 442 Unused places (for extension). 443 These should be NULL for now. In the future they might be used. 444 Then an older object will be binary compatible, because all new code 445 checks if new ops are supported (!= NULL) 446 */ 447 void (*(unused[4]))(DiaObject *obj,...); 448 }; 449 450 /*! 451 \class _DiaObject 452 453 \brief Base class for all of Dia's objects, i.e. diagram building blocks 454 455 The base class in the DiaObject hierarchy. 456 All information in this structure read-only 457 from the application point of view except 458 when connection objects. (Then handles and 459 connections are changed). 460 461 position is not necessarly the corner of the object, but rather 462 some 'good' spot on it which will be natural to snap to. 463 */ 464 struct _DiaObject { 465 DiaObjectType *type; /*!< pointer to the registered type */ 466 Point position; /*!< often but not necessarily the upper left corner of the object */ 467 /** The area that contains all parts of the 'real' object, i.e. the parts 468 * that would be printed, exported to pixmaps etc. This is also used to 469 * determine the size of autofit scaling, so it should be as large as 470 * the objects without interactive bits and preferably no larger. 471 * The bounding_box will always contain this box. 472 * Do not access this field directly, but use dia_object_get_enclosing_box(). 473 */ 474 Rectangle bounding_box; 475 Affine affine; /*!< unused */ 476 477 int num_handles; 478 Handle **handles; 479 480 int num_connections; 481 ConnectionPoint **connections; 482 483 ObjectOps *ops; /*!< pointer to the vtable */ 484 485 Layer *parent_layer; /*< Back-pointer to the owning layer. 486 This may only be set by functions internal to 487 the layer, and accessed via 488 dia_object_get_parent_layer() */ 489 DiaObject *parent; /*!< Back-pointer to DiaObject which is parenting this object. Can be NULL */ 490 GList *children; /*!< In case this object is a parent of other object the children are listed here */ 491 gint flags; /*!< Various flags that can be set for this object, see defines above */ 492 493 Color *highlight_color; /*!< The color that this object is currently 494 highlighted with, or NULL if it is not 495 highlighted. */ 496 /** The area that contains all parts rendered interactively, so includes 497 * handles, bezier controllers etc. Despite historical difference, this 498 * should not be accessed directly, but through dia_object_get_bounding_box(). 499 * Note that handles and connection points are not included by this, but 500 * added by that which needs it. 501 * Internal: If this is set to a 0x0 box, returns bounding_box. That is for 502 * those objects that don't actually calculate it, but can just use the BB. 503 * Since handles and CPs are not in the BB, that will be the case for most 504 * objects. 505 */ 506 Rectangle enclosing_box; 507 /** Metainfo of the object, should not be manipulated directy */ 508 GHashTable *meta; 509 }; 510 511 /*! 512 * \brief Vtable for _DiaObjectType 513 */ 514 struct _ObjectTypeOps { 515 CreateFunc create; 516 LoadFunc load; 517 SaveFunc save; 518 GetDefaultsFunc get_defaults; 519 ApplyDefaultsFunc apply_defaults; 520 /* 521 Unused places (for extension). 522 These should be NULL for now. In the future they might be used. 523 Then an older object will be binary compatible, because all new code 524 checks if new ops are supported (!= NULL) 525 */ 526 void (*(unused[10]))(DiaObject *obj,...); 527 }; 528 529 /*! 530 \brief _DiaObject factory 531 532 Structure so that the ObjectFactory can create objects 533 of unknown type. (Read in from a shared lib.) 534 */ 535 struct _DiaObjectType { 536 537 char *name; /*!< The type name should follow a pattern of '<module> - <class>' like "UML - Class" */ 538 int version; /*!< DiaObjects must be backward compatible, i.e. support possibly older versions formats */ 539 540 char **pixmap; /* Also put a pixmap in the sheet_object. 541 This one is used if not in sheet but in toolbar. 542 Stored in xpm format */ 543 544 ObjectTypeOps *ops; /*!< pointer to the vtable */ 545 546 char *pixmap_file; /* fallback if pixmap is NULL */ 547 void *default_user_data; /* use this if no user data is specified in 548 the .sheet file */ 549 }; 550 551 /* base property stuff ... */ 552 #define OBJECT_COMMON_PROPERTIES \ 553 { "obj_pos", PROP_TYPE_POINT, PROP_FLAG_OPTIONAL, \ 554 "Object position", "Where the object is located"}, \ 555 { "obj_bb", PROP_TYPE_RECT, PROP_FLAG_OPTIONAL, \ 556 "Object bounding box", "The bounding box of the object"}, \ 557 { "meta", PROP_TYPE_DICT, PROP_FLAG_OPTIONAL, \ 558 "Object meta info", "Some key/value pairs"} 559 560 #define OBJECT_COMMON_PROPERTIES_OFFSETS \ 561 { "obj_pos", PROP_TYPE_POINT, offsetof(DiaObject, position) }, \ 562 { "obj_bb", PROP_TYPE_RECT, offsetof(DiaObject, bounding_box) }, \ 563 { "meta", PROP_TYPE_DICT, offsetof(DiaObject, meta) } 564 565 566 gboolean dia_object_defaults_load (const gchar *filename, 567 gboolean create_lazy); 568 DiaObject *dia_object_default_get (const DiaObjectType *type, gpointer user_data); 569 DiaObject *dia_object_default_create (const DiaObjectType *type, 570 Point *startpoint, 571 void *user_data, 572 Handle **handle1, 573 Handle **handle2); 574 gboolean dia_object_defaults_save (const gchar *filename); 575 Layer *dia_object_get_parent_layer(DiaObject *obj); 576 gboolean dia_object_is_selected (const DiaObject *obj); 577 const Rectangle *dia_object_get_bounding_box(const DiaObject *obj); 578 const Rectangle *dia_object_get_enclosing_box(const DiaObject *obj); 579 DiaObject *dia_object_get_parent_with_flags(DiaObject *obj, guint flags); 580 gboolean dia_object_is_selectable(DiaObject *obj); 581 /* The below are for debugging purposes only. */ 582 gboolean dia_object_sanity_check(const DiaObject *obj, const gchar *msg); 583 584 /** A standard definition of a function that takes a DiaObject */ 585 typedef void (*DiaObjectFunc) (const DiaObject *obj); 586 587 /** convenience functions for meta info */ 588 void dia_object_set_meta (DiaObject *obj, const gchar *key, const gchar *value); 589 gchar *dia_object_get_meta (DiaObject *obj, const gchar *key); 590 591 G_END_DECLS 592 593 #endif /* OBJECT_H */ 594 595 596