Code

add *.c to libcroco/CMakeFile and libgdl/CMakeFile
[inkscape.git] / src / libgdl / gdl-dock-item.c
index d9f805ffe1b3eaafb0099488629dfc763a1fdaab..e8ae3d54b1cc343052af09c77b8f2b9fa8e9a58a 100644 (file)
@@ -81,6 +81,10 @@ static void  gdl_dock_item_forall        (GtkContainer *container,
                                           gpointer      callback_data);
 static GtkType gdl_dock_item_child_type  (GtkContainer *container);
 
+static void  gdl_dock_item_set_focus_child (GtkContainer *container,
+                                            GtkWidget    *widget,
+                                            gpointer      callback_data);
+
 static void  gdl_dock_item_size_request  (GtkWidget *widget,
                                           GtkRequisition *requisition);
 static void  gdl_dock_item_size_allocate (GtkWidget *widget,
@@ -93,6 +97,9 @@ static void  gdl_dock_item_style_set     (GtkWidget *widget,
 static gint  gdl_dock_item_expose        (GtkWidget *widget,
                                           GdkEventExpose *event);
 
+static void  gdl_dock_item_move_focus_child (GdlDockItem      *item,
+                                             GtkDirectionType  dir);
+
 static gint  gdl_dock_item_button_changed (GtkWidget *widget,
                                            GdkEventButton *event);
 static gint  gdl_dock_item_motion         (GtkWidget *widget,
@@ -157,6 +164,7 @@ enum {
     DOCK_DRAG_BEGIN,
     DOCK_DRAG_MOTION,
     DOCK_DRAG_END,
+    MOVE_FOCUS_CHILD,
     LAST_SIGNAL
 };
 
@@ -191,6 +199,40 @@ struct _GdlDockItemPrivate {
 
 GDL_CLASS_BOILERPLATE (GdlDockItem, gdl_dock_item, GdlDockObject, GDL_TYPE_DOCK_OBJECT);
 
+static void
+add_tab_bindings (GtkBindingSet    *binding_set,
+                 GdkModifierType   modifiers,
+                 GtkDirectionType  direction)
+{
+    gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
+static void
+add_arrow_bindings (GtkBindingSet    *binding_set,
+                   guint             keysym,
+                   GtkDirectionType  direction)
+{
+    guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
+
+    gtk_binding_entry_add_signal (binding_set, keysym, 0,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
 static void
 gdl_dock_item_class_init (GdlDockItemClass *klass)
 {
@@ -201,6 +243,7 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
     GtkWidgetClass     *widget_class;
     GtkContainerClass  *container_class;
     GdlDockObjectClass *object_class;
+    GtkBindingSet      *binding_set;
     
     g_object_class = G_OBJECT_CLASS (klass);
     gtk_object_class = GTK_OBJECT_CLASS (klass);
@@ -230,6 +273,7 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
     container_class->remove = gdl_dock_item_remove;
     container_class->forall = gdl_dock_item_forall;
     container_class->child_type = gdl_dock_item_child_type;
+    container_class->set_focus_child = gdl_dock_item_set_focus_child;
     
     object_class->is_compound = FALSE;
 
@@ -332,10 +376,38 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
                       1,
                       G_TYPE_BOOLEAN);
 
+    gdl_dock_item_signals [MOVE_FOCUS_CHILD] =
+        g_signal_new ("move_focus_child",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                      G_STRUCT_OFFSET (GdlDockItemClass, move_focus_child),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__ENUM,
+                      G_TYPE_NONE,
+                      1,
+                      GTK_TYPE_DIRECTION_TYPE);
+
+
+    /* key bindings */
+
+    binding_set = gtk_binding_set_by_class (klass);
+
+    add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
+    add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
+    add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
+    add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
+
+    add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+    add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+    add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+    add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
     klass->has_grip = TRUE;
     klass->dock_drag_begin = NULL;
     klass->dock_drag_motion = NULL;
     klass->dock_drag_end = NULL;
+    klass->move_focus_child = gdl_dock_item_move_focus_child;
     klass->set_orientation = gdl_dock_item_real_set_orientation;
 
     if (!style_initialized)
@@ -355,6 +427,7 @@ static void
 gdl_dock_item_instance_init (GdlDockItem *item)
 {
     GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_NO_WINDOW);
+    GTK_WIDGET_SET_FLAGS (GTK_WIDGET (item), GTK_CAN_FOCUS);
 
     item->child = NULL;
     
@@ -622,6 +695,19 @@ gdl_dock_item_child_type (GtkContainer *container)
         return G_TYPE_NONE;
 }
 
+static void
+gdl_dock_item_set_focus_child (GtkContainer *container,
+                               GtkWidget    *child,
+                               gpointer      callback_data)
+{
+    g_return_if_fail (GDL_IS_DOCK_ITEM (container));
+    
+    if (GTK_CONTAINER_CLASS (parent_class)->set_focus_child)
+        (* GTK_CONTAINER_CLASS (parent_class)->set_focus_child) (container, child);
+
+    gdl_dock_item_showhide_grip (GDL_DOCK_ITEM (container));
+}
+
 static void
 gdl_dock_item_size_request (GtkWidget      *widget,
                             GtkRequisition *requisition)
@@ -878,6 +964,14 @@ gdl_dock_item_expose (GtkWidget      *widget,
     return FALSE;
 }
 
+static void
+gdl_dock_item_move_focus_child (GdlDockItem      *item,
+                                GtkDirectionType  dir)
+{
+    g_return_if_fail (GDL_IS_DOCK_ITEM (item));
+    gtk_widget_child_focus (GTK_WIDGET (item->child), dir);
+}
+
 #define EVENT_IN_GRIP_EVENT_WINDOW(ev,gr) \
     ((gr) != NULL && (ev)->window == GDL_DOCK_ITEM_GRIP (gr)->title_window)
 
@@ -922,6 +1016,10 @@ gdl_dock_item_button_changed (GtkWidget      *widget,
 
     /* Left mousebutton click on dockitem. */
     if (!locked && event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+
+        if (!gdl_dock_item_or_child_has_focus (item))
+            gtk_widget_grab_focus (GTK_WIDGET (item));
+            
         /* Set in_drag flag, grab pointer and call begin drag operation. */      
         if (in_handle) {
             item->_priv->start_x = event->x;
@@ -942,6 +1040,7 @@ gdl_dock_item_button_changed (GtkWidget      *widget,
         if (GDL_DOCK_ITEM_IN_DRAG (item)) {
             /* User dropped widget somewhere. */
             gdl_dock_item_drag_end (item, FALSE);
+            gtk_widget_grab_focus (GTK_WIDGET (item));
             event_handled = TRUE;
         }
         else if (GDL_DOCK_ITEM_IN_PREDRAG (item)) {
@@ -1199,7 +1298,7 @@ gdl_dock_item_dock (GdlDockObject    *object,
             }
             if (req.width > 1)
                 g_object_set (object, "preferred-width", req.width, NULL);
-            if (req.height > 1)
+            if (req.height > 1 && object_req.height > req.height)
                 g_object_set (object, "preferred-height",
                               object_req.height - req.height, NULL);
             break;
@@ -1347,6 +1446,8 @@ gdl_dock_item_dock (GdlDockObject    *object,
     gdl_dock_object_thaw (new_parent);
     if (parent)
         gdl_dock_object_thaw (parent);
+
+
 }
 
 static void
@@ -1916,6 +2017,26 @@ gdl_dock_item_preferred_size (GdlDockItem    *item,
 }
 
 
+gboolean
+gdl_dock_item_or_child_has_focus (GdlDockItem *item)
+{
+    GtkWidget *item_child;
+    gboolean item_or_child_has_focus;
+
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (item), FALSE);
+
+    for (item_child = GTK_CONTAINER (item)->focus_child;
+         item_child && GTK_IS_CONTAINER (item_child) && GTK_CONTAINER (item_child)->focus_child;
+         item_child = GTK_CONTAINER (item_child)->focus_child) ;
+    
+    item_or_child_has_focus =
+        (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (item)) || 
+         (GTK_IS_WIDGET (item_child) && GTK_WIDGET_HAS_FOCUS (item_child)));
+    
+    return item_or_child_has_focus;
+}
+
+
 /* ----- gtk orientation type exporter/importer ----- */
 
 static void