[Glade-devel] [glade-3] Patch to draw selection handles
- From: damon karuna uklinux net (Damon Chaplin)
- Subject: [Glade-devel] [glade-3] Patch to draw selection handles
- Date: 28 Apr 2004 15:20:22 +0100
--=-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]