Beispiel #1
0
static void
gdl_dock_get_size (GtkWidget     *widget,
                   GtkOrientation orientation,
                   gint          *minimum,
                   gint          *natural)
{
    GdlDock       *dock;
    GtkContainer  *container;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    dock = GDL_DOCK (widget);
    container = GTK_CONTAINER (widget);

    *minimum = *natural = 0;

    /* make request to root */
    if (dock->priv->root && gtk_widget_get_visible (GTK_WIDGET (dock->priv->root))) {
        if (orientation == GTK_ORIENTATION_HORIZONTAL) {
            gtk_widget_get_preferred_width (GTK_WIDGET (dock->priv->root), minimum, natural);
        }
        else {
            gtk_widget_get_preferred_height (GTK_WIDGET (dock->priv->root), minimum, natural);
        }
    }
}
Beispiel #2
0
static void
gdl_dock_size_allocate (GtkWidget     *widget,
                        GtkAllocation *allocation)
{
    GdlDock       *dock;
    GtkContainer  *container;
    guint          border_width;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));
    
    dock = GDL_DOCK (widget);
    container = GTK_CONTAINER (widget);
    border_width = container->border_width;

    widget->allocation = *allocation;

    /* reduce allocation by border width */
    allocation->x += border_width;
    allocation->y += border_width;
    allocation->width = MAX (1, allocation->width - 2 * border_width);
    allocation->height = MAX (1, allocation->height - 2 * border_width);

    if (dock->root && GTK_WIDGET_VISIBLE (dock->root))
        gtk_widget_size_allocate (GTK_WIDGET (dock->root), allocation);
}
Beispiel #3
0
/**
 * gdl_dock_get_root:
 * @dock: A #GdlDockObject
 *
 * Get the first child of the #GdlDockObject.
 *
 * Returns: (allow-none) (transfer none): A #GdlDockObject or %NULL.
 */
