[dia] [gradient] add pattern standard property



commit cec425ec3bf7a93267ec883bfc0f031e782121b4
Author: Hans Breuer <hans breuer org>
Date:   Tue Dec 24 15:14:14 2013 +0100

    [gradient] add pattern standard property
    
    Step 2 of 7 for gradient support in Dia: glue between pattern object
    and diagram objects, including serialization support.

 lib/Makefile.am     |    4 +
 lib/dia_xml.h       |    3 +
 lib/makefile.msc    |    2 +
 lib/prop_pattern.c  |  259 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/prop_pattern.h  |   43 +++++++++
 lib/properties.c    |    1 +
 lib/properties.h    |    3 +
 lib/propinternals.h |    1 +
 lib/propobject.c    |   37 +++++++
 9 files changed, 353 insertions(+), 0 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 061c030..f06a754 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,6 +16,8 @@ stdprop_files = \
        prop_dict.h \
        prop_matrix.c \
        prop_matrix.h \
+       prop_pattern.c \
+       prop_pattern.h \
        prop_pixbuf.c \
        prop_pixbuf.h \
        prop_inttypes.c \
@@ -132,6 +134,8 @@ libdia_la_SOURCES =  \
                units.h \
                dia_image.c \
                dia_image.h \
+               pattern.c \
+               pattern.h \
                standard-path.c \
                standard-path.h \
                intl.c \
diff --git a/lib/dia_xml.h b/lib/dia_xml.h
index e5ae921..69e861a 100644
--- a/lib/dia_xml.h
+++ b/lib/dia_xml.h
@@ -109,6 +109,9 @@ void data_add_pixbuf (AttributeNode attr, GdkPixbuf *pixbuf);
 DiaMatrix *data_matrix(DataNode data);
 void data_add_matrix(AttributeNode attr, DiaMatrix *matrix);
 
+DiaPattern *data_pattern(DataNode data, DiaContext *ctx);
+void data_add_pattern(AttributeNode attr, DiaPattern *pat);
+
 xmlDocPtr diaXmlParseFile(const char *filename, DiaContext *ctx, gboolean try_harder);
 
 #endif /* DIA_XML_H */
diff --git a/lib/makefile.msc b/lib/makefile.msc
index 0f9a120..158a888 100644
--- a/lib/makefile.msc
+++ b/lib/makefile.msc
@@ -94,6 +94,7 @@ OBJECTS = \
        orth_conn.obj \
        paper.obj \
        parent.obj \
+       pattern.obj \
        persistence.obj \
        plug-ins.obj \
        poly_conn.obj \
@@ -105,6 +106,7 @@ OBJECTS = \
        prop_geomtypes.obj \
        prop_inttypes.obj \
        prop_matrix.obj \
+       prop_pattern.obj \
        prop_pixbuf.obj \
        prop_sdarray.obj \
        prop_sdarray_widget.obj \
