a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * This file is part of the GNOME Devtools Libraries.
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * Copyright (C) 2002 Gustavo Gir�ldez <gustavo.giraldez@gmx.net>
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * This library is free software; you can redistribute it and/or
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * modify it under the terms of the GNU Lesser General Public
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * License as published by the Free Software Foundation; either
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * version 2.1 of the License, or (at your option) any later version.
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * This library is distributed in the hope that it will be useful,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * but WITHOUT ANY WARRANTY; without even the implied warranty of
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * Lesser General Public License for more details.
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * You should have received a copy of the GNU Lesser General Public
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * License along with this library; if not, write to the Free Software
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b/* Private prototypes */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_class_init (GdlDockPanedClass *klass);
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanisstatic void gdl_dock_paned_init (GdlDockPaned *paned);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic GObject *gdl_dock_paned_constructor (GType type,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_set_property (GObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_get_property (GObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_destroy (GtkObject *object);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_add (GtkContainer *container,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_forall (GtkContainer *container,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic GType gdl_dock_paned_child_type (GtkContainer *container);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic gboolean gdl_dock_paned_dock_request (GdlDockObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_dock (GdlDockObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic void gdl_dock_paned_set_orientation (GdlDockItem *item,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bstatic gboolean gdl_dock_paned_child_placement (GdlDockObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b/* ----- Class variables and definitions ----- */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b/* ----- Private functions ----- */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex ValavanisG_DEFINE_TYPE (GdlDockPaned, gdl_dock_paned, GDL_TYPE_DOCK_ITEM);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bgdl_dock_paned_class_init (GdlDockPanedClass *klass)
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_class->set_property = gdl_dock_paned_set_property;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_class->get_property = gdl_dock_paned_get_property;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_class->constructor = gdl_dock_paned_constructor;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_object_class->destroy = gdl_dock_paned_destroy;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b container_class->child_type = gdl_dock_paned_child_type;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b object_class->dock_request = gdl_dock_paned_dock_request;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b object_class->child_placement = gdl_dock_paned_child_placement;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b item_class->set_orientation = gdl_dock_paned_set_orientation;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b _("Position of the divider in pixels"),
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_return_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data));
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* chain the notification to the GdlDockPaned */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_notify (G_OBJECT (user_data), pspec->name);
9da72320667347f97b641753dd3b4591f95df939Alex Valavanis if (GDL_DOCK_ITEM_USER_ACTION (user_data) && !strcmp (pspec->name, "position"))
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_return_val_if_fail (user_data != NULL && GDL_IS_DOCK_PANED (user_data), FALSE);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b GDL_DOCK_ITEM_SET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b GDL_DOCK_ITEM_UNSET_FLAGS (user_data, GDL_DOCK_USER_ACTION);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* emit pending layout changed signal to track separator position */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_signal_emit_by_name (GDL_DOCK_OBJECT (paned)->master, "layout-changed");
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* create the container paned */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* get notification for propagation */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b (GCallback) gdl_dock_paned_notify_cb, (gpointer) item);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_signal_connect (item->child, "button-press-event",
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_signal_connect (item->child, "button-release-event",
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b (GCallback) gdl_dock_paned_button_cb, (gpointer) item);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_widget_set_parent (item->child, GTK_WIDGET (item));
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis g_object = G_OBJECT_CLASS (gdl_dock_paned_parent_class)-> constructor (type,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gdl_dock_paned_create_child (GDL_DOCK_PANED (g_object),
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* otherwise, the orientation was set as a construction
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b parameter and the child is already created */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* we need to call the virtual first, since in GdlDockDestroy our
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b children dock objects are detached */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis GTK_OBJECT_CLASS (gdl_dock_paned_parent_class)->destroy (object);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* after that we can remove the GtkNotebook */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_return_if_fail (container != NULL && widget != NULL);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* use GdlDockItem's forall */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis GTK_CONTAINER_CLASS (gdl_dock_paned_parent_class)->forall
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis (container, include_internals, callback, callback_data);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_container_foreach (GTK_CONTAINER (item->child), callback, callback_data);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b if (gtk_container_child_type (GTK_CONTAINER (item->child)) == G_TYPE_NONE)
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bgdl_dock_paned_request_foreach (GdlDockObject *object,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b may_dock = gdl_dock_object_dock_request (object, data->x, data->y, &my_request);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_return_val_if_fail (GDL_IS_DOCK_ITEM (object), FALSE);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* we get (x,y) in our allocation coordinates system */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* Get item's allocation. */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis gtk_widget_get_allocation (GTK_WIDGET (object), &alloc);
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis bw = gtk_container_get_border_width (GTK_CONTAINER (object));
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* Get coordinates relative to our window. */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* Check if coordinates are inside the widget. */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gdl_dock_item_preferred_size (GDL_DOCK_ITEM (my_request.applicant), &other);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gdl_dock_item_preferred_size (GDL_DOCK_ITEM (object), &my);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* It's inside our area. */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* Set docking indicator rectangle to the widget size. */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis my_request.rect.height = alloc.height - 2*bw;
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* See if it's in the border_width band. */
590e6c721a8540ebed996b273c08f35b1888426eJohan B. C. Engelen } else if (rel_x > alloc.width - (gint)bw) {
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
590e6c721a8540ebed996b273c08f35b1888426eJohan B. C. Engelen } else if (rel_y > alloc.height - (gint)bw) {
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b } else { /* Otherwise try our children. */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* give them coordinates in their allocation system... the
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b GtkPaned has no window, so our children allocation
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b coordinates are our window coordinates */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* the pointer is on the handle, so snap to top/bottom
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b if (item->orientation == GTK_ORIENTATION_HORIZONTAL) {
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b my_request.rect.y += my_request.rect.height * (1 - SPLIT_RATIO);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b my_request.rect.x += my_request.rect.width * (1 - SPLIT_RATIO);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b if (divider >= 0 && my_request.position != GDL_DOCK_CENTER) {
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_value_set_uint (&my_request.extra, (guint) divider);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* adjust returned coordinates so they are relative to
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b our allocation */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_return_if_fail (GDL_DOCK_ITEM (object)->child != NULL);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_get (G_OBJECT (requestor), "preferred_height", &temp, NULL);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b g_object_get (G_OBJECT (requestor), "preferred_width", &temp, NULL);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* see if we can dock the item in our paned */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_paned_pack1 (paned, GTK_WIDGET (requestor), FALSE, FALSE);
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis } else if (!child2 && position == GDL_DOCK_RIGHT) {
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_paned_pack2 (paned, GTK_WIDGET (requestor), TRUE, FALSE);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_paned_pack1 (paned, GTK_WIDGET (requestor), hresize, FALSE);
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis } else if (!child2 && position == GDL_DOCK_BOTTOM) {
9da72320667347f97b641753dd3b4591f95df939Alex Valavanis gtk_paned_pack2 (paned, GTK_WIDGET (requestor), hresize, FALSE);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b /* this will create another paned and reparent us there */
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis GDL_DOCK_OBJECT_CLASS (gdl_dock_paned_parent_class)->dock (object, requestor, position,
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gdl_dock_item_show_grip (GDL_DOCK_ITEM (requestor));
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b GDL_DOCK_OBJECT_SET_FLAGS (requestor, GDL_DOCK_ATTACHED);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gdl_dock_paned_create_child (GDL_DOCK_PANED (item), orientation);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_container_remove (GTK_CONTAINER (old_paned), child1);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b gtk_container_remove (GTK_CONTAINER (old_paned), child2);
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis GDL_DOCK_ITEM_CLASS (gdl_dock_paned_parent_class)->set_orientation (item, orientation);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_bgdl_dock_paned_child_placement (GdlDockObject *object,
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis if (GTK_WIDGET (child) == gtk_paned_get_child1 (paned))
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
d19de0ff8b0793e74e98429ded50868ce7e9f75cAlex Valavanis else if (GTK_WIDGET (child) == gtk_paned_get_child2 (paned))
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b pos = item->orientation == GTK_ORIENTATION_HORIZONTAL ?
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b/* ----- Public interface ----- */
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b paned = GDL_DOCK_PANED (g_object_new (GDL_TYPE_DOCK_PANED,