[Glade-devel] [glade-3] Patch to draw selection handles



--=-p77vWqRf8GGw4ILxtQTv
Content-Type: text/plain
Content-Transfer-Encoding: 7bit


Here's a patch that improves the drawing of the selection rectangles.

It is pretty simple code (unlike in glade-2!).

Whenever a widget gets an expose event, the project queues a
low-priority idle handler (if it isn't already queued).
The idle handler draws the selection rectangles around all the currently
selected widgets, usually in the parent widget's window.

It seems to work well. I'm still testing it though.

Damon


--=-p77vWqRf8GGw4ILxtQTv
Content-Disposition: attachment; filename=glade3.patch
Content-Type: text/x-patch; name=glade3.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: glade-project.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project.h,v
retrieving revision 1.23
diff -u -p -r1.23 glade-project.h
--- glade-project.h     21 Apr 2004 21:03:40 -0000      1.23
+++ glade-project.h     28 Apr 2004 14:09:53 -0000
@@ -48,6 +48,10 @@ struct _GladeProject
        GList *prev_redo_item; /* Points to the item previous to the redo items */
        GHashTable *widget_names_allocator; /* hash table with the used widget names */
        GHashTable *widget_old_names; /* widget -> old name of the widget */
+
+       guint expose_handler_id; /* ID of idle function called to draw the
+                                 * selection rectangless.
+                                 */
 };
 
 struct _GladeProjectClass
