]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkstatusbar.c
Show the grip_window if necessary.
[~andy/gtk] / gtk / gtkstatusbar.c
index a032eb7fadff31e77a24a75cecab56a17239d41d..c7cb374a8a07a23f902c00d28dcde5ca7708180d 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
+#include "gtkalias.h"
 #include "gtkframe.h"
 #include "gtklabel.h"
-#include "gtksignal.h"
+#include "gtkmarshalers.h"
 #include "gtkstatusbar.h"
 #include "gtkwindow.h"
 #include "gtkintl.h"
@@ -48,52 +50,71 @@ enum
   SIGNAL_LAST
 };
 
-static void     gtk_statusbar_class_init     (GtkStatusbarClass *class);
-static void     gtk_statusbar_init           (GtkStatusbar      *statusbar);
-static void     gtk_statusbar_destroy        (GtkObject         *object);
-static void     gtk_statusbar_update         (GtkStatusbar      *statusbar,
-                                             guint              context_id,
-                                             const gchar       *text);
-static void     gtk_statusbar_size_allocate  (GtkWidget         *widget,
-                                             GtkAllocation     *allocation);
-static void     gtk_statusbar_realize        (GtkWidget         *widget);
-static void     gtk_statusbar_unrealize      (GtkWidget         *widget);
-static void     gtk_statusbar_map            (GtkWidget         *widget);
-static void     gtk_statusbar_unmap          (GtkWidget         *widget);
-static gboolean gtk_statusbar_button_press   (GtkWidget         *widget,
-                                             GdkEventButton    *event);
-static gboolean gtk_statusbar_expose_event   (GtkWidget         *widget,
-                                             GdkEventExpose    *event);
-static void     gtk_statusbar_size_request   (GtkWidget         *widget,
-                                              GtkRequisition    *requisition);
-static void     gtk_statusbar_size_allocate  (GtkWidget         *widget,
-                                              GtkAllocation     *allocation);
-static void     gtk_statusbar_create_window  (GtkStatusbar      *statusbar);
-static void     gtk_statusbar_destroy_window (GtkStatusbar      *statusbar);
+enum 
+{
+  PROP_ZERO,
+  PROP_HAS_RESIZE_GRIP
+};
+
+static void     gtk_statusbar_class_init        (GtkStatusbarClass *class);
+static void     gtk_statusbar_init              (GtkStatusbar      *statusbar);
+static void     gtk_statusbar_destroy           (GtkObject         *object);
+static void     gtk_statusbar_update            (GtkStatusbar      *statusbar,
+                                                guint              context_id,
+                                                const gchar       *text);
+static void     gtk_statusbar_size_allocate     (GtkWidget         *widget,
+                                                GtkAllocation     *allocation);
+static void     gtk_statusbar_realize           (GtkWidget         *widget);
+static void     gtk_statusbar_unrealize         (GtkWidget         *widget);
+static void     gtk_statusbar_map               (GtkWidget         *widget);
+static void     gtk_statusbar_unmap             (GtkWidget         *widget);
+static gboolean gtk_statusbar_button_press      (GtkWidget         *widget,
+                                                GdkEventButton    *event);
+static gboolean gtk_statusbar_expose_event      (GtkWidget         *widget,
+                                                GdkEventExpose    *event);
+static void     gtk_statusbar_size_request      (GtkWidget         *widget,
+                                                GtkRequisition    *requisition);
+static void     gtk_statusbar_size_allocate     (GtkWidget         *widget,
+                                                GtkAllocation     *allocation);
+static void     gtk_statusbar_direction_changed (GtkWidget         *widget,
+                                                GtkTextDirection   prev_dir);
+static void     gtk_statusbar_create_window     (GtkStatusbar      *statusbar);
+static void     gtk_statusbar_destroy_window    (GtkStatusbar      *statusbar);
+static void     gtk_statusbar_get_property      (GObject           *object,
+                                                guint              prop_id,
+                                                GValue            *value,
+                                                GParamSpec        *pspec);
+static void     gtk_statusbar_set_property      (GObject           *object,
+                                                guint              prop_id,
+                                                const GValue      *value,
+                                                GParamSpec        *pspec);
+
 
 static GtkContainerClass *parent_class;
 static guint              statusbar_signals[SIGNAL_LAST] = { 0 };
 
