/* Depending on where the dock item (where new item will be docked) locates * in the dock, we might need to change the docking placement. If the * item is does not touches the center of dock, the new-item-to-dock would * require a center dock on this item. */ static GdlDockPlacement gdl_dock_refine_placement (GdlDock *dock, GdlDockItem *dock_item, GdlDockPlacement placement) { GtkRequisition object_size; gdl_dock_item_preferred_size (dock_item, &object_size); g_return_val_if_fail (GTK_WIDGET (dock)->allocation.width > 0, placement); g_return_val_if_fail (GTK_WIDGET (dock)->allocation.height > 0, placement); g_return_val_if_fail (object_size.width > 0, placement); g_return_val_if_fail (object_size.height > 0, placement); if (placement == GDL_DOCK_LEFT || placement == GDL_DOCK_RIGHT) { /* Check if dock_object touches center in terms of width */ if (GTK_WIDGET (dock)->allocation.width/2 > object_size.width) { return GDL_DOCK_CENTER; } } else if (placement == GDL_DOCK_TOP || placement == GDL_DOCK_BOTTOM) { /* Check if dock_object touches center in terms of height */ if (GTK_WIDGET (dock)->allocation.height/2 > object_size.height) { return GDL_DOCK_CENTER; } } return placement; }
/* Determines the larger item of the two based on the placement: * for left/right placement, height determines it. * for top/bottom placement, width determines it. * for center placement, area determines it. */ static GdlDockItem* gdl_dock_select_larger_item (GdlDockItem *dock_item_1, GdlDockItem *dock_item_2, GdlDockPlacement placement, gint level /* for debugging */) { GtkRequisition size_1, size_2; g_return_val_if_fail (dock_item_1 != NULL, dock_item_2); g_return_val_if_fail (dock_item_2 != NULL, dock_item_1); gdl_dock_item_preferred_size (dock_item_1, &size_1); gdl_dock_item_preferred_size (dock_item_2, &size_2); g_return_val_if_fail (size_1.width > 0, dock_item_2); g_return_val_if_fail (size_1.height > 0, dock_item_2); g_return_val_if_fail (size_2.width > 0, dock_item_1); g_return_val_if_fail (size_2.height > 0, dock_item_1); if (placement == GDL_DOCK_LEFT || placement == GDL_DOCK_RIGHT) { /* For left/right placement, height is what matters */ return (size_1.height >= size_2.height? dock_item_1 : dock_item_2); } else if (placement == GDL_DOCK_TOP || placement == GDL_DOCK_BOTTOM) { /* For top/bottom placement, width is what matters */ return (size_1.width >= size_2.width? dock_item_1 : dock_item_2); } else if (placement == GDL_DOCK_CENTER) { /* For center place, area is what matters */ return ((size_1.width * size_1.height) >= (size_2.width * size_2.height)? dock_item_1 : dock_item_2); } else if (placement == GDL_DOCK_NONE) { return dock_item_1; } else { g_warning ("Should not reach here: %s:%d", __FUNCTION__, __LINE__); } return dock_item_1; }
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); }