[gtk+/extended-layout-jhs: 9/64] Dynamically highlight the currently hovered widget and its guides.



commit 84823caf0ea106a27d49d305b8c98ee940514ecb
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Wed Jun 20 16:36:51 2007 +0000

    Dynamically highlight the currently hovered widget and its guides.
    
    2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* gtk/gtkextendedlayout.h, tests/testextendedlayout.c:
    	Dynamically highlight the currently hovered widget and its guides.
    
    svn path=/branches/extended-layout/; revision=18210

 ChangeLog.gtk-extended-layout |    5 +
 gtk/gtkextendedlayout.h       |   13 ++
 tests/testextendedlayout.c    |  251 ++++++++++++++++++++++++++++++++++------
 3 files changed, 231 insertions(+), 38 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index e5f608c..71fbb0d 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,5 +1,10 @@
 2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
 
+	* gtk/gtkextendedlayout.h, tests/testextendedlayout.c:
+	Dynamically highlight the currently hovered widget and its guides.
+
+2007-06-20  Mathias Hasselmann  <mathias hasselmann gmx de>
+
 	* gtk/gtkbin.c, tests/autotestextendedlayout.c,
 	tests/testextendedlayout.c: Implement GtkExtendedLayout for GtkBin.
 
diff --git a/gtk/gtkextendedlayout.h b/gtk/gtkextendedlayout.h
index 481d8f9..69ca7ab 100644
--- a/gtk/gtkextendedlayout.h
+++ b/gtk/gtkextendedlayout.h
@@ -30,6 +30,19 @@ G_BEGIN_DECLS
 #define GTK_IS_EXTENDED_LAYOUT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_EXTENDED_LAYOUT))
 #define GTK_EXTENDED_LAYOUT_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_EXTENDED_LAYOUT, GtkExtendedLayoutIface))
 
+#define GTK_EXTENDED_LAYOUT_HAS_WIDTH_FOR_HEIGHT(obj) \
+  (gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT ((obj))) & \
+   GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT)
+#define GTK_EXTENDED_LAYOUT_HAS_HEIGHT_FOR_WIDTH(obj) \
+  (gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT ((obj))) & \
+   GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH)
+#define GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE(obj) \
+  (gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT ((obj))) & \
+   GTK_EXTENDED_LAYOUT_NATURAL_SIZE)
+#define GTK_EXTENDED_LAYOUT_HAS_BASELINES(obj) \
+  (gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT ((obj))) & \
+   GTK_EXTENDED_LAYOUT_BASELINES)
+
 typedef struct _GtkExtendedLayout           GtkExtendedLayout;
 typedef struct _GtkExtendedLayoutIface      GtkExtendedLayoutIface;
 typedef enum   _GtkExtendedLayoutFeatures   GtkExtendedLayoutFeatures;
diff --git a/tests/testextendedlayout.c b/tests/testextendedlayout.c
index 4a6645d..7edefaa 100644
--- a/tests/testextendedlayout.c
+++ b/tests/testextendedlayout.c
@@ -76,6 +76,7 @@ struct _Guide
 
 struct _TestCase
 {
+  TestSuite *suite;
   const gchar *name;
   GtkWidget *widget;
   GList *guides;
@@ -90,6 +91,9 @@ struct _TestSuite
   GtkTreeIter parent;
   gint n_test_cases;
   gint level;
+
+  GtkWidget *current;
+  gint timestamp;
 };
 
 static const gchar lorem_ipsum[] =
@@ -100,6 +104,33 @@ static const gchar lorem_ipsum[] =
   "vel, eros. Integer fringilla. Aenean justo ipsum, "        
   "luctus ut, volutpat laoreet, vehicula in, libero.";
 
