Example #1
0
/** This is slightly more complex -- must see if any non-parented objects
 * are within a parenting object.
 */
static gboolean
diagram_selected_can_parent(Diagram *dia) {
  GList *selected;
  GList *parents = NULL;

  for (selected = dia->data->selected;
       selected != NULL; selected = selected->next) {
    DiaObject *obj = (DiaObject*)selected->data;
    if (object_flags_set(obj, DIA_OBJECT_CAN_PARENT)) {
      parents = g_list_prepend(parents, obj);
    }
  }
  for (selected = dia->data->selected;
       selected != NULL; selected = selected->next) {
    DiaObject *obj = (DiaObject*)selected->data;
    if (obj->parent == NULL) {
      GList *parent_tmp;
      for (parent_tmp = parents; parent_tmp != NULL; parent_tmp = parent_tmp->next) {
	if (object_within_parent(obj, (DiaObject*)parent_tmp->data)) {
	  g_list_free(parents);
	  return TRUE;
	}
      }
    }
  }
  g_list_free(parents);
  return FALSE;
}
Example #2
0
/** Remove all children from the selected parents. */
void diagram_unparent_children_selected(Diagram *dia)
{
  GList *list;
  DiaObject *obj, *child;
  gboolean any_unparented = FALSE;
  for (list = dia->data->selected; list != NULL; list = g_list_next(list))
  {
    obj = (DiaObject *) list->data;
    if (!object_flags_set(obj, DIA_OBJECT_CAN_PARENT) || !obj->children)
      continue;

    any_unparented = TRUE;
    /* Yes, this creates a whole bunch of Changes.  They're lightweight
     * structures, though, and it's easier to assure correctness this
     * way.  If needed, we can make a parent undo with a list of children.
     */
    while (obj->children != NULL) {
      Change *change;
      child = (DiaObject *) obj->children->data;
      change = undo_parenting(dia, obj, child, FALSE);
      /* This will remove one item from the list, so the while terminates. */
      (change->apply)(change, dia);
    }
    if (obj->children != NULL)
      printf("Obj still has %d children\n",
	     g_list_length(obj->children));
  }
  if (any_unparented) {
    diagram_modified(dia);
    diagram_flush(dia);
    undo_set_transactionpoint(dia->undo);
  }
}
Example #3
0
static gboolean
diagram_selected_any_parents(Diagram *dia) {
  GList *selected;

  for (selected = dia->data->selected;
       selected != NULL; selected = selected->next) {
    DiaObject *obj = (DiaObject*)selected->data;
    if (object_flags_set(obj, DIA_OBJECT_CAN_PARENT) && obj->children != NULL) 
      return TRUE;
  }
  return FALSE;
}
Example #4
0
/* needs faster algorithm -- if we find that parenting is slow.
 * If it works, don't optimize it until it's a hotspot. */
void diagram_parent_selected(Diagram *dia)
{
  GList *list = dia->data->selected;
  int length = g_list_length(list);
  int idx, idx2;
  ObjectExtent *oe;
  gboolean any_parented = FALSE;
  GPtrArray *extents = g_ptr_array_sized_new(length);
  while (list)
  {
    oe = g_new(ObjectExtent, 1);
    oe->object = list->data;
    parent_handle_extents(list->data, &oe->extent);
    g_ptr_array_add(extents, oe);
    list = g_list_next(list);
  }
  /* sort all the objects by their left position */
  g_ptr_array_sort(extents, diagram_parent_sort_cb);

  for (idx = 0; idx < length; idx++)
  {
    ObjectExtent *oe1 = g_ptr_array_index(extents, idx);
    if (oe1->object->parent)
      continue;

    for (idx2 = idx + 1; idx2 < length; idx2++)
    {
      ObjectExtent *oe2 = g_ptr_array_index(extents, idx2);
      if (!object_flags_set(oe2->object, DIA_OBJECT_CAN_PARENT))
        continue;

      if (oe1->extent.right <= oe2->extent.right
        && oe1->extent.bottom <= oe2->extent.bottom)
      {
	Change *change;
	change = undo_parenting(dia, oe2->object, oe1->object, TRUE);
	(change->apply)(change, dia);
	any_parented = TRUE;
	/*
        oe1->object->parent = oe2->object;
	oe2->object->children = g_list_append(oe2->object->children, oe1->object);
	*/
	break;
      }
    }
  }
  g_ptr_array_free(extents, TRUE);
  if (any_parented) {
    diagram_modified(dia);
    diagram_flush(dia);
    undo_set_transactionpoint(dia->undo);
  }
}
Example #5
0
/** Returns TRUE if an object is fully enclosed by a another object, which 
 * can be a parent */
