Code

Dockable dialogs: Allow in-dock dialogs to be expanded even if there's
authorgustav_b <gustav_b@users.sourceforge.net>
Thu, 25 Oct 2007 21:34:38 +0000 (21:34 +0000)
committergustav_b <gustav_b@users.sourceforge.net>
Thu, 25 Oct 2007 21:34:38 +0000 (21:34 +0000)
no "slack".

src/libgdl/gdl-dock-master.c
src/libgdl/gdl-dock-object.h
src/libgdl/gdl-dock-paned.c
src/libgdl/gdl-dock-paned.h
src/libgdl/libgdltypebuiltins.c
src/libgdl/libgdltypebuiltins.h
src/ui/widget/dock.cpp
src/ui/widget/dock.h

index 8a6aba315081026cbd59f4026be62552c68dc2ae..205900702b05ac097d4d42c90cd40c7de689d121 100644 (file)
@@ -79,7 +79,8 @@ enum {
     PROP_0,
     PROP_DEFAULT_TITLE,
     PROP_LOCKED,
-    PROP_SWITCHER_STYLE
+    PROP_SWITCHER_STYLE,
+    PROP_EXPANSION_DIRECTION
 };
 
 enum {
@@ -109,6 +110,8 @@ struct _GdlDockMasterPrivate {
     GHashTable     *unlocked_items;
     
     GdlSwitcherStyle switcher_style;
+
+    GdlDockExpansionDirection expansion_direction;
 };
 
 #define COMPUTE_LOCKED(master)                                          \
@@ -157,6 +160,15 @@ gdl_dock_master_class_init (GdlDockMasterClass *klass)
                            GDL_SWITCHER_STYLE_BOTH,
                            G_PARAM_READWRITE));
 
+    g_object_class_install_property (
+        g_object_class, PROP_EXPANSION_DIRECTION,
+        g_param_spec_enum ("expand-direction", _("Expand direction"),
+                           _("Allow the master's dock items to expand their container "
+                             "dock objects in the given direction"),
+                           GDL_TYPE_EXPANSION_DIRECTION,
+                           GDL_DOCK_EXPANSION_DIRECTION_NONE,
+                           G_PARAM_READWRITE));
+
     master_signals [LAYOUT_CHANGED] = 
         g_signal_new ("layout-changed", 
                       G_TYPE_FROM_CLASS (klass),
@@ -183,6 +195,7 @@ gdl_dock_master_instance_init (GdlDockMaster *master)
     master->_priv = g_new0 (GdlDockMasterPrivate, 1);
     master->_priv->number = 1;
     master->_priv->switcher_style = GDL_SWITCHER_STYLE_BOTH;
+    master->_priv->expansion_direction = GDL_DOCK_EXPANSION_DIRECTION_NONE;
     master->_priv->locked_items = g_hash_table_new (g_direct_hash, g_direct_equal);
     master->_priv->unlocked_items = g_hash_table_new (g_direct_hash, g_direct_equal);
 }