@@ -88,6 +92,10 @@ void glade_project_selection_changed (Gl
 
 GList *glade_project_selection_get (GladeProject *project);
 
+
+/* Sets up an idle handler to draw the selection rectangles. This should be
+   called whenever a widget gets an "expose_event" signal. */
+void glade_project_queue_expose_handler (GladeProject *project);
 
 G_END_DECLS
 
Index: glade-project.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project.c,v
retrieving revision 1.46
diff -u -p -r1.46 glade-project.c
--- glade-project.c     21 Apr 2004 21:03:40 -0000      1.46
+++ glade-project.c     28 Apr 2004 14:09:58 -0000
@@ -209,6 +209,11 @@ glade_project_finalize (GObject *object)
        g_hash_table_destroy (project->widget_names_allocator);
        g_hash_table_destroy (project->widget_old_names);
 
+       if (project->expose_handler_id) {
+               g_source_remove (project->expose_handler_id);
+               project->expose_handler_id = 0;
+       }
+
        G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -734,3 +739,36 @@ glade_project_save (GladeProject *projec
        return TRUE;
 }
 
+static gboolean
+glade_project_expose_handler (GladeProject *project)
+{
+       GList *elem;
+       GtkWidget *widget;
+
+       g_print ("In glade_widget_expose_handler\n");
+
+       /* Step through the selected widgets, drawing the selection rectangles
+          around them. */
+       for (elem = project->selection; elem; elem = elem->next) {
+               widget = elem->data;
+
+               g_print ("  Drawing selected widget: %p\n", widget);
+               glade_util_draw_nodes (widget);
+       }
+
+       project->expose_handler_id = 0;
+
+       /* Return FALSE so this handler isn't called again. */
+       return FALSE;
+}
+
+#define GLADE_EXPOSE_HANDLER_PRIORITY  GTK_PRIORITY_DEFAULT + 10
+
+void
+glade_project_queue_expose_handler (GladeProject *project)
+{
+       /* Add an idle handler, if it isn't already registered. */
+       if (project->expose_handler_id == 0) {
+               project->expose_handler_id = g_idle_add_full (GLADE_EXPOSE_HANDLER_PRIORITY, (GSourceFunc) 
glade_project_expose_handler, project, NULL);
+       }
+}
Index: glade-widget.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget.c,v
retrieving revision 1.98
diff -u -p -r1.98 glade-widget.c
--- glade-widget.c      21 Apr 2004 21:03:40 -0000      1.98
+++ glade-widget.c      28 Apr 2004 14:10:07 -0000
@@ -603,6 +603,33 @@ glade_widget_key_press (GtkWidget *event
        return FALSE;
 }
 
+static gboolean
+glade_widget_expose (GtkWidget *widget,
+                    GdkEventExpose *event,
+                    gpointer unused_data)
+{
+       GladeWidget *glade_widget;
+
+       g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+       glade_widget = glade_widget_get_from_gtk_widget (widget);
+
+       /* Note that this may be an internal child widget that doesn't have
+          a corresponding GladeWidget, so we try to find its parent. */
+       if (!glade_widget)
+               glade_widget = glade_util_get_parent (widget);
+
+       if (!glade_widget)
+               return FALSE;
+
+       glade_project_queue_expose_handler (glade_widget->project);
+
+       /* FIXME: For GtkFixed & GtkLayout we can draw the grid here.
+          (But don't draw it for internal children). */
+
+       return FALSE;
+}
+
 static void
 glade_widget_apply_properties (GladeWidget *glade_widget)
 {
@@ -655,6 +682,23 @@ glade_widget_retrieve_properties (GladeW
        g_object_thaw_notify (G_OBJECT (widget));
 }
 
+/* Connects a signal handler to the 'expose_event' signal for a widget and
+   all its children recursively. We need this to draw the selection
+   rectangles. */
+static void
+glade_widget_connect_to_expose_event (GtkWidget *widget_gtk, gpointer data)
+{
+       g_signal_connect (G_OBJECT (widget_gtk), "expose_event",
+                         G_CALLBACK (glade_widget_expose), NULL);
+
+       /* We also need to get expose events for any children. */
+       if (GTK_IS_CONTAINER (widget_gtk)) {
+               gtk_container_forall (GTK_CONTAINER (widget_gtk), 
+                                     glade_widget_connect_to_expose_event,
+                                     NULL);
+       }
+}
+
 void
 glade_widget_set_widget (GladeWidget *glade_widget, GtkWidget *widget_gtk)
 {
@@ -688,6 +732,8 @@ glade_widget_set_widget (GladeWidget *gl
                          G_CALLBACK (glade_widget_button_press), NULL);
        g_signal_connect (G_OBJECT (widget_gtk), "key_press_event",
                          G_CALLBACK (glade_widget_key_press), NULL);
+
+       glade_widget_connect_to_expose_event (widget_gtk, NULL);
 
        if (glade_widget->internal == NULL)
        {
Index: glade-utils.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-utils.h,v
retrieving revision 1.20
diff -u -p -r1.20 glade-utils.h
--- glade-utils.h       21 Apr 2004 21:03:40 -0000      1.20
+++ glade-utils.h       28 Apr 2004 14:10:13 -0000
@@ -32,6 +32,7 @@ void          glade_util_delete_selection (Glade
 void           glade_util_add_nodes (GtkWidget *widget);
 void           glade_util_remove_nodes (GtkWidget *widget);
 gboolean       glade_util_has_nodes (GtkWidget *widget);
+void           glade_util_draw_nodes (GtkWidget *widget);
 
 GladeWidget    *glade_util_get_parent (GtkWidget *w);
 GList           *glade_util_container_get_all_children (GtkContainer *container);
Index: glade-utils.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-utils.c,v
retrieving revision 1.23
diff -u -p -r1.23 glade-utils.c
--- glade-utils.c       21 Apr 2004 21:03:40 -0000      1.23
+++ glade-utils.c       28 Apr 2004 14:10:18 -0000
@@ -35,7 +35,7 @@
 #include "glade-property.h"
 #include "glade-property-class.h"
 
-#define GLADE_UTIL_ID_EXPOSE "glade_util_id_expose"
+#define GLADE_UTIL_HAS_NODES "glade_util_has_nodes"
 #define GLADE_UTIL_SELECTION_NODE_SIZE 7
 
 void
@@ -372,16 +372,53 @@ glade_util_duplicate_underscores (const 
        return underscored_name;
 }
 
-static gboolean
-glade_util_draw_nodes (GtkWidget *widget, GdkEventExpose *expose, gpointer unused)
+/* This returns the window to draw on for a given widget.
+   Usually we draw on the widget's parent's window, since we know that will
+   cover the widget's entire allocated area. But if the widget is a toplevel,
+   we draw on its own window, as it doesn't have a parent. */
+static GdkWindow*
+glade_util_get_window_to_draw_on (GtkWidget *widget)
+{
+       GtkWidget *parent;
+
+       parent = widget->parent;
+
+#ifdef USE_GNOME
+       /* BonoboDockItem widgets use a different window when floating.
+          FIXME: I've left this here so we remember to add it when we add
+          GNOME support. */
+       if (BONOBO_IS_DOCK_ITEM (widget)
+           && BONOBO_DOCK_ITEM (widget)->is_floating) {
+               return BONOBO_DOCK_ITEM (widget)->float_window;
+       }
+
+       if (parent && BONOBO_IS_DOCK_ITEM (parent)
+           && BONOBO_DOCK_ITEM (parent)->is_floating) {
+               return BONOBO_DOCK_ITEM (parent)->float_window;
+       }
+#endif
+
+       if (parent)
+               return parent->window;
+
+       return widget->window;
+}
+
+void
+glade_util_draw_nodes (GtkWidget *widget)
 {
        GdkGC *gc = widget->style->black_gc;
        gint x, y;
        gint width, height;
-       GdkWindow *window = expose->window;
+       GdkWindow *window;
        gpointer data;
 
-       gdk_window_get_user_data(window, &data);
+       /* Check widget is drawable. */
+       if (!GTK_WIDGET_DRAWABLE (widget))
+               return;
+
+       window = glade_util_get_window_to_draw_on (widget);
+       gdk_window_get_user_data (window, &data);
        gtk_widget_translate_coordinates (widget, GTK_WIDGET (data), 0, 0, &x, &y);
        width = widget->allocation.width;
        height = widget->allocation.height;
@@ -407,38 +444,30 @@ glade_util_draw_nodes (GtkWidget *widget
        gdk_draw_rectangle (window, gc, FALSE, x, y, width - 1, height - 1);
 
        gdk_gc_set_subwindow (gc, GDK_CLIP_BY_CHILDREN);
-       g_debug (("(%d, %d, %d, %d)\n", expose->area.x, expose->area.y, expose->area.width, 
expose->area.height));
-
-       return FALSE;
 }
 
 void
 glade_util_add_nodes (GtkWidget *widget)
 {
-       gint id;
-
-       id = g_signal_connect_after (G_OBJECT (widget), "expose_event",
-                                    G_CALLBACK (glade_util_draw_nodes), NULL);
-       g_object_set_data (G_OBJECT (widget), GLADE_UTIL_ID_EXPOSE, GINT_TO_POINTER (id));
+       g_object_set_data (G_OBJECT (widget), GLADE_UTIL_HAS_NODES,
+                          GINT_TO_POINTER (1));
        gtk_widget_queue_draw (widget);
 }
 
 void
 glade_util_remove_nodes (GtkWidget *widget)
 {
-       gint id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), GLADE_UTIL_ID_EXPOSE));
-
-       g_return_if_fail (id != 0);
+       g_object_set_data (G_OBJECT (widget), GLADE_UTIL_HAS_NODES, 0);
 
-       g_signal_handler_disconnect (G_OBJECT (widget), id);
-       g_object_set_data (G_OBJECT (widget), GLADE_UTIL_ID_EXPOSE, 0);
-       gtk_widget_queue_draw (widget);
+       /* We redraw the parent, since the selection rectangle may not be
+          cleared if we just redraw the widget itself. */
+       gtk_widget_queue_draw (widget->parent ? widget->parent : widget);
 }
 
 gboolean
 glade_util_has_nodes (GtkWidget *widget)
 {
-       return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), GLADE_UTIL_ID_EXPOSE)) != 0;
+       return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), GLADE_UTIL_HAS_NODES)) != 0;
 }
 
 void