GdlDockObject *
gdl_dock_get_root (GdlDock *dock)
{
    g_return_val_if_fail (GDL_IS_DOCK (dock), NULL);

    return dock->priv->root;
}
Beispiel #4
0
static void
gdl_dock_size_request (GtkWidget      *widget,
                       GtkRequisition *requisition)
{
    GdlDock       *dock;
    GtkContainer  *container;
    guint          border_width;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    dock = GDL_DOCK (widget);
    container = GTK_CONTAINER (widget);
    border_width = container->border_width;

    /* make request to root */
    if (dock->root && GTK_WIDGET_VISIBLE (dock->root))
        gtk_widget_size_request (GTK_WIDGET (dock->root), requisition);
    else {
        requisition->width = 0;
        requisition->height = 0;
    };

    requisition->width += 2 * border_width;
    requisition->height += 2 * border_width;

    widget->requisition = *requisition;
}
Beispiel #5
0
GdlDock *
gdl_dock_object_get_toplevel (GdlDockObject *object)
{
    GdlDockObject *parent = object;
    
    g_return_val_if_fail (object != NULL, NULL);

    while (parent && !GDL_IS_DOCK (parent))
        parent = gdl_dock_object_get_parent_object (parent);

    return parent ? GDL_DOCK (parent) : NULL;
}
static void
_gdl_dock_master_remove (GdlDockObject *object,
                         GdlDockMaster *master)
{
    g_return_if_fail (master != NULL && object != NULL);

    if (GDL_IS_DOCK (object)) {
        GList *found_link;

        found_link = g_list_find (master->toplevel_docks, object);
        if (found_link)
            master->toplevel_docks = g_list_delete_link (master->toplevel_docks,
                                                         found_link);
        if (object == master->controller) {
            GList *last;
            GdlDockObject *new_controller = NULL;
            
            /* now find some other non-automatic toplevel to use as a
               new controller.  start from the last dock, since it's
               probably a non-floating and manual */
            last = g_list_last (master->toplevel_docks);
            while (last) {
                if (!GDL_DOCK_OBJECT_AUTOMATIC (last->data)) {
                    new_controller = GDL_DOCK_OBJECT (last->data);
                    break;
                }
                last = last->prev;
            };

            if (new_controller) {
                /* the new controller gets the ref (implicitly of course) */
                master->controller = new_controller;
            } else {
                master->controller = NULL;
                /* no controller, no master */
                g_object_unref (master);
            }
        }
    }
    /* disconnect dock object signals */
    g_signal_handlers_disconnect_matched (object, G_SIGNAL_MATCH_DATA, 
                                          0, 0, NULL, NULL, master);

    /* unref the object from the hash if it's there */
    if (object->name) {
        GdlDockObject *found_object;
        found_object = g_hash_table_lookup (master->dock_objects, object->name);
        if (found_object == object) {
            g_hash_table_remove (master->dock_objects, object->name);
            g_object_unref (object);
        }
    }
}
Beispiel #7
0
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 */
}
Beispiel #8
0
static void
gdl_dock_notify_cb (GObject    *object,
                    GParamSpec *pspec,
                    gpointer    user_data)
{
    GdlDock *dock;
    
    g_return_if_fail (object != NULL || GDL_IS_DOCK (object));
    
    dock = GDL_DOCK (object);
    dock->_priv->auto_title = FALSE;
    gdl_dock_set_title (dock);
}
Beispiel #9
0
static void
gdl_dock_forall (GtkContainer *container,
                 gboolean      include_internals,
                 GtkCallback   callback,
                 gpointer      callback_data)
{
    GdlDock *dock;

    g_return_if_fail (container != NULL);
    g_return_if_fail (GDL_IS_DOCK (container));
    g_return_if_fail (callback != NULL);

    dock = GDL_DOCK (container);

    if (dock->root)
        (*callback) (GTK_WIDGET (dock->root), callback_data);
}
Beispiel #10
0
static gboolean 
gdl_dock_floating_configure_event_cb (GtkWidget         *widget,
                                      GdkEventConfigure *event,
                                      gpointer           user_data)
{
    GdlDock *dock;
    
    g_return_val_if_fail (user_data != NULL && GDL_IS_DOCK (user_data), TRUE);

    dock = GDL_DOCK (user_data);
    dock->_priv->float_x = event->x;
    dock->_priv->float_y = event->y;
    dock->_priv->width = event->width;
    dock->_priv->height = event->height;

    return FALSE;
}
Beispiel #11
0
static void
gdl_dock_size_allocate (GtkWidget     *widget,
                        GtkAllocation *allocation)
{
    GdlDock       *dock;
    GtkContainer  *container;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    dock = GDL_DOCK (widget);
    container = GTK_CONTAINER (widget);

    gtk_widget_set_allocation (widget, allocation);

    if (dock->priv->root && gtk_widget_get_visible (GTK_WIDGET (dock->priv->root)))
        gtk_widget_size_allocate (GTK_WIDGET (dock->priv->root), allocation);
}
Beispiel #12
0
static void
gdl_dock_map (GtkWidget *widget)
{
    GtkWidget *child;
    GdlDock   *dock;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    dock = GDL_DOCK (widget);

    GTK_WIDGET_CLASS (gdl_dock_parent_class)->map (widget);

    if (dock->priv->root) {
        child = GTK_WIDGET (dock->priv->root);
        if (gtk_widget_get_visible (child) && !gtk_widget_get_mapped (child))
            gtk_widget_map (child);
    }
}
Beispiel #13
0
static void
gdl_dock_map (GtkWidget *widget)
{
    GtkWidget *child;
    GdlDock   *dock;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    dock = GDL_DOCK (widget);

    GDL_CALL_PARENT (GTK_WIDGET_CLASS, map, (widget));

    if (dock->root) {
        child = GTK_WIDGET (dock->root);
        if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
            gtk_widget_map (child);
    }
}
Beispiel #14
0
static void
gdl_dock_notify_cb (GObject    *object,
                    GParamSpec *pspec,
                    gpointer    user_data)
{
    GdlDock *dock;
    gchar* long_name;

    g_return_if_fail (object != NULL || GDL_IS_DOCK (object));

    g_object_get (object, "long-name", &long_name, NULL);

    if (long_name)
    {
        dock = GDL_DOCK (object);
        dock->priv->auto_title = FALSE;
        gdl_dock_set_title (dock);
    }
    g_free (long_name);
}
Beispiel #15
0
static void
gdl_dock_hide (GtkWidget *widget)
{
    GdlDock *dock;
    
    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));
    
    GDL_CALL_PARENT (GTK_WIDGET_CLASS, hide, (widget));
    
    dock = GDL_DOCK (widget);
    if (dock->_priv->floating && dock->_priv->window)
        gtk_widget_hide (dock->_priv->window);

    if (GDL_DOCK_IS_CONTROLLER (dock)) {
        gdl_dock_master_foreach_toplevel (GDL_DOCK_OBJECT_GET_MASTER (dock),
                                          FALSE, (GFunc) gdl_dock_foreach_automatic,
                                          gtk_widget_hide);
    }
}
Beispiel #16
0
static void
gdl_dock_hide (GtkWidget *widget)
{
    GdlDock *dock;
    GdlDockMaster *master;

    g_return_if_fail (widget != NULL);
    g_return_if_fail (GDL_IS_DOCK (widget));

    GTK_WIDGET_CLASS (gdl_dock_parent_class)->hide (widget);

    dock = GDL_DOCK (widget);
    if (dock->priv->floating && dock->priv->window)
        gtk_widget_hide (dock->priv->window);

    master = GDL_DOCK_MASTER (gdl_dock_object_get_master (GDL_DOCK_OBJECT (dock)));
    if (GDL_DOCK (gdl_dock_master_get_controller (master)) == dock) {
        gdl_dock_master_foreach_toplevel (master,
                                          FALSE, (GFunc) gdl_dock_foreach_automatic,
                                          gtk_widget_hide);
    }
}
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);
}
Beispiel #19
0
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);
    }
}
Beispiel #20
0
static gboolean
gdl_dock_dock_request (GdlDockObject  *object,
                       gint            x,
                       gint            y,
                       GdlDockRequest *request)
{
    GdlDock            *dock;
    guint               bw;
    gint                rel_x, rel_y;
    GtkAllocation      *alloc;
    gboolean            may_dock = FALSE;
    GdlDockRequest      my_request;

    g_return_val_if_fail (GDL_IS_DOCK (object), FALSE);

    /* we get (x,y) in our allocation coordinates system */
    
    dock = GDL_DOCK (object);
    
    /* Get dock size. */
    alloc = &(GTK_WIDGET (dock)->allocation);
    bw = GTK_CONTAINER (dock)->border_width;

    /* Get coordinates relative to our allocation area. */
    rel_x = x - alloc->x;
    rel_y = y - alloc->y;

    if (request)
        my_request = *request;
        
    /* Check if coordinates are in GdlDock widget. */
    if (rel_x > 0 && rel_x < alloc->width &&
        rel_y > 0 && rel_y < alloc->height) {

        /* It's inside our area. */
        may_dock = TRUE;

	/* Set docking indicator rectangle to the GdlDock size. */
        my_request.rect.x = alloc->x + bw;
        my_request.rect.y = alloc->y + bw;
        my_request.rect.width = alloc->width - 2*bw;
        my_request.rect.height = alloc->height - 2*bw;

	/* If GdlDock has no root item yet, set the dock itself as 
	   possible target. */
        if (!dock->root) {
            my_request.position = GDL_DOCK_TOP;
            my_request.target = object;
        } else {
            my_request.target = dock->root;

            /* See if it's in the border_width band. */
            if (rel_x < bw) {
                my_request.position = GDL_DOCK_LEFT;
                my_request.rect.width *= SPLIT_RATIO;
            } else if (rel_x > alloc->width - bw) {
                my_request.position = GDL_DOCK_RIGHT;
                my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
                my_request.rect.width *= SPLIT_RATIO;
            } else if (rel_y < bw) {
                my_request.position = GDL_DOCK_TOP;
                my_request.rect.height *= SPLIT_RATIO;
            } else if (rel_y > alloc->height - bw) {
                my_request.position = GDL_DOCK_BOTTOM;
                my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
                my_request.rect.height *= SPLIT_RATIO;
            } else {
                /* Otherwise try our children. */
                /* give them allocation coordinates (we are a
                   GTK_NO_WINDOW) widget */
                may_dock = gdl_dock_object_dock_request (GDL_DOCK_OBJECT (dock->root), 
                                                         x, y, &my_request);
            }
        }
    }

    if (may_dock && request)
        *request = my_request;
    
    return may_dock;
}