Example #1
0
File: textobj.c Project: GNOME/dia
static ObjectChange *
_textobj_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data)
{
  Textobj *textobj = (Textobj *)obj;
  const Text *text = textobj->text;
  DiaObject *path = NULL;

  if (!text_is_empty(text)) /* still screwed with empty lines ;) */
    path = create_standard_path_from_text (text);

  if (path) {
    ObjectChange *change;
    Color bg = textobj->fill_color;

    /* FIXME: otherwise object_substitue() will tint the text with bg */
    textobj->fill_color = text->color;
    change = object_substitute (obj, path);
    /* restore */
    textobj->fill_color = bg;

    return change;
  }
  /* silently fail */
  return change_list_create ();
}
Example #2
0
/*!
 * \brief Convert _StdPath to one or more _BezierLine/BezierGon
 */
static ObjectChange *
_convert_to_beziers_callback (DiaObject *obj, Point *clicked, gpointer data)
{
  StdPath *stdpath = (StdPath *)obj;
  BezPoint *bezier = stdpath->points;
  GList *list = NULL;
  int i, n = 0;
  ObjectChange *change;

  for (i = 1; i < stdpath->num_points; ++i) {
    if (bezier[i].type == BEZ_MOVE_TO || i+1 == stdpath->num_points) {
      DiaObject *rep;
      int num = bezier[i].type == BEZ_MOVE_TO ? i - n : i - n + 1;
      if (stdpath->stroke_or_fill & PDO_FILL)
	rep = create_standard_beziergon (num, &bezier[n]);
      else
	rep = create_standard_bezierline (num, &bezier[n], NULL, NULL);
      if (!rep) /* no Standard objects? */
	break;
      list = g_list_append (list, rep);
      n = i;
    }
  }
  if (!list) {
    change = change_list_create ();
  } else if (g_list_length (list) == 1) {
    change = object_substitute (obj, (DiaObject *)list->data);
    g_list_free (list);
  } else {
    change = object_substitute (obj, create_standard_group (list));
  }

  return change;
}
Example #3
0
static ObjectChange *
_box_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data)
{
  const Box *box = (Box *)obj;
  const Element *elem = &box->element;
  DiaObject *path;
  int num_points;
  BezPoint *points;

  if (box->corner_radius > 0) {
    const real w = elem->width;
    const real h = elem->height;
    const real x = elem->corner.x;
    const real y = elem->corner.y;
    real r = box->corner_radius;
    num_points = 9;
    points = g_alloca (sizeof(BezPoint) * num_points);

    /* avoid r>w/w and r>h/2 */
    r = (w > h ) ? (r > h/2 ? h/2 : r) : (r > w/2 ? w/2 : r);

    points[0].type = BEZ_MOVE_TO;  points[0].p1.x = x + r; points[0].p1.y = y; /* top-left */
    points[1].type = BEZ_LINE_TO;  points[1].p1.x = x + w - r; points[1].p1.y = y; /* top-right */
    points[2].type = BEZ_CURVE_TO; points[2].p1.x = x + w - r; points[2].p1.y = y; /* around */
    points[2].p2.x = x + w; points[2].p2.y = y; points[2].p3.x = x + w; points[2].p3.y = y + r;
    points[3].type = BEZ_LINE_TO; points[3].p1.x =  x + w; points[3].p1.y = y + h - r; /* bottom-right */
    points[4].type = BEZ_CURVE_TO; points[4].p1.x = x + w; points[4].p1.y = y + h - r; /* around */
    points[4].p2.x = x + w; points[4].p2.y = y + h; points[4].p3.x = x + w - r; points[4].p3.y = y + h;
    points[5].type = BEZ_LINE_TO;  points[5].p1.x = x + r; points[5].p1.y = y + h; /* bottom-left */
    points[6].type = BEZ_CURVE_TO; points[6].p1.x = x + r; points[6].p1.y = y + h; /* around */
    points[6].p2.x = x; points[6].p2.y = y + h; points[6].p3.x = x; points[6].p3.y = y + h - r;
    points[7].type = BEZ_LINE_TO;  points[7].p1.x = x; points[7].p1.y = y + r; /* top-left */
    points[8].type = BEZ_CURVE_TO; points[8].p1.x = x; points[8].p1.y = y + r; /* around */
    points[8].p2.x = x; points[8].p2.y = y; points[8].p3.x = x + r; points[8].p3.y = y;
  } else {
    num_points = 5;
    points = g_alloca (sizeof(BezPoint) * num_points);

    points[0].type = BEZ_MOVE_TO;
    points[0].p1 = elem->corner;
    points[1].type = points[2].type = points[3].type = points[4].type = BEZ_LINE_TO;
    points[1].p1.x = elem->corner.x + elem->width;
    points[1].p1.y = elem->corner.y;
    points[2].p1.x = elem->corner.x + elem->width;
    points[2].p1.y = elem->corner.y + elem->height;
    points[3].p1.x = elem->corner.x;
    points[3].p1.y = elem->corner.y + elem->height;
    points[4].p1 = elem->corner;
  }
  path = create_standard_path (num_points, points);
  if (path)
    return object_substitute (obj, path);

  /* Empty change */
  return change_list_create ();
}
Example #4
0
/*!
 * \brief Convert _Beziergon to _Path
 * \memberof _Beziergon
 */