Index: glade-placeholder.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-placeholder.c,v
retrieving revision 1.53
diff -u -p -r1.53 glade-placeholder.c
--- glade-placeholder.c 21 Apr 2004 21:03:40 -0000      1.53
+++ glade-placeholder.c 28 Apr 2004 14:10:29 -0000
@@ -232,9 +232,19 @@ glade_placeholder_send_configure (GladeP
        gdk_event_free (event);
 }
 
+static GladeProject*
+glade_placeholder_get_project (GladePlaceholder *placeholder)
+{
+       GladeWidget *parent;
+
+       parent = glade_util_get_parent (GTK_WIDGET (placeholder));
+       return parent->project;
+}
+
 static gboolean
 glade_placeholder_expose (GtkWidget *widget, GdkEventExpose *event)
 {
+       GladeProject *project;
        GdkGC *light_gc;
        GdkGC *dark_gc;
        gint w, h;
@@ -250,6 +260,9 @@ glade_placeholder_expose (GtkWidget *wid
        gdk_draw_line (event->window, dark_gc, 0, h - 1, w - 1, h - 1);
        gdk_draw_line (event->window, dark_gc, w - 1, 0, w - 1, h - 1);
 
+       project = glade_placeholder_get_project (GLADE_PLACEHOLDER (widget));
+       glade_project_queue_expose_handler (project);
+
        return FALSE;
 }
 
@@ -294,8 +307,10 @@ glade_placeholder_button_press (GtkWidge
                }
                else
                {
-                       GladeWidget *parent = glade_util_get_parent (GTK_WIDGET (placeholder));
-                       glade_project_selection_set (parent->project, GTK_WIDGET (placeholder), TRUE);
+                       GladeProject *project;
+
+                       project = glade_placeholder_get_project (placeholder);
+                       glade_project_selection_set (project, GTK_WIDGET (placeholder), TRUE);
                }
        }
        else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)

--=-p77vWqRf8GGw4ILxtQTv--





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