Пример #1
0
/** Resets all highlighting in this layer.  Helper function for 
 * highlight_reset_all
 */
static void
highlight_reset_objects(GList *objects, Diagram *dia)
{
  for (; objects != NULL; objects = g_list_next(objects)) {
    DiaObject *object = (DiaObject*)objects->data;
    highlight_object_off(object, dia);
    if (IS_GROUP(object)) {
      highlight_reset_objects(group_objects(object), dia);
    }
  }
}
Пример #2
0
void diagram_ungroup_selected(Diagram *dia)
{
  DiaObject *group;
  GList *group_list;
  GList *selected, *selection_copy;
  int group_index;
  int any_groups = 0;
  
  if (g_list_length(dia->data->selected) < 1) {
    message_error("Trying to ungroup with no selected objects.");
    return;
  }
  
  selection_copy = g_list_copy(dia->data->selected);
  selected = selection_copy;
  while (selected != NULL) {
    group = (DiaObject *)selected->data;

    if (IS_GROUP(group)) {
      Change *change;

      /* Fix selection */
      diagram_unselect_object(dia, group);

      group_list = group_objects(group);

      group_index = layer_object_get_index(dia->data->active_layer, group);

      change = undo_ungroup_objects(dia, group_list, group, group_index);
      (change->apply)(change, dia);

      diagram_select_list(dia, group_list);
      any_groups = 1;
    }
    selected = g_list_next(selected);
  }
  g_list_free(selection_copy);
  
  if (any_groups) {
    diagram_modified(dia);
    diagram_flush(dia);
    undo_set_transactionpoint(dia->undo);
  }
}
Пример #3
0
static void
read_connections(GList *objects, xmlNodePtr layer_node,
		 GHashTable *objects_hash)
{
  ObjectNode obj_node;
  GList *list;
  xmlNodePtr connections;
  xmlNodePtr connection;
  char *handlestr;
  char *tostr;
  char *connstr;
  int handle, conn;
  DiaObject *to;
  
  list = objects;
  obj_node = layer_node->xmlChildrenNode;
  while ((list != NULL) && (obj_node != NULL)) {
    DiaObject *obj = (DiaObject *) list->data;

    /* the obj and there node must stay in sync to properly setup connections */
    while (obj_node && (xmlIsBlankNode(obj_node) || XML_COMMENT_NODE == obj_node->type)) 
      obj_node = obj_node->next;
    if (!obj_node) break;
    
    if IS_GROUP(obj) {
      read_connections(group_objects(obj), obj_node, objects_hash);
    } else {
      gboolean broken = FALSE;
      /* an invalid bounding box is a good sign for some need of corrections */
      gboolean wants_update = obj->bounding_box.right >= obj->bounding_box.left 
                           || obj->bounding_box.top >= obj->bounding_box.bottom;
      connections = obj_node->xmlChildrenNode;
      while ((connections!=NULL) &&
	     (xmlStrcmp(connections->name, (const xmlChar *)"connections")!=0))
	connections = connections->next;
      if (connections != NULL) {
	connection = connections->xmlChildrenNode;
	while (connection != NULL) {
	  char *donestr;
          if (xmlIsBlankNode(connection)) {
            connection = connection->next;
            continue;
          }
	  handlestr = (char * )xmlGetProp(connection, (const xmlChar *)"handle");
	  tostr = (char *) xmlGetProp(connection, (const xmlChar *)"to");
 	  connstr = (char *) xmlGetProp(connection, (const xmlChar *)"connection");
	  
	  handle = atoi(handlestr);
	  conn = strtol(connstr, &donestr, 10);
	  if (*donestr != '\0') { /* Didn't convert it all -- use string */
	    conn = -1;
	  }

	  to = g_hash_table_lookup(objects_hash, tostr);

	  if (to == NULL) {
	    message_error(_("Error loading diagram.\n"
			    "Linked object not found in document."));
	    broken = TRUE;
	  } else if (handle < 0 || handle >= obj->num_handles) {
	    message_error(_("Error loading diagram.\n"
			    "Connection handle %d does not exist on '%s'."),
			    handle, to->type->name);
	    broken = TRUE;
	  } else {
	    if (conn >= 0 && conn < to->num_connections) {
	      object_connect(obj, obj->handles[handle],
			     to->connections[conn]);
	      /* force an update on the connection, helpful with (incomplete) generated files */
	      if (wants_update) {
#if 0
	        obj->ops->move_handle(obj, obj->handles[handle], &to->connections[conn]->pos,
				      to->connections[conn], HANDLE_MOVE_CONNECTED,0);
#endif
	      }
	    } else {
	      message_error(_("Error loading diagram.\n"
			      "Connection point %d does not exist on '%s'."),
			    conn, to->type->name);
	      broken = TRUE;
	    }
	  }

	  if (handlestr) xmlFree(handlestr);
	  if (tostr) xmlFree(tostr);
	  if (connstr) xmlFree(connstr);

	  connection = connection->next;
	}
        /* Fix positions of the connection object for (de)generated files.
         * Only done for the last point connected otherwise the intermediate posisitions
         * may screw the auto-routing algorithm.
         */
        if (!broken && obj && obj->ops->set_props && wants_update) {
	  /* called for it's side-effect of update_data */
	  obj->ops->move(obj,&obj->position);

	  for (handle = 0; handle < obj->num_handles; ++handle) {
	    if (obj->handles[handle]->connected_to)
	      obj->ops->move_handle(obj, obj->handles[handle], &obj->handles[handle]->pos,
				    obj->handles[handle]->connected_to, HANDLE_MOVE_CONNECTED,0);
	  }
	}
      }
    }
    
    /* Now set up parent relationships. */
    connections = obj_node->xmlChildrenNode;
    while ((connections!=NULL) &&
	   (xmlStrcmp(connections->name, (const xmlChar *)"childnode")!=0))
      connections = connections->next;
    if (connections != NULL) {
      tostr = (char *)xmlGetProp(connections, (const xmlChar *)"parent");
      if (tostr) {
	obj->parent = g_hash_table_lookup(objects_hash, tostr);
	if (obj->parent == NULL) {
	  message_error(_("Can't find parent %s of %s object\n"), 
			tostr, obj->type->name);
	} else {
	  obj->parent->children = g_list_prepend(obj->parent->children, obj);
	}
      }
    }

    list = g_list_next(list);
    obj_node = obj_node->next;
  }
Пример #4
0
/**
 * Recursive function to read objects from a specific level in the xml.
 *
 * Nowadays there are quite a few of them :
 * - Layers : a diagram may have different layers, but this function does *not*
 *   add the created objects to them as it does not know on which nesting level it
 *   is called. So the topmost caller must add the returned objects to the layer.
 * - Groups : groups in itself can have an arbitrary nesting level including other
 *   groups or objects or both of them. A group not containing any objects is by 
 *   definition useless. So it is not created. This is to avoid trouble with some older
 *   diagrams which happen to be saved with empty groups.
 * - Parents : if the parent relations would have been there from the beginning of
 *   Dias file format they probably would have been added as nesting level 
 *   themselves. But to maintain forward compatibility (allow to let older versions
 *   of Dia to see as much as possible) they were added all on the same level and
 *   the parent child relation is reconstructed from additional attributes.
 */
static GList *
read_objects(xmlNodePtr objects, 
             GHashTable *objects_hash,const char *filename, DiaObject *parent,
	     GHashTable *unknown_objects_hash)
{
  GList *list;
  DiaObjectType *type;
  DiaObject *obj;
  ObjectNode obj_node;
  char *typestr;
  char *versionstr;
  char *id;
  int version;
  xmlNodePtr child_node;

  list = NULL;

  obj_node = objects->xmlChildrenNode;

  while ( obj_node != NULL) {
    if (xmlIsBlankNode(obj_node)) {
      obj_node = obj_node->next;
      continue;
    }

    if (!obj_node) break;

    if (xmlStrcmp(obj_node->name, (const xmlChar *)"object")==0) {
      typestr = (char *) xmlGetProp(obj_node, (const xmlChar *)"type");
      versionstr = (char *) xmlGetProp(obj_node, (const xmlChar *)"version");
      id = (char *) xmlGetProp(obj_node, (const xmlChar *)"id");
      
      version = 0;
      if (versionstr != NULL) {
	version = atoi(versionstr);
	xmlFree(versionstr);
      }

      type = object_get_type((char *)typestr);
      
      if (!type) {
	if (g_utf8_validate (typestr, -1, NULL) &&
	    NULL == g_hash_table_lookup(unknown_objects_hash, typestr))
	    g_hash_table_insert(unknown_objects_hash, g_strdup(typestr), 0);
      }
      else
      {
        obj = type->ops->load(obj_node, version, filename);
        list = g_list_append(list, obj);

        if (parent)
        {
          obj->parent = parent;
          parent->children = g_list_append(parent->children, obj);
        }

        g_hash_table_insert(objects_hash, g_strdup((char *)id), obj);

        child_node = obj_node->children;

        while(child_node)
        {
          if (xmlStrcmp(child_node->name, (const xmlChar *)"children") == 0)
          {
	    GList *children_read = read_objects(child_node, objects_hash, filename, obj, unknown_objects_hash);
            list = g_list_concat(list, children_read);
            break;
          }
          child_node = child_node->next;
        }
      }
      if (typestr) xmlFree(typestr);
      if (id) xmlFree (id);
    } else if (xmlStrcmp(obj_node->name, (const xmlChar *)"group")==0
               && obj_node->children) {
      /* don't create empty groups */
      obj = group_create(read_objects(obj_node, objects_hash, filename, NULL, unknown_objects_hash));
#ifdef USE_NEWGROUP
      /* Old group objects had objects recursively inside them.  Since
       * objects are now done with parenting, we need to extract those objects,
       * make a newgroup object, set parent-child relationships, and add
       * all of them to the diagram.
       */
      {
	DiaObject *newgroup;
	GList *objects;
	Point lower_right;
	type = object_get_type("Misc - NewGroup");
	lower_right = obj->position;
	newgroup = type->ops->create(&lower_right,
				     NULL,
				     NULL,
				     NULL);
	list = g_list_append(list, newgroup);
	
	for (objects = group_objects(obj); objects != NULL; objects = g_list_next(objects)) {
	  DiaObject *subobj = (DiaObject *) objects->data;
	  list = g_list_append(list, subobj);
	  subobj->parent = newgroup;
          newgroup->children = g_list_append(newgroup->children, subobj);
	  if (subobj->bounding_box.right > lower_right.x) {
	    lower_right.x = subobj->bounding_box.right;
	  }
	  if (subobj->bounding_box.bottom > lower_right.y) {
	    lower_right.y = subobj->bounding_box.bottom;
	  }
	}
	newgroup->ops->move_handle(newgroup, newgroup->handles[7],
			       &lower_right, NULL,
			       HANDLE_MOVE_CREATE_FINAL, 0);
	/* We've used the info from the old group, destroy it */
	group_destroy_shallow(obj);
      }
#else
      list = g_list_append(list, obj);
#endif
    } else {
      /* silently ignore other nodes */
    }

    obj_node = obj_node->next;
  }
  return list;
}
Пример #5
0
/* 
 * renderer methods 
 */ 
static void 
draw_object(DiaRenderer *self,
            DiaObject   *object,
	    DiaMatrix   *matrix)
{
  DrsRenderer *renderer = DRS_RENDERER (self);
  DiaMatrix *m = g_queue_peek_tail (renderer->matrices);
  xmlNodePtr node;

  g_queue_push_tail (renderer->parents, renderer->root);
  renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"object", NULL);
  xmlSetProp(node, (const xmlChar *)"type", (xmlChar *)object->type->name);
  /* if it looks like intdata store it as well */
  if ((int)object->type->default_user_data > 0 && (int)object->type->default_user_data < 0xFF) {
    gchar buffer[30];
    g_snprintf(buffer, sizeof(buffer), "%d", (int)object->type->default_user_data);
    xmlSetProp(node, (const xmlChar *)"intdata", (xmlChar *)buffer);
  }
  if (renderer->save_props) {
    xmlNodePtr props_node;

    props_node = xmlNewChild(node, NULL, (const xmlChar *)"properties", NULL);
    object_save_props (object, props_node, renderer->ctx);
  }
  if (matrix) {
    DiaMatrix *m2 = g_new (DiaMatrix, 1);
    if (m)
      dia_matrix_multiply (m2, matrix, m);
    else
      *m2 = *matrix;
    g_queue_push_tail (renderer->matrices, m2);
    /* lazy creation of our transformer */
    if (!renderer->transformer)
      renderer->transformer = dia_transform_renderer_new (self);
  }
  /* special handling for group objects:
   *  - for the render branch use DiaTransformRenderer, but not it's draw_object,
   *    to see all the children's draw_object ourself
   *  - for the object branch we rely on this draw_object being called so need
   *    to inline group_draw here
   *  - to maintain the correct transform build our own queue of matrices like
   *    the DiaTransformRenderer would do through it's draw_object
   */
  {
    g_queue_push_tail (renderer->parents, renderer->root);
    renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"render", NULL);
    if (renderer->transformer) {
      DiaMatrix *m = g_queue_peek_tail (renderer->matrices);

      if (IS_GROUP (object)) {
	/* reimplementation of group_draw to use this draw_object method */
	GList *list;
	DiaObject *obj;

	list = group_objects (object);
	while (list != NULL) {
	  obj = (DiaObject *) list->data;

	  DIA_RENDERER_GET_CLASS(self)->draw_object(self, obj, m);
	  list = g_list_next(list);
	}
      } else {
	/* just the leaf */
	DIA_RENDERER_GET_CLASS(renderer->transformer)->draw_object(renderer->transformer, object, m);
      }
    } else {
      object->ops->draw(object, DIA_RENDERER (renderer));
    }
    renderer->root = g_queue_pop_tail (renderer->parents);
  }
  renderer->root = g_queue_pop_tail (renderer->parents);

  if (matrix)
    g_queue_pop_tail (renderer->matrices);
  /* one lost demand destruction */
  if (renderer->transformer && g_queue_is_empty (renderer->matrices)) {
    g_object_unref (renderer->transformer);
    renderer->transformer = NULL;
  }
}
Пример #6
0
void
read_connections(GList *objects, xmlNodePtr layer_node,
		 GHashTable *objects_hash)
{
  ObjectNode obj_node;
  GList *list;
  xmlNodePtr connections;
  xmlNodePtr connection;
  char *handlestr;
  char *tostr;
  char *connstr;
  int handle, conn;
  Object *to;
  
  list = objects;
  obj_node = layer_node->childs;
  while (list != NULL) {
    Object *obj = (Object *) list->data;

    if IS_GROUP(obj) {
      read_connections(group_objects(obj), obj_node, objects_hash);
    } else {
      connections = obj_node->childs;
      while ((connections!=NULL) &&
	     (strcmp(connections->name, "connections")!=0))
	connections = connections->next;
      if (connections != NULL) {
	connection = connections->childs;
	while (connection != NULL) {
	  handlestr = xmlGetProp(connection, "handle");
	  tostr = xmlGetProp(connection, "to");
	  connstr = xmlGetProp(connection, "connection");
	  
	  handle = atoi(handlestr);
	  conn = atoi(connstr);
	  
	  to = g_hash_table_lookup(objects_hash, tostr);

	  if (handlestr) free(handlestr);
	  if (connstr) free(connstr);
	  if (tostr) free(tostr);

	  if (to == NULL) {
	    message_error(_("Error loading diagram.\n"
			    "Linked object not found in document."));
	  } else if (conn >= 0 && conn >= to->num_connections) {
	    message_error(_("Error loading diagram.\n"
			    "connection point does not exist."));
	  } else if (handle >= 0 && handle >= obj->num_handles) {
	    message_error(_("Error loading diagram.\n"
			    "connection handle does not exist."));
	  } else {
	    object_connect(obj, obj->handles[handle],
			   to->connections[conn]);
	  }

	  connection = connection->next;
	}
      }
      
    }
    
    list = g_list_next(list);
    obj_node = obj_node->next;
  }