@@ -359,6 +372,9 @@ gdl_dock_master_set_property  (GObject      *object,
         case PROP_SWITCHER_STYLE:
             gdl_dock_master_set_switcher_style (master, g_value_get_enum (value));
             break;
+        case PROP_EXPANSION_DIRECTION:
+            master->_priv->expansion_direction = g_value_get_enum (value);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
             break;
@@ -383,6 +399,9 @@ gdl_dock_master_get_property  (GObject      *object,
         case PROP_SWITCHER_STYLE:
             g_value_set_enum (value, master->_priv->switcher_style);
             break;
+        case PROP_EXPANSION_DIRECTION:
+            g_value_set_enum (value, master->_priv->expansion_direction);
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
             break;
index f2141830222b59e09b02982447fb59f69fa134f9..84e5eb9a7002c981111ccc5416449fe5253ab885 100644 (file)
@@ -66,6 +66,14 @@ typedef enum {
     GDL_DOCK_FLOATING
 } GdlDockPlacement;
 
+typedef enum {
+    GDL_DOCK_EXPANSION_DIRECTION_NONE = 0,
+    GDL_DOCK_EXPANSION_DIRECTION_UP,
+    GDL_DOCK_EXPANSION_DIRECTION_DOWN,
+    GDL_DOCK_EXPANSION_DIRECTION_LEFT,
+    GDL_DOCK_EXPANSION_DIRECTION_RIGHT
+} GdlDockExpansionDirection;
+
 typedef struct _GdlDockObject      GdlDockObject;
 typedef struct _GdlDockObjectClass GdlDockObjectClass;
 typedef struct _GdlDockRequest     GdlDockRequest;
index a176f1f7d84da0d52be7969591b925d7d125ad90..268a9f6737f9f89f7b3a5f2f9f4e7aa117759ef3 100644 (file)
@@ -140,6 +140,64 @@ static void
 gdl_dock_paned_instance_init (GdlDockPaned *paned)
 {
     paned->position_changed = FALSE;
+    paned->in_drag = FALSE;
+    paned->last_drag_position = -1;
+}
+
+static void
+gdl_dock_paned_resize_paned_ancestors (GdlDockPaned       *paned, 
+                                       GdlDockExpansionDirection  expansion_direction,
+                                       gint                diff)
+{
+     GtkWidget *widget, *last_widget;
+
+     g_return_if_fail (GDL_IS_DOCK_PANED (paned));
+
+     last_widget = GTK_WIDGET (paned);
+
+     /* make sure resizing only can be done in the drag direction */
+     if (expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_NONE ||
+         ((expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_DOWN || 
+           expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_UP) && 
+          !GTK_IS_VPANED (GDL_DOCK_ITEM (paned)->child)) ||
+         ((expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_LEFT || 
+           expansion_direction == GDL_DOCK_EXPANSION_DIRECTION_RIGHT) && 
+          !GTK_IS_HPANED (GDL_DOCK_ITEM (paned)->child)))
+     {         
+         return;
+     }
+
+     for (widget = GTK_WIDGET (paned)->parent; widget != NULL; 
+          widget = widget->parent) {
+
+         if (GTK_IS_PANED (widget)) {
+
+             GtkPaned *paned = GTK_PANED (widget);
+
+                 if (last_widget == paned->child1) {
+
+                     if (!GDL_IS_DOCK_OBJECT(widget->parent)) {
+                         GtkRequisition requisition;
+                         GtkAllocation allocation = paned->child1->allocation;
+
+                         gtk_widget_size_request (paned->child1, &requisition);
+
+                         gint new_height =
+                             (allocation.height > requisition.height && diff > 0 ?
+                              allocation.height : requisition.height) + diff;
+
+                         gtk_widget_set_size_request (paned->child1, -1, new_height);
+                     }
+                     
+                     gtk_paned_set_position (paned, gtk_paned_get_position (paned) + diff);
+                 }
+             
+         } else if (!GDL_IS_DOCK_OBJECT (widget)) {
+             break;
+         }
+
+         last_widget = widget;
+     }
 }
 
 static void 
@@ -148,7 +206,7 @@ gdl_dock_paned_notify_cb (GObject    *g_object,
                           gpointer    user_data) 
 {
     GdlDockPaned *paned;
-    
+
     g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data));
     
     /* chain the notification to the GdlDockPaned */
@@ -156,8 +214,40 @@ gdl_dock_paned_notify_cb (GObject    *g_object,
     
     paned = GDL_DOCK_PANED (user_data);
     
-    if (GDL_DOCK_ITEM_USER_ACTION (user_data) && !strcmp (pspec->name, "position"))
+    if (GDL_DOCK_ITEM_USER_ACTION (user_data) && !strcmp (pspec->name, "position")) {
+
+        GdlDockExpansionDirection expansion_direction;
+
         paned->position_changed = TRUE;
+
+        g_object_get (GDL_DOCK_OBJECT(paned)->master,
+                      "expand-direction", &expansion_direction,
+                      NULL);
+
+        switch (expansion_direction) {
+        case GDL_DOCK_EXPANSION_DIRECTION_DOWN:
+            if (paned->in_drag) {
+                gint max_position, position, diff;
+                g_object_get (GDL_DOCK_ITEM (paned)->child,
+                              "max-position", &max_position,
+                              "position", &position,
+                              NULL);
+                diff = position - paned->last_drag_position;
+                paned->last_drag_position = position;
+
+                if (diff > 0 && position == max_position) {
+                    gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, diff + 1);
+                } else {
+                    gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, diff);
+                }
+                 
+            }
+            break;
+        default:
+            ;
+        }
+    }
 }
 
 static gboolean 