static ObjectChange *
_beziergon_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data)
{
  Beziergon *beziergon = (Beziergon *) obj;
  BezierShape *bez = &beziergon->bezier;
  DiaObject *path = NULL;

  if (bez->bezier.num_points > 1)
    path = create_standard_path (bez->bezier.num_points, bez->bezier.points);

  if (path)
    return object_substitute (obj, path);

  /* just an empty change */
  return change_list_create ();
}
Example #5
0
/*!
 * \brief Modification of the objects 'pattern' property
 *
 * @param object object to modify
 * @param pattern the pattern to set
 * @return an object change or NULL
 *
 * If the object does not have a pattern property nothing
 * happens. If there is a pattern property and the passed
 * in pattern is identical an empty change is returned.
 *
 * \memberof _DiaObject
 * \ingroup StdProps
 */
ObjectChange *
dia_object_set_pattern (DiaObject  *object,
			DiaPattern *pattern)
{
  ObjectChange *change;
  GPtrArray *props;
  PatternProperty *pp;
  Property *prop = object_prop_by_name_type (object, "pattern", PROP_TYPE_PATTERN);
  
  if (!prop)
    return NULL;
  pp = (PatternProperty *)prop;
  if (pp->pattern == pattern)
    return change_list_create ();
  if (pp->pattern)
    g_object_unref (pp->pattern);
  pp->pattern = g_object_ref (pattern);
  props = prop_list_from_single (prop);
  change = object_apply_props (object, props);
  prop_list_free (props);
  return change;
}
Example #6
0
/*!
 * \brief Modification of the objects 'pixbuf' property
 *
 * @param object object to modify
 * @param pixbuf the pixbuf to set
 * @return an object change or NULL
 *
 * If the object does not have a pixbuf property nothing
 * happens. If there is a pixbuf property and the passed
 * in pixbuf is identical an empty change is returned.
 *
 * \memberof _DiaObject
 * \ingroup StdProps
 */
ObjectChange *
dia_object_set_pixbuf (DiaObject *object,
		       GdkPixbuf *pixbuf)
{
  ObjectChange *change;
  GPtrArray *props;
  PixbufProperty *pp;
  Property *prop = object_prop_by_name_type (object, "pixbuf", PROP_TYPE_PIXBUF);
  
  if (!prop)
    return NULL;
  pp = (PixbufProperty *)prop;
  if (pp->pixbuf == pixbuf)
    return change_list_create ();
  if (pp->pixbuf)
    g_object_unref (pp->pixbuf);
  pp->pixbuf = g_object_ref (pixbuf);
  props = prop_list_from_single (prop);
  change = object_apply_props (object, props);
  prop_list_free (props);
  return change;
}
Example #7
0
/*!
 * \brief Calback function invoking layout algorithms from Dia's menu
 * \ingroup LayoutPlugin
 */