diff --git a/lib/prop_pattern.c b/lib/prop_pattern.c
new file mode 100644
index 0000000..e93881a
--- /dev/null
+++ b/lib/prop_pattern.c
@@ -0,0 +1,259 @@
+/* Dia -- a diagram creation/manipulation program -*- c -*-
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * Property system for dia objects/shapes.
+ * Copyright (C) 2000 James Henstridge
+ * Copyright (C) 2001 Cyrille Chepelov
+ *
+ * Copyright (C) 2013 Hans Breuer
+ * Property types for pattern.
+ *
+ * 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.
+ */
+#include <config.h>
+
+#include <gtk/gtk.h>
+#define WIDGET GtkWidget
+#include "widgets.h"
+#include "properties.h"
+#include "propinternals.h"
+#include "pattern.h"
+#include "prop_pattern.h"
+#include "message.h"
+
+static PatternProperty *
+patternprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
+{
+  PatternProperty *prop = g_new0(PatternProperty,1);
+
+  initialize_property(&prop->common, pdesc, reason);
+  /* empty by default */
+  prop->pattern = NULL;
+
+  return prop;
+}
+
+static void
+patternprop_free(PatternProperty *prop) 
+{
+  if (prop->pattern)
+    dia_pattern_release(prop->pattern);
+  g_free(prop);
+} 
+
+static PatternProperty *
+patternprop_copy(PatternProperty *src) 
+{
+  PatternProperty *prop = 
+    (PatternProperty *)src->common.ops->new_prop(src->common.descr,
+                                              src->common.reason);
+  if (src->pattern) /* TODO: rethink on edit - ...copy() ? */
+    prop->pattern = g_object_ref (src->pattern);
+
+  return prop;
+}
+
+DiaPattern *
+data_pattern (DataNode node, DiaContext *ctx)
+{
+  AttributeNode attr;
+  DiaPattern *pattern;
+  DiaPatternType type = DIA_LINEAR_GRADIENT;
+  guint flags = 0;
+  Point p = {0.0, 0.0};
+  real r;
+
+  attr = composite_find_attribute(node, "gradient");
+  if (attr)
+    type = data_int (attribute_first_data(attr), ctx);
+  attr = composite_find_attribute(node, "flags");
+  if (attr)
+    flags = data_int (attribute_first_data(attr), ctx);
+  attr = composite_find_attribute(node, "p1");
+  if (attr)
+    data_point (attribute_first_data(attr), &p, ctx);
+  pattern = dia_pattern_new (type, flags, p.x, p.y);
+  if (pattern) {
+    /* need to apply the radius first as it may limit p2 */
+    attr = composite_find_attribute(node, "r");
+    if (attr) {
+      r = data_real (attribute_first_data(attr), ctx);
+      dia_pattern_set_radius (pattern, r);
+    }
+    attr = composite_find_attribute(node, "p2");
+    if (attr) {
+      data_point (attribute_first_data(attr), &p, ctx);
+      dia_pattern_set_point (pattern, p.x, p.y);
+    }
+    /* restore color-stops */
+    attr =  composite_find_attribute(node, "data");
+    if (attr) {
+      DataNode data = attribute_first_data(attr);
+      guint nvals = attribute_num_data(attr);
+      guint i;
+      real offset = 0.0;
+      Color color = color_black;
+
+      for (i=0; (i < nvals) && data; i++, data = data_next(data)) {
+       attr = composite_find_attribute(data, "offset");
+       if (attr)
+         offset = data_real (attribute_first_data(attr), ctx);
+       attr = composite_find_attribute(data, "color");
+       if (attr)
+         data_color (attribute_first_data(attr), &color, ctx);
+       dia_pattern_add_color (pattern, offset, &color);
+      }
+    }
+  } 
+  return pattern;
+}
+
+static void 
+patternprop_load(PatternProperty *prop, AttributeNode attr, DataNode data, DiaContext *ctx)
+{
+  prop->pattern = data_pattern (data, ctx);
+}
+
+static gboolean
+_data_add_stop (real ofs, const Color *col, gpointer user_data)
+{
+  AttributeNode attr = (AttributeNode)user_data;
+  ObjectNode composite = data_add_composite(attr, "color-stop");
+  
+  data_add_real (composite_add_attribute(composite, "offset"), ofs);
+  data_add_color(composite_add_attribute(composite, "color"), col);
+
+  return TRUE;
+}
+
+void
+data_add_pattern (AttributeNode attr, DiaPattern *pattern)
+{
+  ObjectNode composite = data_add_composite(attr, "pattern");
+  AttributeNode comp_attr = composite_add_attribute (composite, "data");
+  DiaPatternType type;
+  guint flags;
+  Point p1, p2;
+
+  dia_pattern_get_settings (pattern, &type, &flags);
+  data_add_int (composite_add_attribute(composite, "gradient"), type);
+  data_add_int (composite_add_attribute(composite, "flags"), flags);
+  dia_pattern_get_points (pattern, &p1, &p2);
+  data_add_point (composite_add_attribute(composite, "p1"), &p1);
+  data_add_point (composite_add_attribute(composite, "p2"), &p2);
+  if (type == DIA_RADIAL_GRADIENT) {
+    real r;
+    dia_pattern_get_radius (pattern, &r);
+    data_add_real (composite_add_attribute(composite, "r"), r);
+  }
+  dia_pattern_foreach (pattern, _data_add_stop, comp_attr);
+}
+
+static void 
+patternprop_save(PatternProperty *prop, AttributeNode attr) 
+{
+  if (prop->pattern) {
+    data_add_pattern (attr, prop->pattern);
+  }
+}
+
+static void 
+patternprop_get_from_offset(PatternProperty *prop,
+                         void *base, guint offset, guint offset2) 
+{
+  /* before we start editing a simple reference should be enough */
+  DiaPattern *pattern = struct_member(base,offset,DiaPattern *);
+
+  if (pattern)
+    prop->pattern = g_object_ref (pattern);
+  else
+    prop->pattern = NULL;
+}
+
+static void 
+patternprop_set_from_offset(PatternProperty *prop,
+                           void *base, guint offset, guint offset2)
+{
+  DiaPattern *dest = struct_member(base,offset,DiaPattern *);
+  if (dest)
+    g_object_unref (dest);
+  if (prop->pattern)
+    struct_member(base,offset, DiaPattern *) = g_object_ref (prop->pattern);
+  else
+    struct_member(base,offset, DiaPattern *) = NULL;
+}
+
+/* GUI stuff - not yet 
+   - allow to crop
+   - maybe scale
+ */
+static void
+_pattern_toggled(GtkWidget *wid)
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(wid)))
+    gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(wid))), _("Yes"));
+  else
+    gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(wid))), _("No"));
+}
+
+static GtkWidget *
+patternprop_get_widget (PatternProperty *prop, PropDialog *dialog) 
+{ 
+  GtkWidget *ret = gtk_toggle_button_new_with_label(_("No"));
+  g_signal_connect(G_OBJECT(ret), "toggled",
+                   G_CALLBACK (_pattern_toggled), NULL);
+  prophandler_connect(&prop->common, G_OBJECT(ret), "toggled");
+  return ret;
+}
+
+static void
+patternprop_reset_widget(PatternProperty *prop, GtkWidget *widget)
+{
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),prop->pattern != NULL);
+}
+
+static void
+patternprop_set_from_widget(PatternProperty *prop, GtkWidget *widget) 
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget))) {
+    if (!prop->pattern)
+      message_warning (_("Cant create pattern from scratch!"));
+  } else {
+    if (prop->pattern)
+      g_object_unref (prop->pattern);
+    prop->pattern = NULL;
+  }
+}
+
+static const PropertyOps patternprop_ops = {
+  (PropertyType_New) patternprop_new,
+  (PropertyType_Free) patternprop_free,
+  (PropertyType_Copy) patternprop_copy,
+  (PropertyType_Load) patternprop_load,
+  (PropertyType_Save) patternprop_save,
+  (PropertyType_GetWidget) patternprop_get_widget,
+  (PropertyType_ResetWidget) patternprop_reset_widget,
+  (PropertyType_SetFromWidget) patternprop_set_from_widget,
+
+  (PropertyType_CanMerge) noopprop_can_merge,
+  (PropertyType_GetFromOffset) patternprop_get_from_offset,
+  (PropertyType_SetFromOffset) patternprop_set_from_offset
+};
+
+void 
+prop_patterntypes_register(void)
+{
+  prop_type_register(PROP_TYPE_PATTERN, &patternprop_ops);
+}
diff --git a/lib/prop_pattern.h b/lib/prop_pattern.h
new file mode 100644
index 0000000..ceb8e56
--- /dev/null
+++ b/lib/prop_pattern.h
@@ -0,0 +1,43 @@
+/* Dia -- a diagram creation/manipulation program -*- c -*-
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * Property system for dia objects/shapes.
+ * Copyright (C) 2000 James Henstridge
+ * Copyright (C) 2001 Cyrille Chepelov
+ * Major restructuration done in August 2001 by C. Chepelov
+ *
+ * Copyright (C) 2013 Hans Breuer
+ * Property types for pattern (gradient for now).
+ *
+ * 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.
+ */
+#ifndef PROP_PATTERN_H
+#define PROP_PATTERN_H
+
+#include "properties.h"
+#include "dia_xml.h"
+
+/*!
+ * \brief Property for DiaPattern
+ * \extends _Property
+ */
+typedef struct {
+  Property common;
+  DiaPattern *pattern; /* just the reference */
+} PatternProperty;
+
+void prop_patterntypes_register(void);
+
+#endif /* PROP_PATTERN_H */
diff --git a/lib/properties.c b/lib/properties.c
index 3befbac..e70de41 100644
--- a/lib/properties.c
+++ b/lib/properties.c
@@ -51,6 +51,7 @@ stdprops_init(void)
   prop_widgets_register();
   prop_sdarray_register();
   prop_dicttypes_register();
