void gdl_dock_master_remove (GdlDockMaster *master, GdlDockObject *object) { g_return_if_fail (master != NULL && object != NULL); /* remove from locked/unlocked hashes and property change if * that's the case */ if (GDL_IS_DOCK_ITEM (object) && GDL_DOCK_ITEM_HAS_GRIP (GDL_DOCK_ITEM (object))) { gint locked = COMPUTE_LOCKED (master); if (g_hash_table_remove (master->_priv->locked_items, object) || g_hash_table_remove (master->_priv->unlocked_items, object)) { if (COMPUTE_LOCKED (master) != locked) g_object_notify (G_OBJECT (master), "locked"); } } /* ref the master, since removing the controller could cause master disposal */ g_object_ref (master); /* all the interesting stuff happens in _gdl_dock_master_remove */ _gdl_dock_master_remove (object, master); /* post a layout_changed emission if the item is not automatic * (since it should be removed from the items model) */ if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) { if (!master->_priv->idle_layout_changed_id) master->_priv->idle_layout_changed_id = g_idle_add (idle_emit_layout_changed, master); } /* balance ref count */ g_object_unref (master); }
static void _gdl_dock_foreach_build_list (GdlDockObject *object, gpointer user_data) { GList **l = (GList **) user_data; if (GDL_IS_DOCK_ITEM (object)) *l = g_list_prepend (*l, object); }
static void anjuta_window_maximize_widget (AnjutaShell *shell, const char *widget_name, GError **error) { AnjutaWindow *win = NULL; GtkWidget *dock_item = NULL; gpointer value, key; GtkWidget *widget = NULL; GHashTableIter iter; /* AnjutaWindow assertions */ g_return_if_fail (ANJUTA_IS_WINDOW (shell)); win = ANJUTA_WINDOW (shell); /* If win->maximized is TRUE then another widget is already maximized. Restoring the UI for a new maximization. */ if(win->maximized) gdl_dock_layout_load_layout (win->layout_manager, "back-up"); /* Back-up the layout so it can be restored */ gdl_dock_layout_save_layout(win->layout_manager, "back-up"); /* Mark the win as maximized (the other widgets except center are hidden) */ win->maximized = TRUE; /* Hide all DockItem's except the ones positioned in the center */ g_hash_table_iter_init (&iter, win->widgets); while (g_hash_table_iter_next (&iter, &key, &value)) { if (value == NULL) continue; /* Widget assertions */ widget = GTK_WIDGET (value); if(!GTK_IS_WIDGET (widget)) continue; /* DockItem assertions */ dock_item = g_object_get_data (G_OBJECT (widget), "dockitem"); if(dock_item == NULL || !GDL_IS_DOCK_ITEM (dock_item)) continue; if(!g_strcmp0((gchar*)key, widget_name)) { /* If it's the widget requesting maximization then make sure the * widget is visible*/ gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item)); } else { /* Hide the other item */ gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock_item)); } } }
static void gdl_dock_add (GtkContainer *container, GtkWidget *widget) { g_return_if_fail (container != NULL); g_return_if_fail (GDL_IS_DOCK (container)); g_return_if_fail (GDL_IS_DOCK_ITEM (widget)); gdl_dock_add_item (GDL_DOCK (container), GDL_DOCK_ITEM (widget), GDL_DOCK_TOP); /* default position */ }
static void foreach_lock_unlock (GdlDockItem *item, gboolean locked) { if (!GDL_IS_DOCK_ITEM (item)) return; g_object_set (item, "locked", locked, NULL); if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (item))) gtk_container_foreach (GTK_CONTAINER (item), (GtkCallback) foreach_lock_unlock, GINT_TO_POINTER (locked)); }
GdlDockItem * gdl_dock_get_item_by_name (GdlDock *dock, const gchar *name) { GdlDockObject *found; g_return_val_if_fail (dock != NULL && name != NULL, NULL); /* proxy the call to our master */ found = gdl_dock_master_get_object (GDL_DOCK_OBJECT_GET_MASTER (dock), name); return (found && GDL_IS_DOCK_ITEM (found)) ? GDL_DOCK_ITEM (found) : NULL; }
static void set_switcher_style_foreach (GtkWidget *obj, gpointer user_data) { GdlSwitcherStyle style = GPOINTER_TO_INT (user_data); if (!GDL_IS_DOCK_ITEM (obj)) return; if (GDL_IS_DOCK_NOTEBOOK (obj)) { GtkWidget *child = GDL_DOCK_ITEM (obj)->child; if (GDL_IS_SWITCHER (child)) { g_object_set (child, "switcher-style", style, NULL); } } else if (gdl_dock_object_is_compound (GDL_DOCK_OBJECT (obj))) { gtk_container_foreach (GTK_CONTAINER (obj), set_switcher_style_foreach, user_data); } }
void gdl_dock_master_add (GdlDockMaster *master, GdlDockObject *object) { g_return_if_fail (master != NULL && object != NULL); if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) { GdlDockObject *found_object; /* create a name for the object if it doesn't have one */ if (!object->name) /* directly set the name, since it's a construction only property */ object->name = g_strdup_printf ("__dock_%u", master->_priv->number++); /* add the object to our hash list */ if ((found_object = g_hash_table_lookup (master->dock_objects, object->name))) { g_warning (_("master %p: unable to add object %p[%s] to the hash. " "There already is an item with that name (%p)."), master, object, object->name, found_object); } else { g_object_ref_sink (object); g_hash_table_insert (master->dock_objects, g_strdup (object->name), object); } } if (GDL_IS_DOCK (object)) { gboolean floating; /* if this is the first toplevel we are adding, name it controller */ if (!master->toplevel_docks) /* the dock should already have the ref */ master->controller = object; /* add dock to the toplevel list */ g_object_get (object, "floating", &floating, NULL); if (floating) master->toplevel_docks = g_list_prepend (master->toplevel_docks, object); else master->toplevel_docks = g_list_append (master->toplevel_docks, object); /* we are interested in the dock request this toplevel * receives to update the layout */ g_signal_connect (object, "dock", G_CALLBACK (item_dock_cb), master); } else if (GDL_IS_DOCK_ITEM (object)) { /* we need to connect the item's signals */ g_signal_connect (object, "dock_drag_begin", G_CALLBACK (gdl_dock_master_drag_begin), master); g_signal_connect (object, "dock_drag_motion", G_CALLBACK (gdl_dock_master_drag_motion), master); g_signal_connect (object, "dock_drag_end", G_CALLBACK (gdl_dock_master_drag_end), master); g_signal_connect (object, "dock", G_CALLBACK (item_dock_cb), master); g_signal_connect (object, "detach", G_CALLBACK (item_detach_cb), master); /* register to "locked" notification if the item has a grip, * and add the item to the corresponding hash */ if (GDL_DOCK_ITEM_HAS_GRIP (GDL_DOCK_ITEM (object))) { g_signal_connect (object, "notify::locked", G_CALLBACK (item_notify_cb), master); item_notify_cb (object, NULL, master); } /* If the item is notebook, set the switcher style */ if (GDL_IS_DOCK_NOTEBOOK (object) && GDL_IS_SWITCHER (GDL_DOCK_ITEM (object)->child)) { g_object_set (GDL_DOCK_ITEM (object)->child, "switcher-style", master->_priv->switcher_style, NULL); } /* post a layout_changed emission if the item is not automatic * (since it should be added to the items model) */ if (!GDL_DOCK_OBJECT_AUTOMATIC (object)) { if (!master->_priv->idle_layout_changed_id) master->_priv->idle_layout_changed_id = g_idle_add (idle_emit_layout_changed, master); } } }
static void gdl_dock_master_drag_motion (GdlDockItem *item, gint root_x, gint root_y, gpointer data) { GdlDockMaster *master; GdlDockRequest my_request, *request; GdkWindow *window; gint win_x, win_y; gint x, y; GdlDock *dock = NULL; gboolean may_dock = FALSE; g_return_if_fail (item != NULL && data != NULL); master = GDL_DOCK_MASTER (data); request = master->_priv->drag_request; g_return_if_fail (GDL_DOCK_OBJECT (item) == request->applicant); my_request = *request; /* first look under the pointer */ window = gdk_window_at_pointer (&win_x, &win_y); if (window) { GtkWidget *widget; /* ok, now get the widget who owns that window and see if we can get to a GdlDock by walking up the hierarchy */ gdk_window_get_user_data (window, (gpointer) &widget); if (GTK_IS_WIDGET (widget)) { while (widget && (!GDL_IS_DOCK (widget) || GDL_DOCK_OBJECT_GET_MASTER (widget) != master)) widget = widget->parent; if (widget) { gint win_w, win_h; /* verify that the pointer is still in that dock (the user could have moved it) */ gdk_window_get_geometry (widget->window, NULL, NULL, &win_w, &win_h, NULL); gdk_window_get_origin (widget->window, &win_x, &win_y); if (root_x >= win_x && root_x < win_x + win_w && root_y >= win_y && root_y < win_y + win_h) dock = GDL_DOCK (widget); } } } if (dock) { /* translate root coordinates into dock object coordinates (i.e. widget coordinates) */ gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y); x = root_x - win_x; y = root_y - win_y; may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock), x, y, &my_request); } else { GList *l; /* try to dock the item in all the docks in the ring in turn */ for (l = master->toplevel_docks; l; l = l->next) { dock = GDL_DOCK (l->data); /* translate root coordinates into dock object coordinates (i.e. widget coordinates) */ gdk_window_get_origin (GTK_WIDGET (dock)->window, &win_x, &win_y); x = root_x - win_x; y = root_y - win_y; may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock), x, y, &my_request); if (may_dock) break; } } if (!may_dock) { GtkRequisition req; /* Special case for GdlDockItems : they must respect the flags */ if(GDL_IS_DOCK_ITEM(item) && GDL_DOCK_ITEM(item)->behavior & GDL_DOCK_ITEM_BEH_NEVER_FLOATING) return; dock = NULL; my_request.target = GDL_DOCK_OBJECT ( gdl_dock_object_get_toplevel (request->applicant)); my_request.position = GDL_DOCK_FLOATING; gdl_dock_item_preferred_size (GDL_DOCK_ITEM (request->applicant), &req); my_request.rect.width = req.width; my_request.rect.height = req.height; my_request.rect.x = root_x - GDL_DOCK_ITEM (request->applicant)->dragoff_x; my_request.rect.y = root_y - GDL_DOCK_ITEM (request->applicant)->dragoff_y; /* setup extra docking information */ if (G_IS_VALUE (&my_request.extra)) g_value_unset (&my_request.extra); g_value_init (&my_request.extra, GDK_TYPE_RECTANGLE); g_value_set_boxed (&my_request.extra, &my_request.rect); } /* if we want to enforce GDL_DOCK_ITEM_BEH_NEVER_FLOATING */ /* the item must remain attached to the controller, otherwise */ /* it could be inserted in another floating dock */ /* so check for the flag at this moment */ else if(GDL_IS_DOCK_ITEM(item) && GDL_DOCK_ITEM(item)->behavior & GDL_DOCK_ITEM_BEH_NEVER_FLOATING && dock != GDL_DOCK(master->controller)) return; if (!(my_request.rect.x == request->rect.x && my_request.rect.y == request->rect.y && my_request.rect.width == request->rect.width && my_request.rect.height == request->rect.height && dock == master->_priv->rect_owner)) { /* erase the previous rectangle */ if (master->_priv->rect_drawn) gdl_dock_master_xor_rect (master); } /* set the new values */ *request = my_request; master->_priv->rect_owner = dock; /* draw the previous rectangle */ if (~master->_priv->rect_drawn) gdl_dock_master_xor_rect (master); }
static void gdl_dock_dock (GdlDockObject *object, GdlDockObject *requestor, GdlDockPlacement position, GValue *user_data) { GdlDock *dock; g_return_if_fail (GDL_IS_DOCK (object)); /* only dock items allowed at this time */ g_return_if_fail (GDL_IS_DOCK_ITEM (requestor)); dock = GDL_DOCK (object); if (position == GDL_DOCK_FLOATING) { GdlDockItem *item = GDL_DOCK_ITEM (requestor); gint x, y, width, height; if (user_data && G_VALUE_HOLDS (user_data, GDK_TYPE_RECTANGLE)) { GdkRectangle *rect; rect = g_value_get_boxed (user_data); x = rect->x; y = rect->y; width = rect->width; height = rect->height; } else { x = y = 0; width = height = -1; } gdl_dock_add_floating_item (dock, item, x, y, width, height); } else if (dock->root) { /* This is somewhat a special case since we know which item to pass the request on because we only have on child */ gdl_dock_object_dock (dock->root, requestor, position, NULL); gdl_dock_set_title (dock); } else { /* Item about to be added is root item. */ GtkWidget *widget = GTK_WIDGET (requestor); dock->root = requestor; GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED); gtk_widget_set_parent (widget, GTK_WIDGET (dock)); gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor)); /* Realize the item (create its corresponding GdkWindow) when GdlDock has been realized. */ if (GTK_WIDGET_REALIZED (dock)) gtk_widget_realize (widget); /* Map the widget if it's visible and the parent is visible and has been mapped. This is done to make sure that the GdkWindow is visible. */ if (GTK_WIDGET_VISIBLE (dock) && GTK_WIDGET_VISIBLE (widget)) { if (GTK_WIDGET_MAPPED (dock)) gtk_widget_map (widget); /* Make the widget resize. */ gtk_widget_queue_resize (widget); } gdl_dock_set_title (dock); } }
/* Determines the best dock item to dock a new item with the given placement. * It traverses the dock tree and (based on the placement) tries to find * the best located item wrt to the placement. The approach is to find the * largest item on/around the placement side (for side placements) and to * find the largest item for center placement. In most situations, this is * what user wants and the heuristic should be therefore sufficient. */ static GdlDockItem* gdl_dock_find_best_placement_item (GdlDockItem *dock_item, GdlDockPlacement placement, gint level /* for debugging */) { GdlDockItem *ret_item = NULL; if (GDL_IS_DOCK_PANED (dock_item)) { GtkOrientation orientation; GdlDockItem *dock_item_1, *dock_item_2; GList* children; children = gtk_container_get_children (GTK_CONTAINER (dock_item)); g_assert (g_list_length (children) == 2); g_object_get (dock_item, "orientation", &orientation, NULL); if ((orientation == GTK_ORIENTATION_HORIZONTAL && placement == GDL_DOCK_LEFT) || (orientation == GTK_ORIENTATION_VERTICAL && placement == GDL_DOCK_TOP)) { /* Return left or top pane widget */ ret_item = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (children->data), placement, level + 1); } else if ((orientation == GTK_ORIENTATION_HORIZONTAL && placement == GDL_DOCK_RIGHT) || (orientation == GTK_ORIENTATION_VERTICAL && placement == GDL_DOCK_BOTTOM)) { /* Return right or top pane widget */ ret_item = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (children->next->data), placement, level + 1); } else { /* Evaluate which of the two sides is bigger */ dock_item_1 = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (children->data), placement, level + 1); dock_item_2 = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (children->next->data), placement, level + 1); ret_item = gdl_dock_select_larger_item (dock_item_1, dock_item_2, placement, level); } g_list_free (children); } else if (GDL_IS_DOCK_ITEM (dock_item)) { ret_item = dock_item; } else { /* should not be here */ g_warning ("Should not reach here: %s:%d", __FUNCTION__, __LINE__); } return ret_item; }