static ObjectChange *
layout_callback (DiagramData *data,
                 const gchar *filename,
                 guint flags, /* further additions */
                 void *user_data,
		 GraphCreateFunc func)
{
  ObjectChange *changes = NULL;
  GList *nodes = NULL, *edges = NULL, *list;
  const char *algorithm = (const char*)user_data;

  /* from the selection create two lists */
  list = data_get_sorted_selected (data);
  while (list) {
    DiaObject *o = (DiaObject *)list->data;
    if (!maybe_edge (o))
      nodes = g_list_append (nodes, o);
    //FIXME: neither 1 nor num_handles-1 is guaranteed to be the second connection
    // it entirely depends on the objects implementation
    else if (   o->num_handles > 1 && o->handles[0]->connected_to 
             && (o->handles[1]->connected_to || o->handles[o->num_handles-1]->connected_to))
      edges = g_list_append (edges, o);
    list = g_list_next(list);
  }
  if (g_list_length (edges) < 1 || g_list_length (nodes) < 2) {
    message_warning (_("Please select edges and nodes to layout."));
  } else {
    IGraph *g = func ? func () : NULL;

    if (!g)
      message_error (_("Graph creation failed"));
    else {
      std::vector<double> coords;

      /* transfer nodes and edges */
      for (list = nodes; list != NULL; list = g_list_next(list)) {
        DiaObject *o = (DiaObject *)list->data;
        const Rectangle *bbox = dia_object_get_bounding_box (o);
        g->AddNode (bbox->left, bbox->top, bbox->right, bbox->bottom);
      }
      for (list = edges; list != NULL; list = g_list_next(list)) {
        DiaObject *o = (DiaObject *)list->data;
	DiaObject *src = o->handles[0]->connected_to->object;
	// see above: there is no guarantee ...
	DiaObject *dst = o->handles[1]->connected_to ?
	  o->handles[1]->connected_to->object : o->handles[o->num_handles-1]->connected_to->object;

	if (_obj_get_bends (o, coords))
          g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), &coords[0], coords.size());
	else
          g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), NULL, 0);
      }
      IGraph::eResult res;
      if ((res = g->Layout (algorithm)) != IGraph::SUCCESS) {
	const char *sErr;
	switch (res) {
	case IGraph::NO_MODULE : sErr = _("No such module."); break;
	case IGraph::OUT_OF_MEMORY : sErr = _("Out of memory."); break;
	case IGraph::NO_TREE: sErr = _("Not a tree."); break;
	case IGraph::NO_FOREST: sErr = _("Not a forest."); break;
	case IGraph::FAILED_ALGORITHM: sErr = _("Failed algorithm."); break;
	case IGraph::FAILED_PRECONDITION: sErr = _("Failed precondition."); break;
	case IGraph::CRASHED : sErr = _("OGDF crashed."); break;
	default : sErr = _("Unknown reason"); break;
	}
        message_warning (_("Layout '%s' failed.\n%s"), (const char*)user_data, sErr);
      } else {
        changes = change_list_create ();
	/* transfer back information */
	int n;
	for (n = 0, list = nodes; list != NULL; list = g_list_next (list), ++n) {
	  Point pt;
	  if (g->GetNodePosition (n, &pt.x, &pt.y)) {
	    DiaObject *o = (DiaObject *)list->data;
	    GPtrArray *props = g_ptr_array_new ();
	    
	    //FIXME: can't use "obj_pos", it is not read in usual update_data impementations
	    // "elem_corner" will only work for Element derived classes, but that covers most
	    // of the cases here ...
	    prop_list_add_point (props, "elem_corner", &pt);
	    change_list_add (changes, object_apply_props (o, props));
	  }
	}
	// first update to reuse the connected points
	diagram_update_connections_selection(DIA_DIAGRAM (data));
	/* use edge bends, if any */
	int e;
	for (e = 0, list = edges; list != NULL; list = g_list_next (list), ++e) {
          DiaObject *o = (DiaObject *)list->data;
	  // number of bends / 2 is the number of points
	  int n = g->GetEdgeBends (e, NULL, 0);
	  if (n >= 0) { // with 0 it is just a reset of the exisiting line
	    try {
	      coords.resize (n);
	    } catch (std::bad_alloc& ex) {
	      g_warning ("%s", ex.what());
	      continue;
	    }
	    g->GetEdgeBends (e, &coords[0], n);
	    change_list_add (changes, _obj_set_bends (o, coords));
	  }
	}
	/* update view */
	diagram_update_connections_selection(DIA_DIAGRAM (data));
      }
      g->Release ();
    }
  }
  g_list_free (nodes);
  g_list_free (edges);

  return changes;
}
Example #8
0
static int
text_key_event(Focus *focus, 
	       guint keystate, guint keyval, 
	       const gchar *str, int strlen,
               ObjectChange **change)
{
  Text *text;
  int return_val = FALSE;
  int row, i;
  const char *utf;
  gunichar c;

  *change = NULL;
  
  text = focus->text;

  switch(keyval) {
      case GDK_Up:
      case GDK_KP_Up:
        text->cursor_row--;
        if (text->cursor_row<0)
          text->cursor_row = 0;

        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);

        break;
      case GDK_Down:
      case GDK_KP_Down:
        text->cursor_row++;
        if (text->cursor_row >= text->numlines)
          text->cursor_row = text->numlines - 1;

        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
    
        break;
      case GDK_Left:
      case GDK_KP_Left:
        if (keystate & GDK_CONTROL_MASK)
	  text_move_cursor(text, WORD_START);
	else
          text->cursor_pos--;
        if (text->cursor_pos<0)
          text->cursor_pos = 0;
        break;
      case GDK_Right:
      case GDK_KP_Right:
        if (keystate & GDK_CONTROL_MASK)
	  text_move_cursor(text, WORD_END);
	else
          text->cursor_pos++;
        if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
          text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
        break;
      case GDK_Home:
      case GDK_KP_Home:
        text->cursor_pos = 0;
        break;
      case GDK_End:
      case GDK_KP_End:
        text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
        break;
      case GDK_Delete:
      case GDK_KP_Delete:
        return_val = text_delete_key_handler(focus, change);
        break;
      case GDK_BackSpace:
        return_val = TRUE;
        row = text->cursor_row;
        if (text->cursor_pos <= 0) {
          if (row > 0) {
            *change = text_create_change(text, TYPE_JOIN_ROW, 'Q',
                                         text_get_line_strlen(text, row-1), row-1,
					 focus->obj);
          } else {
            return_val = FALSE;
            break;
          }
        } else {
          utf = text_get_line(text, row);
          for (i = 0; i < (text->cursor_pos - 1); i++)
            utf = g_utf8_next_char (utf);
          c = g_utf8_get_char (utf);
          *change = text_create_change (text, TYPE_DELETE_BACKWARD, c,
                                        text->cursor_pos - 1,
                                        text->cursor_row,
					focus->obj);
        }
        text_delete_backward(text);
        break;
      case GDK_Return:
      case GDK_KP_Enter:
        return_val = TRUE;
        *change = text_create_change(text, TYPE_SPLIT_ROW, 'Q',
                                     text->cursor_pos, text->cursor_row,
				     focus->obj);
        text_split_line(text);
        break;
      case GDK_Shift_L:
      case GDK_Shift_R:
      case GDK_Control_L:
      case GDK_Control_R:
      case GDK_Alt_L:
      case GDK_Alt_R:
      case GDK_Meta_L:
      case GDK_Meta_R:
        return_val = FALSE; /* no text change for modifiers */
        break;
      default:
        if (str || (strlen>0)) {
          if (str && *str == '\r')
            break; /* avoid putting junk into our string */
          return_val = TRUE;
	  *change = change_list_create();
          for (utf = str; utf && *utf && strlen > 0 ;
	       utf = g_utf8_next_char (utf), strlen--) {
	    ObjectChange *step;
            c = g_utf8_get_char (utf);
            
            step = text_create_change (text, TYPE_INSERT_CHAR, c,
                                       text->cursor_pos, text->cursor_row,
				       focus->obj);
	    change_list_add (*change, step);
            text_insert_char (text, c);
          }
        }
        break;
  }  
  
  return return_val;
}