]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktearoffmenuitem.c
Handle float and uint style properties
[~andy/gtk] / gtk / gtktearoffmenuitem.c
index 30c81873e102e92ecd50e179d70fb1cb409c8539..680b0851b37738c2263a0d3880c36f02e79daa6a 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <config.h>
+#include "config.h"
 
-#include "gtkalias.h"
 #include "gtkmenu.h"
 #include "gtktearoffmenuitem.h"
+#include "gtkintl.h"
 
 #define ARROW_SIZE 10
 #define TEAR_LENGTH 5
 #define BORDER_SPACING  3
 
-static void gtk_tearoff_menu_item_class_init (GtkTearoffMenuItemClass *klass);
-static void gtk_tearoff_menu_item_init       (GtkTearoffMenuItem      *tearoff_menu_item);
-static void gtk_tearoff_menu_item_size_request (GtkWidget             *widget,
-                                               GtkRequisition        *requisition);
-static gint gtk_tearoff_menu_item_expose     (GtkWidget             *widget,
-                                             GdkEventExpose        *event);
-static void gtk_tearoff_menu_item_activate   (GtkMenuItem           *menu_item);
-static void gtk_tearoff_menu_item_parent_set (GtkWidget             *widget,
-                                             GtkWidget             *previous);
-
-GType
-gtk_tearoff_menu_item_get_type (void)
+struct _GtkTearoffMenuItemPrivate
 {
-  static GType tearoff_menu_item_type = 0;
-
-  if (!tearoff_menu_item_type)
-    {
-      static const GTypeInfo tearoff_menu_item_info =
-      {
-        sizeof (GtkTearoffMenuItemClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-       (GClassInitFunc) gtk_tearoff_menu_item_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       sizeof (GtkTearoffMenuItem),
-       0,              /* n_preallocs */
-       (GInstanceInitFunc) gtk_tearoff_menu_item_init,
-      };
-
-      tearoff_menu_item_type =
-       g_type_register_static (GTK_TYPE_MENU_ITEM, "GtkTearoffMenuItem",
-                               &tearoff_menu_item_info, 0);
-    }
-
-  return tearoff_menu_item_type;
-}
+  guint torn_off : 1;
+};
+
+static void gtk_tearoff_menu_item_get_preferred_width  (GtkWidget      *widget,
+                                                       gint           *minimum,
+                                                       gint           *natural);
+static void gtk_tearoff_menu_item_get_preferred_height (GtkWidget      *widget,
+                                                       gint           *minimum,
+                                                       gint           *natural);
+static gboolean gtk_tearoff_menu_item_draw             (GtkWidget      *widget,
+                                                       cairo_t        *cr);
+static void gtk_tearoff_menu_item_activate             (GtkMenuItem    *menu_item);
+static void gtk_tearoff_menu_item_parent_set           (GtkWidget      *widget,
+                                                       GtkWidget      *previous);
+
+G_DEFINE_TYPE (GtkTearoffMenuItem, gtk_tearoff_menu_item, GTK_TYPE_MENU_ITEM)
 
 GtkWidget*
 gtk_tearoff_menu_item_new (void)
@@ -81,163 +62,182 @@ gtk_tearoff_menu_item_new (void)
 static void
 gtk_tearoff_menu_item_class_init (GtkTearoffMenuItemClass *klass)
 {
-  GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkMenuItemClass *menu_item_class;
 
-  object_class = (GtkObjectClass*) klass;
   widget_class = (GtkWidgetClass*) klass;
   menu_item_class = (GtkMenuItemClass*) klass;
 
-  widget_class->expose_event = gtk_tearoff_menu_item_expose;
-  widget_class->size_request = gtk_tearoff_menu_item_size_request;
+  widget_class->draw = gtk_tearoff_menu_item_draw;
+  widget_class->get_preferred_width = gtk_tearoff_menu_item_get_preferred_width;
+  widget_class->get_preferred_height = gtk_tearoff_menu_item_get_preferred_height;
   widget_class->parent_set = gtk_tearoff_menu_item_parent_set;
 
   menu_item_class->activate = gtk_tearoff_menu_item_activate;
+
+  g_type_class_add_private (klass, sizeof (GtkTearoffMenuItemPrivate));
 }
 
 static void
 gtk_tearoff_menu_item_init (GtkTearoffMenuItem *tearoff_menu_item)
 {
-  tearoff_menu_item->torn_off = FALSE;
+  GtkTearoffMenuItemPrivate *priv;
+
+  tearoff_menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (tearoff_menu_item,
+                                                         GTK_TYPE_TEAROFF_MENU_ITEM,
+                                                         GtkTearoffMenuItemPrivate);
+  priv = tearoff_menu_item->priv;
+
+  priv->torn_off = FALSE;
 }
 
 static void
