Beispiel #1
0
/* 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;
}
Beispiel #2
0
/* 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);
}