@@ -171,8 +261,42 @@ gdl_dock_paned_button_cb (GtkWidget      *widget,
     
     paned = GDL_DOCK_PANED (user_data);
     if (event->button == 1) {
-        if (event->type == GDK_BUTTON_PRESS)
+       if (event->type == GDK_BUTTON_PRESS) {
+
+            GdlDockExpansionDirection expansion_direction;
+
             GDL_DOCK_ITEM_SET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
+
+            paned->in_drag = TRUE;
+
+            g_object_get (GDL_DOCK_OBJECT (paned)->master,
+                          "expand-direction", &expansion_direction,
+                          NULL);
+
+            switch (expansion_direction) {
+            case GDL_DOCK_EXPANSION_DIRECTION_DOWN:
+            {
+                gint max_position, position;
+                g_object_get (GDL_DOCK_ITEM (paned)->child,
+                              "max-position", &max_position,
+                              "position", &position,
+                              NULL);
+
+                paned->last_drag_position = position;
+                /* expand the paned's ancestors a bit if the separator is in max position
+                 * to allow dragging in all directions */
+                if (position == max_position)
+                    gdl_dock_paned_resize_paned_ancestors (paned, expansion_direction, 1);
+                break;
+            }
+            default:
+                ;
+            }
+        }
+        else if (event->type == GDK_BUTTON_RELEASE) {
+            paned->last_drag_position = -1;
+            paned->in_drag = FALSE;
+        }
         else {
             GDL_DOCK_ITEM_UNSET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
             if (paned->position_changed) {
@@ -570,7 +694,7 @@ gdl_dock_paned_dock (GdlDockObject    *object,
                 gtk_paned_pack1 (paned, GTK_WIDGET (requestor), hresize, FALSE);
                 done = TRUE;
             } else if (!paned->child2 && position == GDL_DOCK_BOTTOM) {
-                gtk_paned_pack2 (paned, GTK_WIDGET (requestor), hresize, FALSE);
+                gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
                 done = TRUE;
             }
             break;
@@ -581,7 +705,7 @@ gdl_dock_paned_dock (GdlDockObject    *object,
     if (!done) {
         /* this will create another paned and reparent us there */
         GDL_CALL_PARENT (GDL_DOCK_OBJECT_CLASS, dock, (object, requestor, position,
-                                                         other_data));
+                                                       other_data));
     }
     else {
         gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor));
index 41107a51fd30fde2b8b34c124c18e0caea462dbf..208c9c4225df6d33a948e9f25f8d35bf3b010e93 100644 (file)
@@ -44,6 +44,8 @@ struct _GdlDockPaned {
     GdlDockItem  dock_item;
 
     gboolean     position_changed;
+    gboolean     in_drag;
+    gint         last_drag_position;
 };
 
 struct _GdlDockPanedClass {
index 5ec9ec808d7b3920560453f655941fcbfb3db7b7..853dc5d538597757d629195c99ea70714b83eb0e 100644 (file)
@@ -65,6 +65,28 @@ gdl_dock_placement_get_type (void)
 }
 
 
+
+static const GEnumValue _gdl_dock_expansion_direction_values[] = {
+  { GDL_DOCK_EXPANSION_DIRECTION_NONE, "GDL_DOCK_EXPANSION_DIRECTION_NONE", "none" },
+  { GDL_DOCK_EXPANSION_DIRECTION_UP, "GDL_DOCK_EXPANSION_DIRECTION_UP", "up" },
+  { GDL_DOCK_EXPANSION_DIRECTION_DOWN, "GDL_DOCK_EXPANSION_DIRECTION_DOWN", "down" },
+  { GDL_DOCK_EXPANSION_DIRECTION_LEFT, "GDL_DOCK_EXPANSION_DIRECTION_LEFT", "left" },
+  { GDL_DOCK_EXPANSION_DIRECTION_RIGHT, "GDL_DOCK_EXPANSION_DIRECTION_RIGHT", "right" },
+  { 0, NULL, NULL }
+};
+
+GType
+gdl_dock_expansion_direction_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type)
+    type = g_enum_register_static ("GdlDockExpansionDirection", _gdl_dock_expansion_direction_values);
+
+  return type;
+}
+
+
 /* enumerations from "gdl-dock-item.h" */
 static const GFlagsValue _gdl_dock_item_behavior_values[] = {
   { GDL_DOCK_ITEM_BEH_NORMAL, "GDL_DOCK_ITEM_BEH_NORMAL", "normal" },
index 22b28cf4b31f4715e58cb3f2386aa9d2a50c79ca..8be5decb19d8bfa9678c89c0ee513646b39159a5 100644 (file)
@@ -16,6 +16,8 @@ GType gdl_dock_param_flags_get_type (void);
 GType gdl_dock_object_flags_get_type (void);
 #define GDL_TYPE_DOCK_PLACEMENT gdl_dock_placement_get_type()
 GType gdl_dock_placement_get_type (void);
+#define GDL_TYPE_EXPANSION_DIRECTION gdl_dock_expansion_direction_get_type()
+GType gdl_dock_expansion_direction_get_type (void);
 
 /* --- gdl-dock-item.h --- */
 #define GDL_TYPE_DOCK_ITEM_BEHAVIOR gdl_dock_item_behavior_get_type()
index ae19ed8d6fa5197dbe9e6ad2ccec9d789ed5facf..1ca2580ba5326502f3f7b7be669aaafbea04fdce 100644 (file)
@@ -80,6 +80,7 @@ Dock::Dock(Gtk::Orientation orientation)
 
     g_object_set (GDL_DOCK_OBJECT(_gdl_dock)->master,
                   "switcher-style", gdl_switcher_style,
+                  "expand-direction", GDL_DOCK_EXPANSION_DIRECTION_DOWN,
                   NULL);
 
     GdlDockBarStyle gdl_dock_bar_style = 
@@ -91,6 +92,9 @@ Dock::Dock(Gtk::Orientation orientation)
     g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_hide", G_CALLBACK(hideCallback), (void *)this);
     g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_unhide", G_CALLBACK(unhideCallback), (void *)this);
 
+    g_signal_connect(_paned->gobj(), "button-press-event", G_CALLBACK(_on_paned_button_event), (void *)this);
+    g_signal_connect(_paned->gobj(), "button-release-event", G_CALLBACK(_on_paned_button_event), (void *)this);
+
     signal_layout_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::Dock::_onLayoutChanged));
 }    
 