+static char * mask_xpm[] = 
+  {
+    "20 20 2 1",
+    " 	c #000000",
+    "#	c #FFFFFF",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # ",
+    " # # # # # # # # # #",
+    "# # # # # # # # # # "
+  };
+
 static Guide*
 guide_new (GtkWidget   *widget,
            GuideType    type,
@@ -115,11 +146,13 @@ guide_new (GtkWidget   *widget,
 }
 
 static TestCase*
-test_case_new (const gchar *name,
+test_case_new (TestSuite   *suite,
+               const gchar *name,
                GtkWidget   *widget)
 {
   TestCase* self = g_new0 (TestCase, 1);
 
+  self->suite = suite;
   self->name = name;
   self->widget = widget;
 
@@ -134,6 +167,7 @@ test_case_append_guide (TestCase  *self,
 {
   Guide *guide = guide_new (widget, type, group);
   self->guides = g_list_append (self->guides, guide);
+  g_object_set_data (G_OBJECT (widget), "test-case", self);
 }
 
 static void
@@ -153,11 +187,11 @@ append_natural_size_box (TestCase           *test,
   button = gtk_button_new ();
   gtk_container_add (GTK_CONTAINER (button), label);
   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
-
   test_case_append_guide (test, button, GUIDE_EXTERIOUR_VERTICAL, 0);
 
   button = gtk_button_new_with_label ("The large Button");
   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  test_case_append_guide (test, button, GUIDE_EXTERIOUR_VERTICAL, 1);
 
   label = gtk_label_new (NULL);
   gtk_label_set_markup (GTK_LABEL (label), caption); 
@@ -165,12 +199,13 @@ append_natural_size_box (TestCase           *test,
 
   gtk_box_pack_start (GTK_BOX (test->widget), label, FALSE, TRUE, 0);
   gtk_box_pack_start (GTK_BOX (test->widget), hbox, FALSE, TRUE, 0);
+
 }
 
 static TestCase*
-create_natural_size_test ()
+create_natural_size_test (TestSuite *suite)
 {
-  TestCase *test = test_case_new ("Natural Size",
+  TestCase *test = test_case_new (suite, "Natural Size",
                                   gtk_vbox_new (FALSE, 12));
 
   gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
@@ -192,13 +227,13 @@ create_natural_size_test ()
 }
 
 static TestCase*
-create_height_for_width_test ()
+create_height_for_width_test (TestSuite *suite)
 {
   PangoLayout *layout;
   PangoRectangle log;
   GtkWidget *child;
 
-  TestCase *test = test_case_new ("Height for Width",
+  TestCase *test = test_case_new (suite, "Height for Width",
                                   gtk_hbox_new (FALSE, 12));
 
   gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
@@ -226,13 +261,13 @@ create_height_for_width_test ()
 }
 
 static TestCase*
-create_baseline_test ()
+create_baseline_test (TestSuite *suite)
 {
   GtkWidget *child;
   GtkWidget *view;
   GtkWidget *label;
 
-  TestCase *test = test_case_new ("Baseline Alignment",
+  TestCase *test = test_case_new (suite, "Baseline Alignment",
                                   gtk_table_new (3, 3, FALSE));
 
   gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
@@ -241,6 +276,7 @@ create_baseline_test ()
 
   child = gtk_entry_new ();
   gtk_entry_set_text (GTK_ENTRY (child), "Test...");
+  test_case_append_guide (test, child, GUIDE_BASELINE, 0);
   gtk_table_attach (GTK_TABLE (test->widget), child, 1, 2, 0, 1, 
                     GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
 
@@ -258,6 +294,7 @@ create_baseline_test ()
                     GTK_FILL, GTK_FILL, 0, 0);
 
   child = gtk_font_button_new ();
+  test_case_append_guide (test, child, GUIDE_BASELINE, 1);
   gtk_table_attach (GTK_TABLE (test->widget), child, 1, 2, 1, 2, 
                     GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
 
@@ -299,7 +336,7 @@ create_baseline_test ()
 }
 
 static TestCase*
-create_baseline_test_bin ()
+create_baseline_test_bin (TestSuite *suite)
 {
   const GType types[] = 
     { 
@@ -323,7 +360,7 @@ create_baseline_test_bin ()
 
   int i, j;
 
-  TestCase *test = test_case_new ("Baseline Alignment for GtkBin",
+  TestCase *test = test_case_new (suite, "Baseline Alignment for GtkBin",
                                   gtk_alignment_new (0.5, 0.5, 0.0, 0.0));
 
   table = gtk_table_new (G_N_ELEMENTS (types) - 1, 
@@ -453,7 +490,8 @@ get_baselines_of_text_view (GtkTextView *view, gint **baselines)
 static gint
 get_baselines (GtkWidget *widget, gint **baselines)
 {
-  if (GTK_IS_EXTENDED_LAYOUT (widget))
+  if (GTK_IS_EXTENDED_LAYOUT (widget) &&
+      GTK_EXTENDED_LAYOUT_HAS_BASELINES (widget))
     return gtk_extended_layout_get_baselines (GTK_EXTENDED_LAYOUT (widget), baselines);
   if (GTK_IS_TEXT_VIEW (widget))
     return get_baselines_of_text_view (GTK_TEXT_VIEW (widget), baselines);
@@ -484,7 +522,7 @@ draw_baseline (GdkDrawable  *drawable,
                               GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
 
   gdk_draw_line (drawable, gc, x0, ya, xa - 2, ya);
-  gdk_draw_line (drawable, gc, xe + 2, ya, x0 + cx, ya);
+  gdk_draw_line (drawable, gc, xe + 2, ya, x0 + cx - 1, ya);
 
   gdk_gc_set_line_attributes (gc, 1, GDK_LINE_SOLID,
                               GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
@@ -507,10 +545,10 @@ draw_extends (GdkDrawable  *drawable,
   const gint ya = y0 + extends->y;
   const gint ye = ya + extends->height - 1;
 
-  gdk_draw_line (drawable, gc, xa, y0, xa, y0 + cy);
-  gdk_draw_line (drawable, gc, xe, y0, xe, y0 + cy);
-  gdk_draw_line (drawable, gc, x0, ya, x0 + cx, ya);
-  gdk_draw_line (drawable, gc, x0, ye, x0 + cx, ye);
+  gdk_draw_line (drawable, gc, xa, y0, xa, y0 + cy - 1);
+  gdk_draw_line (drawable, gc, xe, y0, xe, y0 + cy - 1);
+  gdk_draw_line (drawable, gc, x0, ya, x0 + cx - 1, ya);
+  gdk_draw_line (drawable, gc, x0, ye, x0 + cx - 1, ye);
 }
 
 static gint
@@ -646,6 +684,8 @@ draw_guides (gpointer data)
 {
   TestCase *test = data;
   GdkDrawable *drawable;
+  GdkPixmap *tile;
+
   const GList *iter;
 
   gint8 dashes[] = { 3, 3 };
@@ -658,6 +698,11 @@ draw_guides (gpointer data)
   gc = gdk_gc_new_with_values (drawable, &values, 
                                GDK_GC_SUBWINDOW);
 
+  tile = gdk_pixmap_colormap_create_from_xpm_d (drawable, NULL, NULL, 
+                                                NULL, mask_xpm);
+  gdk_gc_set_tile (gc, tile);
+  g_object_unref (tile);
+
   gdk_gc_set_dashes (gc, 1, dashes, 2);
 
   for (iter = test->guides; iter; iter = iter->next)
@@ -668,6 +713,28 @@ draw_guides (gpointer data)
       gint *baselines;
       gint i;
 
+      if (guide->widget == test->suite->current)
+        {
+          if (test->suite->timestamp < 3)
+            {
+              gdk_gc_set_fill (gc, GDK_TILED);
+              gdk_gc_set_function (gc, GDK_OR);
+
+              gdk_draw_rectangle (drawable, gc, TRUE, 
+                                  guide->widget->allocation.x,
+                                  guide->widget->allocation.y,
+                                  guide->widget->allocation.width,
+                                  guide->widget->allocation.height);
+
+              gdk_gc_set_function (gc, GDK_COPY);
+              gdk_gc_set_fill (gc, GDK_SOLID);
+            }
+          else
+            {
+              continue;
+            }
+        }
+
       gdk_color_parse (guide_type_get_color (guide->type), 
                        &values.foreground);
 
@@ -697,7 +764,7 @@ draw_guides (gpointer data)
 }
 
 static gboolean           
-on_expose (GtkWidget      *widget,
+expose_cb (GtkWidget      *widget,
            GdkEventExpose *event,
            gpointer        data)
 {
@@ -715,21 +782,21 @@ on_expose (GtkWidget      *widget,
 }
 
 static void
-on_realize (GtkWidget *widget,
+realize_cb (GtkWidget *widget,
             gpointer   data)
 {
   TestCase *test = data;
 
   if (widget->window != test->widget->window)
     g_signal_connect_after (widget, "expose-event",
-                            G_CALLBACK (on_expose), test);
+                            G_CALLBACK (expose_cb), test);
 }
 
 static void
 attach_sub_windows (GtkWidget *widget,
                     gpointer   data)
 {
-  g_signal_connect_after (widget, "realize", G_CALLBACK (on_realize), data);
+  g_signal_connect_after (widget, "realize", G_CALLBACK (realize_cb), data);
 
   if (GTK_IS_CONTAINER (widget))
     gtk_container_forall (GTK_CONTAINER (widget), attach_sub_windows, data);
@@ -744,9 +811,9 @@ test_suite_append (TestSuite *self,
                             self->n_test_cases++);
 
   g_signal_connect_after (test->widget, "expose-event",
-                          G_CALLBACK (on_expose), test);
+                          G_CALLBACK (expose_cb), test);
   g_signal_connect_after (test->widget, "realize",
-                          G_CALLBACK (on_realize), test);
+                          G_CALLBACK (realize_cb), test);
   g_object_set_data_full (G_OBJECT(test->widget), 
                           "test-case", test, g_free);
 
@@ -764,10 +831,10 @@ test_suite_new ()
 
   self->notebook = gtk_notebook_new ();
 
-  test_suite_append (self, create_natural_size_test ());
-  test_suite_append (self, create_height_for_width_test ());
-  test_suite_append (self, create_baseline_test ());
-  test_suite_append (self, create_baseline_test_bin ());
+  test_suite_append (self, create_natural_size_test (self));
+  test_suite_append (self, create_height_for_width_test (self));
+  test_suite_append (self, create_baseline_test (self));
+  test_suite_append (self, create_baseline_test_bin (self));
 
   self->results = gtk_tree_store_new (COLUNN_COUNT,
                                       G_TYPE_STRING, PANGO_TYPE_WEIGHT,
@@ -963,16 +1030,16 @@ test_suite_run (TestSuite *self,
 }
 
 static void
-test_current (GtkWidget *widget,
-              gpointer  data)
+test_current_cb (GtkWidget *widget,
+                 gpointer  data)
 {
   TestSuite *suite = data;
   test_suite_run (suite, -1);
 }
 
 static void
-test_all (GtkWidget *widget,
-          gpointer  data)
+test_all_cb (GtkWidget *widget,
+             gpointer  data)
 {
   GTimer *timer = g_timer_new ();
   TestSuite *suite = data;
@@ -992,7 +1059,7 @@ test_all (GtkWidget *widget,
             g_usleep (500);
         }
 
-      test_current (widget, suite);
+      test_current_cb (widget, suite);
       g_timer_stop (timer);
     }
 
@@ -1001,10 +1068,10 @@ test_all (GtkWidget *widget,
 }
 
 static void
-switch_page (GtkNotebook     *notebook,
-             GtkNotebookPage *page,
-             gint             index,
-             gpointer         data)
+switch_page_cb (GtkNotebook     *notebook,
+                GtkNotebookPage *page,
+                gint             index,
+                gpointer         data)
 {
   gpointer *bag = data;
   TestSuite *suite = bag[0];
@@ -1046,6 +1113,111 @@ pointer_bag_free (gpointer self)
   g_free (self);
 }
 
+static GtkWidget*
+find_widget_at_position (GtkWidget *widget,
+                         gint       x,
+                         gint       y)
+{
+  if (x < 0 || x >= widget->allocation.width ||
+      y < 0 || y >= widget->allocation.height)
+    return NULL;
+
+  if (GTK_IS_CONTAINER (widget))
+    {
+      GtkWidget *child;
+      GList *children;
+      GList *iter;
+
+      gint rx, ry;
+
+      children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+      for (iter = children; iter; iter = iter->next)
+        {
+          gtk_widget_translate_coordinates (widget, iter->data, x, y, &rx, &ry);
+          child = find_widget_at_position (iter->data, rx, ry);
+
+          if (child)
+            {
+              widget = child;
+              break;
+            }
+        }
+
+      g_list_free (children);
+    }
+
+  return widget;
+}
+
+static gboolean           
+watch_pointer_cb (gpointer data)
+{
+  TestSuite *suite = data;
+  TestCase *test = NULL;
+
+  gboolean dirty;
+  GtkWidget *page;
+  GtkWidget *child;
+  gint i, x, y;
+
+  i = gtk_notebook_get_current_page (GTK_NOTEBOOK (suite->notebook));
+  page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (suite->notebook), i);
+
+  gtk_widget_get_pointer (page, &x, &y);
+  child = find_widget_at_position (page, x, y);
+
+  while (child)
+    {
+      test = g_object_get_data (G_OBJECT(child), "test-case");
+
+      if (test)
+        break;
+
+      child = gtk_widget_get_parent (child);
+    }
+
+  dirty = suite->current && !(suite->timestamp % 3);
+  suite->timestamp = (suite->timestamp + 1) % 6;
+
+  if (test)
+    {
+      g_assert (child);
+      suite->current = child;
+      dirty = TRUE;
+    }
+  else
+    {
+      dirty = (NULL != suite->current);
+      suite->current = NULL;
+    }
+
+  if (dirty)
+    {
+      if (suite->current)
+        {
+          gtk_widget_translate_coordinates (suite->current, page, 0, 0, &x, &y);
+
+          gtk_widget_queue_draw_area (page,
+                                      page->allocation.x,
+                                      page->allocation.y + y,
+                                      page->allocation.width,
+                                      suite->current->allocation.height);
+          gtk_widget_queue_draw_area (page,
+                                      page->allocation.x + x,
+                                      page->allocation.y,
+                                      suite->current->allocation.width,
+                                      page->allocation.height);
+        }
+      else
+        {
+          gtk_widget_queue_draw (page);
+        }
+    }
+
+  return TRUE;
+}
+        
 int
 main (int argc, char *argv[])
 {
@@ -1066,16 +1238,16 @@ main (int argc, char *argv[])
   gtk_container_add (GTK_CONTAINER (align), actions);
 
   button = gtk_button_new_with_mnemonic ("Test _Current Page");
-  g_signal_connect (button, "clicked", G_CALLBACK (test_current), suite);
+  g_signal_connect (button, "clicked", G_CALLBACK (test_current_cb), suite);
   gtk_box_pack_start (GTK_BOX (actions), button, FALSE, TRUE, 0);
 
   g_signal_connect_data (suite->notebook, "switch-page",
-                         G_CALLBACK (switch_page),
+                         G_CALLBACK (switch_page_cb),
                          pointer_bag_new (suite, button, NULL),
                          (GClosureNotify) pointer_bag_free, 0);
 
   button = gtk_button_new_with_mnemonic ("Test _All Pages");
-  g_signal_connect (button, "clicked", G_CALLBACK (test_all), suite);
+  g_signal_connect (button, "clicked", G_CALLBACK (test_all_cb), suite);
   gtk_box_pack_start (GTK_BOX (actions), button, FALSE, TRUE, 0);
 
   vbox = gtk_vbox_new (FALSE, 12);
@@ -1084,7 +1256,10 @@ main (int argc, char *argv[])
   gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, TRUE, 0);
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+  g_timeout_add (200, watch_pointer_cb, suite);
+
   gtk_window_set_title (GTK_WINDOW (window), "Testing GtkExtendedLayout");
   gtk_container_add (GTK_CONTAINER (window), vbox);
   gtk_widget_show_all (window);



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