gboolean
object_within_parent(DiaObject *obj, DiaObject *p)
{
  Rectangle obj_bb = obj->bounding_box;
  if (!object_flags_set(p, DIA_OBJECT_CAN_PARENT))
    return FALSE;
  if (p == obj) 
    return FALSE;
  if (obj_bb.left > p->bounding_box.left &&
      obj_bb.right < p->bounding_box.right &&
      obj_bb.top > p->bounding_box.top &&
      obj_bb.bottom < p->bounding_box.bottom)
    return TRUE;
  return FALSE;
}
Example #6
0
static void
newgroup_update_data(NewGroup *group)
{
  Element *elem = &group->element;
  /* ElementBBExtras *extra = &elem->extra_spacing; */
  DiaObject *obj = &elem->object;

  /* Update connections: */
  group->connections[0].pos.x = elem->corner.x;
  group->connections[0].pos.y = elem->corner.y;
  group->connections[1].pos.x = elem->corner.x + elem->width / 2.0;
  group->connections[1].pos.y = elem->corner.y;
  group->connections[2].pos.x = elem->corner.x + elem->width;
  group->connections[2].pos.y = elem->corner.y;
  group->connections[3].pos.x = elem->corner.x;
  group->connections[3].pos.y = elem->corner.y + elem->height / 2.0;
  group->connections[4].pos.x = elem->corner.x + elem->width;
  group->connections[4].pos.y = elem->corner.y + elem->height / 2.0;
  group->connections[5].pos.x = elem->corner.x;
  group->connections[5].pos.y = elem->corner.y + elem->height;
  group->connections[6].pos.x = elem->corner.x + elem->width / 2.0;
  group->connections[6].pos.y = elem->corner.y + elem->height;
  group->connections[7].pos.x = elem->corner.x + elem->width;
  group->connections[7].pos.y = elem->corner.y + elem->height;
  group->connections[8].pos.x = elem->corner.x + elem->width / 2.0;
  group->connections[8].pos.y = elem->corner.y + elem->height / 2.0;

  group->connections[0].directions = DIR_NORTH|DIR_WEST;
  group->connections[1].directions = DIR_NORTH;
  group->connections[2].directions = DIR_NORTH|DIR_EAST;
  group->connections[3].directions = DIR_WEST;
  group->connections[4].directions = DIR_EAST;
  group->connections[5].directions = DIR_SOUTH|DIR_WEST;
  group->connections[6].directions = DIR_SOUTH;
  group->connections[7].directions = DIR_SOUTH|DIR_EAST;
  group->connections[8].directions = DIR_ALL;

  element_update_boundingbox(elem);
  
  obj->position = elem->corner;
  
  element_update_handles(elem);

  if (group->is_open) {
    obj->flags &= ~DIA_OBJECT_GRABS_CHILD_INPUT;
  } else {
    gboolean newlySet = FALSE;
    Layer *layer;
    if (!object_flags_set(obj, DIA_OBJECT_GRABS_CHILD_INPUT)) {
      newlySet = TRUE;
    }
    obj->flags |= DIA_OBJECT_GRABS_CHILD_INPUT;
    if (newlySet) {
      layer = dia_object_get_parent_layer(obj);
      if (layer != NULL) { /* Placed in diagram already */
	GList *children = g_list_prepend(NULL, obj);
	children = parent_list_affected(children);
	/* Remove the group object that stayed at the start of the list,
	   leaving only the children */
	children = g_list_remove_link(children, children);
#if 0 /* this introduces a crircular dependency, does not work on win32 and is bad style everywhere */
	diagram_unselect_objects(layer_get_parent_diagram(layer), children);
#else
	g_warning ("used to call diagram_unselect_objects()");
#endif
	g_list_free(children);
      }
    }
  }
}