-GtkType      
+GType      
 gtk_statusbar_get_type (void)
 {
-  static GtkType statusbar_type = 0;
+  static GType statusbar_type = 0;
 
   if (!statusbar_type)
     {
-      static const GtkTypeInfo statusbar_info =
+      static const GTypeInfo statusbar_info =
       {
-        "GtkStatusbar",
-        sizeof (GtkStatusbar),
         sizeof (GtkStatusbarClass),
-        (GtkClassInitFunc) gtk_statusbar_class_init,
-        (GtkObjectInitFunc) gtk_statusbar_init,
-        /* reserved_1 */ NULL,
-        /* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+        (GClassInitFunc) gtk_statusbar_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+        sizeof (GtkStatusbar),
+       0,              /* n_preallocs */
+        (GInstanceInitFunc) gtk_statusbar_init,
       };
 
-      statusbar_type = gtk_type_unique (GTK_TYPE_HBOX, &statusbar_info);
+      statusbar_type = g_type_register_static (GTK_TYPE_HBOX, "GtkStatusbar",
+                                              &statusbar_info, 0);
     }
 
   return statusbar_type;
@@ -102,16 +123,21 @@ gtk_statusbar_get_type (void)
 static void
 gtk_statusbar_class_init (GtkStatusbarClass *class)
 {
+  GObjectClass *gobject_class;
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
 
+  gobject_class = (GObjectClass *) class;
   object_class = (GtkObjectClass *) class;
   widget_class = (GtkWidgetClass *) class;
   container_class = (GtkContainerClass *) class;
 
-  parent_class = gtk_type_class (GTK_TYPE_HBOX);
+  parent_class = g_type_class_peek_parent (class);
   
+  gobject_class->set_property = gtk_statusbar_set_property;
+  gobject_class->get_property = gtk_statusbar_get_property;
+
   object_class->destroy = gtk_statusbar_destroy;
 
   widget_class->realize = gtk_statusbar_realize;
@@ -124,8 +150,10 @@ gtk_statusbar_class_init (GtkStatusbarClass *class)
 
   widget_class->size_request = gtk_statusbar_size_request;
   widget_class->size_allocate = gtk_statusbar_size_allocate;
+
+  widget_class->direction_changed = gtk_statusbar_direction_changed;
   
-  class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusBar messages mem chunk",
+  class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusbar messages mem chunk",
                                               sizeof (GtkStatusbarMsg),
                                               sizeof (GtkStatusbarMsg) * 64,
                                               G_ALLOC_AND_FREE);
@@ -133,29 +161,45 @@ gtk_statusbar_class_init (GtkStatusbarClass *class)
   class->text_pushed = gtk_statusbar_update;
   class->text_popped = gtk_statusbar_update;
   
+  /**
+   * GtkStatusbar:has-resize-grip:
+   *
+   * Whether the statusbar has a grip for resizing the toplevel window.
+   *
+   * Since: 2.4
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_HAS_RESIZE_GRIP,
+                                  g_param_spec_boolean ("has_resize_grip",
+                                                        P_("Has Resize Grip"),
+                                                        P_("Whether the statusbar has a grip for resizing the toplevel"),
+                                                        TRUE,
+                                                        G_PARAM_READWRITE));
   statusbar_signals[SIGNAL_TEXT_PUSHED] =
-    gtk_signal_new ("text_pushed",
-                   GTK_RUN_LAST,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_pushed),
-                   gtk_marshal_VOID__UINT_STRING,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_UINT,
-                   GTK_TYPE_STRING);
+    g_signal_new ("text_pushed",
+                 G_OBJECT_CLASS_TYPE (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkStatusbarClass, text_pushed),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__UINT_STRING,
+                 G_TYPE_NONE, 2,
+                 G_TYPE_UINT,
+                 G_TYPE_STRING);
   statusbar_signals[SIGNAL_TEXT_POPPED] =
-    gtk_signal_new ("text_popped",
-                   GTK_RUN_LAST,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkStatusbarClass, text_popped),
-                   gtk_marshal_VOID__UINT_STRING,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_UINT,
-                   GTK_TYPE_STRING);
+    g_signal_new ("text_popped",
+                 G_OBJECT_CLASS_TYPE (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkStatusbarClass, text_popped),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__UINT_STRING,
+                 G_TYPE_NONE, 2,
+                 G_TYPE_UINT,
+                 G_TYPE_STRING);
 
   gtk_widget_class_install_style_property (widget_class,
                                            g_param_spec_enum ("shadow_type",
-                                                              _("Shadow type"),
-                                                              _("Style of bevel around the statusbar text"),
+                                                              P_("Shadow type"),
+                                                              P_("Style of bevel around the statusbar text"),
                                                               GTK_TYPE_SHADOW_TYPE,
                                                               GTK_SHADOW_IN,
                                                               G_PARAM_READABLE));
@@ -182,11 +226,12 @@ gtk_statusbar_init (GtkStatusbar *statusbar)
   gtk_widget_show (statusbar->frame);
 
   statusbar->label = gtk_label_new ("");
-  gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.0);
+  gtk_label_set_single_line_mode (GTK_LABEL (statusbar->label), TRUE);
+  gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.5);
   /* don't expand the size request for the label; if we
    * do that then toplevels weirdly resize
    */
-  gtk_widget_set_usize (statusbar->label, 1, -1);
+  gtk_widget_set_size_request (statusbar->label, 1, -1);
   gtk_container_add (GTK_CONTAINER (statusbar->frame), statusbar->label);
   gtk_widget_show (statusbar->label);
 
@@ -199,7 +244,7 @@ gtk_statusbar_init (GtkStatusbar *statusbar)
 GtkWidget* 
 gtk_statusbar_new (void)
 {
-  return gtk_type_new (GTK_TYPE_STATUSBAR);
+  return g_object_new (GTK_TYPE_STATUSBAR, NULL);
 }
 
 static void
@@ -207,7 +252,6 @@ gtk_statusbar_update (GtkStatusbar *statusbar,
                      guint         context_id,
                      const gchar  *text)
 {
-  g_return_if_fail (statusbar != NULL);
   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
 
   if (!text)
@@ -223,19 +267,18 @@ gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
   gchar *string;
   guint *id;
   
-  g_return_val_if_fail (statusbar != NULL, 0);
   g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
   g_return_val_if_fail (context_description != NULL, 0);
 
   /* we need to preserve namespaces on object datas */
   string = g_strconcat ("gtk-status-bar-context:", context_description, NULL);
 
-  id = gtk_object_get_data (GTK_OBJECT (statusbar), string);
+  id = g_object_get_data (G_OBJECT (statusbar), string);
   if (!id)
     {
       id = g_new (guint, 1);
       *id = statusbar->seq_context_id++;
-      gtk_object_set_data_full (GTK_OBJECT (statusbar), string, id, (GtkDestroyNotify) g_free);
+      g_object_set_data_full (G_OBJECT (statusbar), string, id, g_free);
       statusbar->keys = g_slist_prepend (statusbar->keys, string);
     }
   else
@@ -252,7 +295,6 @@ gtk_statusbar_push (GtkStatusbar *statusbar,
   GtkStatusbarMsg *msg;
   GtkStatusbarClass *class;
 
-  g_return_val_if_fail (statusbar != NULL, 0);
   g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
   g_return_val_if_fail (text != NULL, 0);
 
@@ -264,10 +306,11 @@ gtk_statusbar_push (GtkStatusbar *statusbar,
 
   statusbar->messages = g_slist_prepend (statusbar->messages, msg);
 
-  gtk_signal_emit (GTK_OBJECT (statusbar),
-                  statusbar_signals[SIGNAL_TEXT_PUSHED],
-                  msg->context_id,
-                  msg->text);
+  g_signal_emit (statusbar,
+                statusbar_signals[SIGNAL_TEXT_PUSHED],
+                0,
+                msg->context_id,
+                msg->text);
 
   return msg->message_id;
 }
@@ -278,7 +321,6 @@ gtk_statusbar_pop (GtkStatusbar *statusbar,
 {
   GtkStatusbarMsg *msg;
 
-  g_return_if_fail (statusbar != NULL);
   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
 
   if (statusbar->messages)
@@ -307,10 +349,11 @@ gtk_statusbar_pop (GtkStatusbar *statusbar,
 
   msg = statusbar->messages ? statusbar->messages->data : NULL;
 
-  gtk_signal_emit (GTK_OBJECT (statusbar),
-                  statusbar_signals[SIGNAL_TEXT_POPPED],
-                  (guint) (msg ? msg->context_id : 0),
-                  msg ? msg->text : NULL);
+  g_signal_emit (statusbar,
+                statusbar_signals[SIGNAL_TEXT_POPPED],
+                0,
+                (guint) (msg ? msg->context_id : 0),
+                msg ? msg->text : NULL);
 }
 
 void
@@ -320,7 +363,6 @@ gtk_statusbar_remove (GtkStatusbar *statusbar,
 {
   GtkStatusbarMsg *msg;
 
-  g_return_if_fail (statusbar != NULL);
   g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
   g_return_if_fail (message_id > 0);
 
@@ -374,10 +416,15 @@ gtk_statusbar_set_has_resize_grip (GtkStatusbar *statusbar,
       if (GTK_WIDGET_REALIZED (statusbar))
         {
           if (statusbar->has_resize_grip && statusbar->grip_window == NULL)
-            gtk_statusbar_create_window (statusbar);
+           {
+             gtk_statusbar_create_window (statusbar);
+             gdk_window_show (statusbar->grip_window);
+           }
           else if (!statusbar->has_resize_grip && statusbar->grip_window != NULL)
             gtk_statusbar_destroy_window (statusbar);
         }
+
+      g_object_notify (G_OBJECT (statusbar), "has_resize_grip");
     }
 }
 
@@ -396,7 +443,6 @@ gtk_statusbar_destroy (GtkObject *object)
   GtkStatusbarClass *class;
   GSList *list;
 
-  g_return_if_fail (object != NULL);
   g_return_if_fail (GTK_IS_STATUSBAR (object));
 
   statusbar = GTK_STATUSBAR (object);
@@ -421,6 +467,55 @@ gtk_statusbar_destroy (GtkObject *object)
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
+static void
+gtk_statusbar_set_property (GObject      *object, 
+                           guint         prop_id, 
+                           const GValue *value, 
+                           GParamSpec   *pspec)
+{
+  GtkStatusbar *statusbar = GTK_STATUSBAR (object);
+
+  switch (prop_id) 
+    {
+    case PROP_HAS_RESIZE_GRIP:
+      gtk_statusbar_set_has_resize_grip (statusbar, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_statusbar_get_property (GObject    *object, 
+                           guint       prop_id, 
+                           GValue     *value, 
+                           GParamSpec *pspec)
+{
+  GtkStatusbar *statusbar = GTK_STATUSBAR (object);
+       
+  switch (prop_id) 
+    {
+    case PROP_HAS_RESIZE_GRIP:
+      g_value_set_boolean (value, statusbar->has_resize_grip);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static GdkWindowEdge
+get_grip_edge (GtkStatusbar *statusbar)
+{
+  GtkWidget *widget = GTK_WIDGET (statusbar);
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+    return GDK_WINDOW_EDGE_SOUTH_EAST; 
+  else
+    return GDK_WINDOW_EDGE_SOUTH_WEST; 
+}
+
 static void
 get_grip_rect (GtkStatusbar *statusbar,
                GdkRectangle *rect)
@@ -434,16 +529,41 @@ get_grip_rect (GtkStatusbar *statusbar,
   w = 18;
   h = 18;
 
-  if (w > (widget->allocation.width))
+  if (w > widget->allocation.width)
     w = widget->allocation.width;
 
-  if (h > (widget->allocation.height - widget->style->ythickness))
+  if (h > widget->allocation.height - widget->style->ythickness)
     h = widget->allocation.height - widget->style->ythickness;
   
-  rect->x = widget->allocation.x + widget->allocation.width - w;
-  rect->y = widget->allocation.y + widget->allocation.height - h;
   rect->width = w;
   rect->height = h;
+  rect->y = widget->allocation.y + widget->allocation.height - h;
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
+    rect->x = widget->allocation.x + widget->allocation.width - w;
+  else 
+    rect->x = widget->allocation.x + widget->style->xthickness;
+}
+
+static void
+set_grip_cursor (GtkStatusbar *statusbar)
+{
+  if (statusbar->has_resize_grip)
+    {
+      GtkWidget *widget = GTK_WIDGET (statusbar);
+      GdkDisplay *display = gtk_widget_get_display (widget);
+      GdkCursorType cursor_type;
+      GdkCursor *cursor;
+      
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+       cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+      else
+       cursor_type = GDK_BOTTOM_LEFT_CORNER;
+
+      cursor = gdk_cursor_new_for_display (display, cursor_type);
+      gdk_window_set_cursor (statusbar->grip_window, cursor);
+      gdk_cursor_unref (cursor);
+    }
 }
 
 static void
@@ -474,7 +594,19 @@ gtk_statusbar_create_window (GtkStatusbar *statusbar)
 
   statusbar->grip_window = gdk_window_new (widget->window,
                                            &attributes, attributes_mask);
+
   gdk_window_set_user_data (statusbar->grip_window, widget);
+
+  set_grip_cursor (statusbar);
+}
+
+static void
+gtk_statusbar_direction_changed (GtkWidget        *widget,
+                                GtkTextDirection  prev_dir)
+{
+  GtkStatusbar *statusbar = GTK_STATUSBAR (widget);
+
+  set_grip_cursor (statusbar);
 }
 
 static void
@@ -543,10 +675,12 @@ gtk_statusbar_button_press (GtkWidget      *widget,
 {
   GtkStatusbar *statusbar;
   GtkWidget *ancestor;
+  GdkWindowEdge edge;
   
   statusbar = GTK_STATUSBAR (widget);
   
-  if (!statusbar->has_resize_grip)
+  if (!statusbar->has_resize_grip ||
+    event->type != GDK_BUTTON_PRESS)
     return FALSE;
   
   ancestor = gtk_widget_get_toplevel (widget);
@@ -554,9 +688,11 @@ gtk_statusbar_button_press (GtkWidget      *widget,
   if (!GTK_IS_WINDOW (ancestor))
     return FALSE;
 
+  edge = get_grip_edge (statusbar);
+
   if (event->button == 1)
     gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
-                                  GDK_WINDOW_EDGE_SOUTH_EAST,
+                                  edge,
                                   event->button,
                                   event->x_root, event->y_root,
                                   event->time);
@@ -584,6 +720,10 @@ gtk_statusbar_expose_event (GtkWidget      *widget,
 
   if (statusbar->has_resize_grip)
     {
+      GdkWindowEdge edge;
+      
+      edge = get_grip_edge (statusbar);
+
       get_grip_rect (statusbar, &rect);
 
       gtk_paint_resize_grip (widget->style,
@@ -592,7 +732,7 @@ gtk_statusbar_expose_event (GtkWidget      *widget,
                              NULL,
                              widget,
                              "statusbar",
-                             GDK_WINDOW_EDGE_SOUTH_EAST,
+                             edge,
                              rect.x, rect.y,
                              /* don't draw grip over the frame, though you
                               * can click on the frame.
@@ -617,19 +757,6 @@ gtk_statusbar_size_request   (GtkWidget      *widget,
   gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), shadow_type);
   
   GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
-
-  if (statusbar->has_resize_grip)
-    {
-      GdkRectangle rect;
-
-      /* x, y in the grip rect depend on size allocation, but
-       * w, h do not so this is OK
-       */
-      get_grip_rect (statusbar, &rect);
-      
-      requisition->width += rect.width;
-      requisition->height = MAX (requisition->height, rect.height);
-    }
 }
 
 static void
@@ -640,31 +767,18 @@ gtk_statusbar_size_allocate  (GtkWidget     *widget,
   
   statusbar = GTK_STATUSBAR (widget);
 
-  if (statusbar->has_resize_grip)
+  /* chain up normally */
+  GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+
+  if (statusbar->has_resize_grip && statusbar->grip_window)
     {
       GdkRectangle rect;
-      GtkAllocation hbox_allocation;
-      GtkRequisition saved_req;
       
-      widget->allocation = *allocation; /* get_grip_rect needs this info */
       get_grip_rect (statusbar, &rect);
   
-      if (statusbar->grip_window)
         gdk_window_move_resize (statusbar->grip_window,
                                 rect.x, rect.y,
                                 rect.width, rect.height);
-      
-      /* enter the bad hack zone */      
-      saved_req = widget->requisition;
-      widget->requisition.width -= rect.width; /* HBox::size_allocate needs this */
-      if (widget->requisition.width < 0)
-        widget->requisition.width = 0;
-      GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
-      widget->requisition = saved_req;
-    }
-  else
-    {
-      /* chain up normally */
-      GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
     }
 }
+