@@ -230,7 +234,6 @@ void
 Dock::_onLayoutChanged()
 {
     if (isEmpty()) {
-
        if (hasIconifiedItems())
            _scrolled_window->set_size_request(_default_dock_bar_width);
        else
@@ -238,10 +241,28 @@ Dock::_onLayoutChanged()
 
         getParentPaned()->set_position(INT_MAX);
     } else {
+        // unset any forced size requests
+        _paned->get_child1()->set_size_request(-1, -1);
        _scrolled_window->set_size_request(-1);
     }
 }
 
+void
+Dock::_onPanedButtonEvent(GdkEventButton *event)
+{
+    if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+        /* unset size request when starting a drag */
+        _paned->get_child1()->set_size_request(-1, -1);
+}
+
+gboolean
+Dock::_on_paned_button_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+    if (Dock *dock = static_cast<Dock *>(user_data))
+        dock->_onPanedButtonEvent(event);
+
+    return FALSE;
+}
 
 const Glib::SignalProxyInfo
 Dock::_signal_layout_changed_proxy = 
index b5ecc02cabed6ac68b9b3146b630b1db2534b9dc..dd501f186e4765ae340e022408a1e0dccccc608c 100644 (file)
@@ -71,6 +71,10 @@ protected:
 
     /** Internal signal handlers */
     void _onLayoutChanged();
+    void _onPanedButtonEvent(GdkEventButton *event);
+
+    static gboolean _on_paned_button_event(GtkWidget *widget, GdkEventButton *event, 
+                                           gpointer user_data);
 
     /** GdlDock signal proxy structures */
     static const Glib::SignalProxyInfo _signal_layout_changed_proxy;