+  prop_patterntypes_register();
   prop_pixbuftypes_register();
   prop_matrix_register();
 }
diff --git a/lib/properties.h b/lib/properties.h
index 84cfb86..b6ee0fe 100644
--- a/lib/properties.h
+++ b/lib/properties.h
@@ -222,6 +222,7 @@ typedef const gchar *PropertyType;
 #define PROP_TYPE_DICT "dict" /* DictProperty */
 #define PROP_TYPE_PIXBUF "pixbuf" /* PixbufProperty */
 #define PROP_TYPE_MATRIX "matrix" /* MatrixProperty */
+#define PROP_TYPE_PATTERN "pattern" /* PatternProperty */
 
 /* **************************************************************** */
 
@@ -558,6 +559,8 @@ Property *object_prop_by_name(DiaObject *obj, const char *name);
 Property *object_prop_by_name_type(DiaObject *obj, const char *name, const char *type);
 /* Set the pixbuf property if there is one */
 ObjectChange *dia_object_set_pixbuf (DiaObject *object, GdkPixbuf *pixbuf);
+/* Set the pattern property if there is one */
+ObjectChange *dia_object_set_pattern (DiaObject *object, DiaPattern *pat);
 /* Set the string property if there is one */
 ObjectChange *dia_object_set_string (DiaObject *object, const char *name, const char *value);
 
diff --git a/lib/propinternals.h b/lib/propinternals.h
index 116c6ac..b45c8bc 100644
--- a/lib/propinternals.h
+++ b/lib/propinternals.h
@@ -86,6 +86,7 @@ void do_get_props_from_offsets(void *base, GPtrArray *props,
 #include "prop_widgets.h"
 #include "prop_sdarray.h"
 #include "prop_dict.h"
+#include "prop_pattern.h"
 #include "prop_pixbuf.h"
 #include "prop_matrix.h"
 
diff --git a/lib/propobject.c b/lib/propobject.c
index d8e368d..6b4b9ee 100644
--- a/lib/propobject.c
+++ b/lib/propobject.c
@@ -440,6 +440,43 @@ dia_object_set_pixbuf (DiaObject *object,
 }
 
 /*!
+ * \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;
+}
+
+/*!
  * \brief Modify the objects string property
  * @param object the object to modify
  * @param name the name of the string property (NULL for any)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]