-gtk_tearoff_menu_item_size_request (GtkWidget      *widget,
-                                   GtkRequisition *requisition)
+gtk_tearoff_menu_item_get_preferred_width (GtkWidget      *widget,
+                                          gint           *minimum,
+                                          gint           *natural)
 {
-  GtkTearoffMenuItem *tearoff;
-  
-  tearoff = GTK_TEAROFF_MENU_ITEM (widget);
-  
-  requisition->width = (GTK_CONTAINER (widget)->border_width +
-                       widget->style->xthickness +
-                       BORDER_SPACING) * 2;
-  requisition->height = (GTK_CONTAINER (widget)->border_width +
-                        widget->style->ythickness) * 2;
+  GtkStyle *style;
+  guint border_width;
+
+  style = gtk_widget_get_style (widget);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  *minimum = *natural = (border_width + style->xthickness + BORDER_SPACING) * 2;
+}
+
+static void
+gtk_tearoff_menu_item_get_preferred_height (GtkWidget      *widget,
+                                           gint           *minimum,
+                                           gint           *natural)
+{
+  GtkStyle *style;
+  GtkWidget *parent;
+  guint border_width;
+
+  style = gtk_widget_get_style (widget);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  *minimum = *natural = (border_width + style->ythickness) * 2;
 
-  if (GTK_IS_MENU (widget->parent) && GTK_MENU (widget->parent)->torn_off)
+  parent = gtk_widget_get_parent (widget);
+  if (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off)
     {
-      requisition->height += ARROW_SIZE;
+      *minimum += ARROW_SIZE;
+      *natural += ARROW_SIZE;
     }
   else
     {
-      requisition->height += widget->style->ythickness + 4;
+      *minimum += style->ythickness + 4;
+      *natural += style->ythickness + 4;
     }
 }
 
