/** * gdl_dock_add_item: * @dock: A #GdlDock widget * @item: A #GdlDockItem widget * @placement: A position for the widget * * Dock in @dock, the widget @item at the position defined by @placement. The * function takes care of finding the right parent widget eventually creating * it if needed. */ void gdl_dock_add_item (GdlDock *dock, GdlDockItem *item, GdlDockPlacement placement) { GdlDockObject *placeholder; GdlDockObject *parent = NULL; GdlDockPlacement place; g_return_if_fail (dock != NULL); g_return_if_fail (item != NULL); /* Check if a placeholder widget already exist in the same dock */ placeholder = gdl_dock_master_get_object (GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock))), gdl_dock_object_get_name (GDL_DOCK_OBJECT (item))); if ((placeholder != GDL_DOCK_OBJECT (item)) && (placeholder != NULL)) { if (gdl_dock_object_get_toplevel (placeholder) == dock) { parent = gdl_dock_object_get_parent_object (placeholder); } else { gtk_widget_destroy (GTK_WIDGET (placeholder)); } } if (parent && gdl_dock_object_child_placement (parent, placeholder, &place)) { gdl_dock_object_freeze (GDL_DOCK_OBJECT (parent)); gtk_widget_destroy (GTK_WIDGET (placeholder)); gdl_dock_object_dock (GDL_DOCK_OBJECT (parent), GDL_DOCK_OBJECT (item), place, NULL); gdl_dock_object_thaw (GDL_DOCK_OBJECT (parent)); } else if (placement == GDL_DOCK_FLOATING) /* Add the item to a new floating dock */ gdl_dock_add_floating_item (dock, item, 0, 0, -1, -1); else { GdlDockItem *best_dock_item; /* Non-floating item. */ if (dock->priv->root) { GdlDockPlacement local_placement; GtkRequisition preferred_size; best_dock_item = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (dock->priv->root), placement, 0); local_placement = gdl_dock_refine_placement (dock, best_dock_item, placement); gdl_dock_object_dock (GDL_DOCK_OBJECT (best_dock_item), GDL_DOCK_OBJECT (item), local_placement, NULL); } else { gdl_dock_object_dock (GDL_DOCK_OBJECT (dock), GDL_DOCK_OBJECT (item), placement, NULL); } } }
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); }