-static void
-gtk_tearoff_menu_item_paint (GtkWidget   *widget,
-                            GdkRectangle *area)
+static gboolean
+gtk_tearoff_menu_item_draw (GtkWidget *widget,
+                            cairo_t   *cr)
 {
   GtkMenuItem *menu_item;
-  GtkTearoffMenuItem *tearoff_item;
   GtkShadowType shadow_type;
-  gint width, height;
-  gint x, y;
+  GtkStateType state;
+  GtkStyle *style;
+  gint x, y, width, height;
   gint right_max;
+  guint border_width;
   GtkArrowType arrow_type;
   GtkTextDirection direction;
-  
-  if (GTK_WIDGET_DRAWABLE (widget))
+  GtkWidget *parent;
+  GdkWindow *window;
+
+  menu_item = GTK_MENU_ITEM (widget);
+  style = gtk_widget_get_style (widget);
+  window = gtk_widget_get_window (widget);
+  direction = gtk_widget_get_direction (widget);
+  state = gtk_widget_get_state (widget);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_item));
+  x = border_width;
+  y = border_width;
+  width = gtk_widget_get_allocated_width (widget) - border_width * 2;
+  height = gtk_widget_get_allocated_height (widget) - border_width * 2;
+  right_max = x + width;
+
+  if (state == GTK_STATE_PRELIGHT)
     {
-      menu_item = GTK_MENU_ITEM (widget);
-      tearoff_item = GTK_TEAROFF_MENU_ITEM (widget);
-
-      direction = gtk_widget_get_direction (widget);
-
-      x = widget->allocation.x + GTK_CONTAINER (menu_item)->border_width;
-      y = widget->allocation.y + GTK_CONTAINER (menu_item)->border_width;
-      width = widget->allocation.width - GTK_CONTAINER (menu_item)->border_width * 2;
-      height = widget->allocation.height - GTK_CONTAINER (menu_item)->border_width * 2;
-      right_max = x + width;
-
-      if (widget->state == GTK_STATE_PRELIGHT)
-       {
-         gint selected_shadow_type;
-         
-         gtk_widget_style_get (widget,
-                               "selected_shadow_type", &selected_shadow_type,
-                               NULL);
-         gtk_paint_box (widget->style,
-                        widget->window,
-                        GTK_STATE_PRELIGHT,
-                        selected_shadow_type,
-                        area, widget, "menuitem",
-                        x, y, width, height);
-       }
+      gint selected_shadow_type;
+      
+      gtk_widget_style_get (widget,
+                            "selected-shadow-type", &selected_shadow_type,
+                            NULL);
+      gtk_paint_box (style,
+                     cr,
+                     GTK_STATE_PRELIGHT,
+                     selected_shadow_type,
+                     widget, "menuitem",
+                     x, y, width, height);
+    }
+
+  parent = gtk_widget_get_parent (widget);
+  if (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off)
+    {
+      gint arrow_x;
+
+      if (state == GTK_STATE_PRELIGHT)
+        shadow_type = GTK_SHADOW_IN;
       else
-       gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
-
-      if (GTK_IS_MENU (widget->parent) && GTK_MENU (widget->parent)->torn_off)
-       {
-         gint arrow_x;
-
-         if (widget->state == GTK_STATE_PRELIGHT)
-           shadow_type = GTK_SHADOW_IN;
-         else
-           shadow_type = GTK_SHADOW_OUT;
-
-         if (menu_item->toggle_size > ARROW_SIZE)
-           {
-             if (direction == GTK_TEXT_DIR_LTR) {
-               arrow_x = x + (menu_item->toggle_size - ARROW_SIZE)/2;
-               arrow_type = GTK_ARROW_LEFT;
-             }
-             else {
-               arrow_x = x + width - menu_item->toggle_size + (menu_item->toggle_size - ARROW_SIZE)/2; 
-               arrow_type = GTK_ARROW_RIGHT;       
-             }
-             x += menu_item->toggle_size + BORDER_SPACING;
-           }
-         else
-           {
-             if (direction == GTK_TEXT_DIR_LTR) {
-               arrow_x = ARROW_SIZE / 2;
-               arrow_type = GTK_ARROW_LEFT;
-             }
-             else {
-               arrow_x = x + width - 2 * ARROW_SIZE + ARROW_SIZE / 2; 
-               arrow_type = GTK_ARROW_RIGHT;       
-             }
-             x += 2 * ARROW_SIZE;
-           }
-
-
-         gtk_paint_arrow (widget->style, widget->window,
-                          widget->state, shadow_type,
-                          NULL, widget, "tearoffmenuitem",
-                          arrow_type, FALSE,
-                          arrow_x, y + height / 2 - 5, 
-                          ARROW_SIZE, ARROW_SIZE);
-       }
-
-      while (x < right_max)
-       {
-         gint x1, x2;
-
-         if (direction == GTK_TEXT_DIR_LTR) {
-           x1 = x;
-           x2 = MIN (x + TEAR_LENGTH, right_max);
-         }
-         else {
-           x1 = right_max - x;
-           x2 = MAX (right_max - x - TEAR_LENGTH, 0);
-         }
-         
-         gtk_paint_hline (widget->style, widget->window, GTK_STATE_NORMAL,
-                          NULL, widget, "tearoffmenuitem",
-                          x1, x2, y + (height - widget->style->ythickness) / 2);
-         x += 2 * TEAR_LENGTH;
-       }
+        shadow_type = GTK_SHADOW_OUT;
+
+      if (menu_item->toggle_size > ARROW_SIZE)
+        {
+          if (direction == GTK_TEXT_DIR_LTR) {
+            arrow_x = x + (menu_item->toggle_size - ARROW_SIZE)/2;
+            arrow_type = GTK_ARROW_LEFT;
+          }
+          else {
+            arrow_x = x + width - menu_item->toggle_size + (menu_item->toggle_size - ARROW_SIZE)/2; 
+            arrow_type = GTK_ARROW_RIGHT;          
+          }
+          x += menu_item->toggle_size + BORDER_SPACING;
+        }
+      else
+        {
+          if (direction == GTK_TEXT_DIR_LTR) {
+            arrow_x = ARROW_SIZE / 2;
+            arrow_type = GTK_ARROW_LEFT;
+          }
+          else {
+            arrow_x = x + width - 2 * ARROW_SIZE + ARROW_SIZE / 2; 
+            arrow_type = GTK_ARROW_RIGHT;          
+          }
+          x += 2 * ARROW_SIZE;
+        }
+
+
+      gtk_paint_arrow (style, cr,
+                       state, shadow_type,
+                       widget, "tearoffmenuitem",
+                       arrow_type, FALSE,
+                       arrow_x, y + height / 2 - 5, 
+                       ARROW_SIZE, ARROW_SIZE);
     }
-}
 
-static gint
-gtk_tearoff_menu_item_expose (GtkWidget      *widget,
-                           GdkEventExpose *event)
-{
-  gtk_tearoff_menu_item_paint (widget, &event->area);
+  while (x < right_max)
+    {
+      gint x1, x2;
+
+      if (direction == GTK_TEXT_DIR_LTR) {
+        x1 = x;
+        x2 = MIN (x + TEAR_LENGTH, right_max);
+      }
+      else {
+        x1 = right_max - x;
+        x2 = MAX (right_max - x - TEAR_LENGTH, 0);
+      }
+
+      gtk_paint_hline (style, cr, GTK_STATE_NORMAL,
+                       widget, "tearoffmenuitem",
+                       x1, x2, y + (height - style->ythickness) / 2);
+      x += 2 * TEAR_LENGTH;
+    }
 
   return FALSE;
 }
@@ -245,22 +245,28 @@ gtk_tearoff_menu_item_expose (GtkWidget      *widget,
 static void
 gtk_tearoff_menu_item_activate (GtkMenuItem *menu_item)
 {
-  if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
+  GtkWidget *parent;
+
+  parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
+  if (GTK_IS_MENU (parent))
     {
-      GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
-      
-      gtk_menu_set_tearoff_state (GTK_MENU (GTK_WIDGET (menu_item)->parent),
+      GtkMenu *menu = GTK_MENU (parent);
+
+      gtk_widget_queue_resize (GTK_WIDGET (menu_item));
+      gtk_menu_set_tearoff_state (GTK_MENU (parent),
                                  !menu->torn_off);
     }
-
-  gtk_widget_queue_resize (GTK_WIDGET (menu_item));
 }
 
 static void
 tearoff_state_changed (GtkMenu            *menu,
-                      GtkTearoffMenuItem *tearoff_menu_item)
+                      GParamSpec         *pspec,
+                      gpointer            data)
 {
-  tearoff_menu_item->torn_off = gtk_menu_get_tearoff_state (menu);
+  GtkTearoffMenuItem *tearoff_menu_item = GTK_TEAROFF_MENU_ITEM (data);
+  GtkTearoffMenuItemPrivate *priv = tearoff_menu_item->priv;
+
+  priv->torn_off = gtk_menu_get_tearoff_state (menu);
 }
 
 static void
@@ -268,7 +274,12 @@ gtk_tearoff_menu_item_parent_set (GtkWidget *widget,
                                  GtkWidget *previous)
 {
   GtkTearoffMenuItem *tearoff_menu_item = GTK_TEAROFF_MENU_ITEM (widget);
-  GtkMenu *menu = GTK_IS_MENU (widget->parent) ? GTK_MENU (widget->parent) : NULL;
+  GtkTearoffMenuItemPrivate *priv = tearoff_menu_item->priv;
+  GtkMenu *menu;
+  GtkWidget *parent;
+
+  parent = gtk_widget_get_parent (widget);
+  menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
 
   if (previous)
     g_signal_handlers_disconnect_by_func (previous, 
@@ -277,7 +288,7 @@ gtk_tearoff_menu_item_parent_set (GtkWidget *widget,
   
   if (menu)
     {
-      tearoff_menu_item->torn_off = gtk_menu_get_tearoff_state (menu);
+      priv->torn_off = gtk_menu_get_tearoff_state (menu);
       g_signal_connect (menu, "notify::tearoff-state", 
                        G_CALLBACK (tearoff_state_changed), 
                        tearoff_menu_item);