summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tvb@src.gnome.org>2006-10-26 00:45:22 +0000
committerTristan Van Berkom <tvb@src.gnome.org>2006-10-26 00:45:22 +0000
commit90ba661ff990afb46e400b59459b0fc64f647ef8 (patch)
tree3a04cb1802510edbd7aa7508291de49a9dafb2a0
parent3a66616b3a9133032106b3a24e046cbc058e8c30 (diff)
downloadglade-90ba661ff990afb46e400b59459b0fc64f647ef8.tar.gz
o integrate ui into one main window. o A GtkNotebook is used to display
* src/glade-project-window.c: o integrate ui into one main window. o A GtkNotebook is used to display GladeDesignView's. * src/glade-project-view.[ch]: add "item-activated" signal. * src/glade-design-layout.[ch], src/glade-design-view.[ch]: new files. * src/glade-widget.[ch]: o Added functions for embedding toplevel GladeWidgets o glade_widget_show() modified to manage embedding of toplevels.
-rw-r--r--ChangeLog16
-rw-r--r--INSTALL16
-rw-r--r--src/Makefile.am4
-rw-r--r--src/glade-design-layout.c742
-rw-r--r--src/glade-design-layout.h64
-rw-r--r--src/glade-design-view.c194
-rw-r--r--src/glade-design-view.h73
-rw-r--r--src/glade-project-view.c27
-rw-r--r--src/glade-project-view.h2
-rw-r--r--src/glade-project-window.c1160
-rw-r--r--src/glade-project-window.h5
-rw-r--r--src/glade-widget.c539
-rw-r--r--src/glade-widget.h6
13 files changed, 2110 insertions, 738 deletions
diff --git a/ChangeLog b/ChangeLog
index ca58449a..bf40f31c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2006-10-25 Vincent Geddes <vincent.geddes@gmail.com>
+
+ * src/glade-project-window.c:
+ o integrate ui into one main window.
+ o A GtkNotebook is used to display GladeDesignView's.
+
+ * src/glade-project-view.[ch]: add "item-activated" signal.
+
+ * src/glade-design-layout.[ch], src/glade-design-view.[ch]:
+ new files.
+
+ * src/glade-widget.[ch]:
+ o Added functions for embedding toplevel GladeWidgets
+ o glade_widget_show() modified to manage embedding of
+ toplevels.
+
2006-10-20 Tristan Van Berkom <tvb@gnome.org>
* configure.in: Removed the python check
diff --git a/INSTALL b/INSTALL
index 56b077d6..23e5f25d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -102,16 +102,16 @@ for another architecture.
Installation Names
==================
-By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PREFIX'.
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PREFIX', the package will
-use PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
@@ -159,7 +159,7 @@ where SYSTEM can have one of these forms:
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
+use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
diff --git a/src/Makefile.am b/src/Makefile.am
index 99179b43..42a5685f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,8 @@ libgladeui_1_la_SOURCES = \
glade-palette-item.c \
glade-palette-box.c \
glade-palette-expander.c \
+ glade-design-layout.c \
+ glade-design-view.c \
glade-cursor.c \
glade-property.c \
glade-property-class.c \
@@ -114,6 +116,8 @@ libgladeuiinclude_HEADERS = \
glade-palette-item.h \
glade-palette-box.h \
glade-palette-expander.h \
+ glade-design-layout.h \
+ glade-design-view.h \
glade-cursor.h \
glade-widget.h \
glade-widget-adaptor.h \
diff --git a/src/glade-design-layout.c b/src/glade-design-layout.c
new file mode 100644
index 00000000..adb95bbe
--- /dev/null
+++ b/src/glade-design-layout.c
@@ -0,0 +1,742 @@
+/*
+ * glade-design-layout.c
+ *
+ * Copyright (C) 2006 Vincent Geddes
+ *
+ * Authors:
+ * Vincent Geddes <vgeddes@metroweb.co.za>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glade-design-layout.h"
+
+#include "glade.h"
+
+#include <gtk/gtk.h>
+
+#define GLADE_DESIGN_LAYOUT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
+ GLADE_TYPE_DESIGN_LAYOUT, \
+ GladeDesignLayoutPrivate))
+
+#define OUTLINE_WIDTH 4
+#define PADDING 12
+
+
+typedef enum
+{
+ GLADE_ACTIVITY_NONE,
+ GLADE_ACTIVITY_RESIZE_WIDTH,
+ GLADE_ACTIVITY_RESIZE_HEIGHT,
+ GLADE_ACTIVITY_RESIZE_WIDTH_AND_HEIGHT
+
+} GladeActivity;
+
+typedef enum
+{
+ GLADE_REGION_EAST = 1,
+ GLADE_REGION_SOUTH,
+ GLADE_REGION_SOUTH_EAST,
+ GLADE_REGION_WEST_OF_SOUTH_EAST,
+ GLADE_REGION_NORTH_OF_SOUTH_EAST
+
+} GladePointerRegion;
+
+struct _GladeDesignLayoutPrivate
+{
+ GdkWindow *event_window;
+
+ GdkCursor *cursor_resize_bottom;
+ GdkCursor *cursor_resize_right;
+ GdkCursor *cursor_resize_bottom_right;
+
+ /* state machine */
+ GladeActivity activity; /* the current activity */
+ GtkRequisition *current_size_request;
+ int dx; /* child.width - event.pointer.x */
+ int dy; /* child.height - event.pointer.y */
+ int new_width; /* user's new requested width */
+ int new_height; /* user's new requested height */
+};
+
+static GtkBinClass *parent_class = NULL;
+
+
+G_DEFINE_TYPE(GladeDesignLayout, glade_design_layout, GTK_TYPE_BIN)
+
+static GladePointerRegion
+glade_design_layout_get_pointer_region (GladeDesignLayout *layout, int x, int y)
+{
+ GladeDesignLayoutPrivate *priv;
+ GtkAllocation *child_allocation;
+ GladePointerRegion region = 0;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+
+ child_allocation = &GTK_BIN (layout)->child->allocation;
+
+ if ((x >= (child_allocation->x + child_allocation->width)) &&
+ (x < (child_allocation->x + child_allocation->width + OUTLINE_WIDTH)))
+ {
+ if ((y < (child_allocation->y + child_allocation->height - OUTLINE_WIDTH)) &&
+ (y >= child_allocation->y - OUTLINE_WIDTH))
+ region = GLADE_REGION_EAST;
+
+ else if ((y < (child_allocation->y + child_allocation->height)) &&
+ (y >= (child_allocation->y + child_allocation->height - OUTLINE_WIDTH)))
+ region = GLADE_REGION_NORTH_OF_SOUTH_EAST;
+
+ else if ((y < (child_allocation->y + child_allocation->height + OUTLINE_WIDTH)) &&
+ (y >= (child_allocation->y + child_allocation->height)))
+ region = GLADE_REGION_SOUTH_EAST;
+ }
+ else if ((y >= (child_allocation->y + child_allocation->height)) &&
+ (y < (child_allocation->y + child_allocation->height + OUTLINE_WIDTH)))
+ {
+ if ((x < (child_allocation->x + child_allocation->width - OUTLINE_WIDTH)) &&
+ (x >= child_allocation->x - OUTLINE_WIDTH))
+ region = GLADE_REGION_SOUTH;
+
+ else if ((x < (child_allocation->x + child_allocation->width)) &&
+ (x >= (child_allocation->x + child_allocation->width - OUTLINE_WIDTH)))
+ region = GLADE_REGION_WEST_OF_SOUTH_EAST;
+
+ else if ((x < (child_allocation->x + child_allocation->width + OUTLINE_WIDTH)) &&
+ (x >= (child_allocation->x + child_allocation->width)))
+ region = GLADE_REGION_SOUTH_EAST;
+ }
+
+ return region;
+}
+
+
+
+static void
+child_size_request_handler (GtkWidget *widget,
+ GtkRequisition *req,
+ GladeDesignLayout *layout)
+{
+ GladeDesignLayoutPrivate *priv;
+ int new_width, new_height;
+ int old_width, old_height;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+
+ priv->current_size_request->width = req->width;
+ priv->current_size_request->height = req->height;
+
+ new_width = widget->allocation.width;
+ new_height = widget->allocation.height;
+
+ if (req->width > new_width)
+ new_width = req->width;
+
+ if (req->height > new_height)
+ new_height = req->height;
+
+ if ((new_width != widget->allocation.width) ||
+ (new_height != widget->allocation.height))
+ {
+ old_width = widget->requisition.width;
+ old_height = widget->requisition.height;
+
+ gtk_widget_set_size_request (widget, new_width, new_height);
+
+ if (old_width > new_width)
+ widget->requisition.width = old_width;
+
+ if (old_height > new_height)
+ widget->requisition.height = old_height;
+
+ gtk_widget_queue_draw (GTK_WIDGET (layout));
+ }
+
+
+
+}
+
+static void
+glade_design_layout_handle_event (GladeDesignLayout *layout, GdkEvent* ev)
+{
+ GladeDesignLayoutPrivate *priv;
+ GtkWidget *widget;
+ GtkWidget *child;
+ GladeWidget *child_glade_widget;
+ GladePointerRegion region;
+ gint x, y;
+ gint new_width, new_height;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+ widget = GTK_WIDGET (layout);
+ child = gtk_bin_get_child (GTK_BIN (layout));
+
+ if (child == NULL)
+ return;
+
+ switch (ev->type)
+ {
+ case GDK_MOTION_NOTIFY:
+
+ if (((GdkEventMotion *)ev)->is_hint)
+ gdk_window_get_pointer (priv->event_window, &x, &y, NULL);
+ else {
+ x = (int) ((GdkEventMotion *)ev)->x;
+ y = (int) ((GdkEventMotion *)ev)->y;
+ }
+
+ child_glade_widget = glade_widget_get_from_gobject (child);
+
+ if (priv->activity == GLADE_ACTIVITY_RESIZE_WIDTH)
+ {
+ new_width = x - priv->dx - PADDING - OUTLINE_WIDTH;
+
+ if (new_width < priv->current_size_request->width)
+ new_width = priv->current_size_request->width;
+
+ //g_object_set (child, "width-request", new_width,
+ // NULL);
+
+ glade_widget_property_set_enabled (child_glade_widget, "default-width", TRUE);
+ glade_widget_property_set (child_glade_widget, "default-width", new_width, NULL);
+
+ gtk_widget_queue_draw (widget);
+ }
+ else if (priv->activity == GLADE_ACTIVITY_RESIZE_HEIGHT)
+ {
+ new_height = y - priv->dy - PADDING - OUTLINE_WIDTH;
+
+ if (new_height < priv->current_size_request->height)
+ new_height = priv->current_size_request->height;
+
+ //g_object_set (child, "height-request", new_height,
+ // NULL);
+
+ glade_widget_property_set_enabled (child_glade_widget, "default-height", TRUE);
+ glade_widget_property_set (child_glade_widget, "default-height", new_height, NULL);
+
+ gtk_widget_queue_draw (widget);
+ }
+ else if (priv->activity == GLADE_ACTIVITY_RESIZE_WIDTH_AND_HEIGHT)
+ {
+ new_width = x - priv->dx - PADDING - OUTLINE_WIDTH;
+ new_height = y - priv->dy - PADDING - OUTLINE_WIDTH;
+
+ if (new_width < priv->current_size_request->width)
+ new_width = priv->current_size_request->width;
+ if (new_height < priv->current_size_request->height)
+ new_height = priv->current_size_request->height;
+
+ //g_object_set (child, "width-request", new_width,
+ // "height-request", new_height,
+ // NULL);
+
+ glade_widget_property_set_enabled (child_glade_widget, "default-width", TRUE);
+ glade_widget_property_set_enabled (child_glade_widget, "default-height", TRUE);
+ glade_widget_property_set (child_glade_widget, "default-width", new_width, NULL);
+ glade_widget_property_set (child_glade_widget, "default-height", new_height, NULL);
+
+ gtk_widget_queue_draw (widget);
+ }
+ else
+ {
+ region = glade_design_layout_get_pointer_region (layout, x, y);
+
+ if (region == GLADE_REGION_EAST)
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_right);
+
+ else if (region == GLADE_REGION_SOUTH)
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom);
+
+ else if (region == GLADE_REGION_SOUTH_EAST ||
+ region == GLADE_REGION_WEST_OF_SOUTH_EAST ||
+ region == GLADE_REGION_NORTH_OF_SOUTH_EAST)
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom_right);
+
+ else
+ gdk_window_set_cursor (widget->window, NULL);
+ }
+ break;
+
+ case GDK_BUTTON_PRESS:
+
+ x = (int) ((GdkEventButton *) ev)->x;
+ y = (int) ((GdkEventButton *) ev)->y;
+
+ region = glade_design_layout_get_pointer_region (layout, x, y);
+
+ if (((GdkEventButton *) ev)->button == 1) {
+
+ priv->dx = x - (child->allocation.x + child->allocation.width);
+ priv->dy = y - (child->allocation.y + child->allocation.height);
+
+ if (region == GLADE_REGION_EAST) {
+ priv->activity = GLADE_ACTIVITY_RESIZE_WIDTH;
+
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_right);
+ }
+ if (region == GLADE_REGION_SOUTH) {
+ priv->activity = GLADE_ACTIVITY_RESIZE_HEIGHT;
+
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom);
+ }
+ if (region == GLADE_REGION_SOUTH_EAST) {
+ priv->activity = GLADE_ACTIVITY_RESIZE_WIDTH_AND_HEIGHT;
+
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom_right);
+ }
+ if (region == GLADE_REGION_WEST_OF_SOUTH_EAST) {
+ priv->activity = GLADE_ACTIVITY_RESIZE_WIDTH_AND_HEIGHT;
+
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom_right);
+ }
+ if (region == GLADE_REGION_NORTH_OF_SOUTH_EAST) {
+ priv->activity = GLADE_ACTIVITY_RESIZE_WIDTH_AND_HEIGHT;
+
+ gdk_window_set_cursor (widget->window, priv->cursor_resize_bottom_right);
+ }
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+
+ priv->activity = GLADE_ACTIVITY_NONE;
+ gdk_window_set_cursor (widget->window, NULL);
+
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+
+ if (priv->activity == GLADE_ACTIVITY_NONE)
+ gdk_window_set_cursor (widget->window, NULL);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static gboolean
+glade_design_layout_leave_notify_event (GtkWidget *widget, GdkEventCrossing *ev)
+{
+ GtkWidget *child;
+
+ child = ((GtkBin *) widget)->child;
+
+ if (child && GTK_IS_WINDOW (child))
+ glade_design_layout_handle_event (GLADE_DESIGN_LAYOUT (widget), (GdkEvent *) ev);
+
+ return FALSE;
+}
+
+static gboolean
+glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
+{
+ GtkWidget *child;
+
+ child = ((GtkBin *) widget)->child;
+
+ if (child && GTK_IS_WINDOW (child))
+ glade_design_layout_handle_event (GLADE_DESIGN_LAYOUT (widget), (GdkEvent *) ev);
+
+ return FALSE;
+}
+
+static gboolean
+glade_design_layout_button_press_event (GtkWidget *widget, GdkEventButton *ev)
+{
+ GtkWidget *child;
+
+ child = ((GtkBin *) widget)->child;
+
+ if (child && GTK_IS_WINDOW (child))
+ glade_design_layout_handle_event (GLADE_DESIGN_LAYOUT (widget), (GdkEvent *) ev);
+
+ return FALSE;
+}
+
+static gboolean
+glade_design_layout_button_release_event (GtkWidget *widget, GdkEventButton *ev)
+{
+ GtkWidget *child;
+
+ child = ((GtkBin *) widget)->child;
+
+ if (child && GTK_IS_WINDOW (child))
+ glade_design_layout_handle_event (GLADE_DESIGN_LAYOUT (widget), (GdkEvent *) ev);
+
+ return FALSE;
+}
+
+static void
+glade_design_layout_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ GladeDesignLayoutPrivate *priv;
+ GtkRequisition child_requisition;
+ GtkWidget *child;
+ gint child_width = 0;
+ gint child_height = 0;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ child = GTK_BIN (widget)->child;
+ if (child && GTK_WIDGET_VISIBLE (child))
+ {
+ gtk_widget_size_request (child, &child_requisition);
+
+ if (GTK_IS_WINDOW (child))
+ gtk_window_get_default_size (GTK_WINDOW (child), &child_width, &child_height);
+
+ child_width = MAX (child_width, child_requisition.width);
+ child_height = MAX (child_height, child_requisition.height);
+
+ requisition->width = MAX (requisition->width,
+ 2 * PADDING + child_width + 2 * OUTLINE_WIDTH);
+
+ requisition->height = MAX (requisition->height,
+ 2 * PADDING + child_height + 2 * OUTLINE_WIDTH);
+ }
+
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+
+}
+
+static void
+glade_design_layout_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ GladeDesignLayoutPrivate *priv;
+ GtkRequisition child_requisition;
+ GtkAllocation child_allocation;
+ GtkWidget *child;
+ gint border_width;
+ gint child_width = 0;
+ gint child_height = 0;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ widget->allocation = *allocation;
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ if (priv->event_window)
+ gdk_window_move_resize (priv->event_window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ allocation->width - 2 * border_width ,
+ allocation->height - 2 * border_width);
+
+ }
+
+ child = GTK_BIN (widget)->child;
+ if (child && GTK_WIDGET_VISIBLE (child))
+ {
+ gtk_widget_get_child_requisition (child, &child_requisition);
+
+ if (GTK_IS_WINDOW (child))
+ {
+ gtk_window_get_default_size (GTK_WINDOW (child), &child_width, &child_height);
+
+ child_width = MAX (child_width, priv->current_size_request->width);
+ child_height = MAX (child_height, priv->current_size_request->height);
+ }
+ else
+ {
+ child_width = child_requisition.width;
+ child_height = child_requisition.height;
+ }
+
+ child_allocation.x = widget->allocation.x + border_width + PADDING + OUTLINE_WIDTH;
+ child_allocation.y = widget->allocation.y + border_width + PADDING + OUTLINE_WIDTH;
+
+ child_allocation.width = child_width - 2 * border_width;
+ child_allocation.height = child_height - 2 * border_width;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+}
+
+static void
+glade_design_layout_map (GtkWidget *widget)
+{
+ GladeDesignLayoutPrivate *priv;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ if (priv->event_window)
+ gdk_window_show (priv->event_window);
+
+ GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+}
+
+static void
+glade_design_layout_unmap (GtkWidget *widget)
+{
+ GladeDesignLayoutPrivate *priv;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+
+ if (priv->event_window)
+ gdk_window_hide (priv->event_window);
+}
+
+static void
+glade_design_layout_realize (GtkWidget *widget)
+{
+ GladeDesignLayoutPrivate *priv;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint border_width;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ attributes.x = widget->allocation.x + border_width;
+ attributes.y = widget->allocation.y + border_width;
+ attributes.width = widget->allocation.width - 2 * border_width;
+ attributes.height = widget->allocation.height - 2 * border_width;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.event_mask = gtk_widget_get_events (widget)
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_EXPOSURE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ widget->window = gtk_widget_get_parent_window (widget);
+ g_object_ref (widget->window);
+
+ priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (priv->event_window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+glade_design_layout_unrealize (GtkWidget *widget)
+{
+ GladeDesignLayoutPrivate *priv;
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+
+ if (priv->event_window)
+ {
+ gdk_window_set_user_data (priv->event_window, NULL);
+ gdk_window_destroy (priv->event_window);
+ priv->event_window = NULL;
+ }
+
+ GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+
+}
+
+static void
+glade_design_layout_add (GtkContainer *container, GtkWidget *widget)
+{
+ GladeDesignLayout *layout;
+
+ layout = GLADE_DESIGN_LAYOUT (container);
+
+ layout->priv->current_size_request->width = 0;
+ layout->priv->current_size_request->height = 0;
+
+ g_signal_connect (G_OBJECT (widget), "size-request",
+ G_CALLBACK (child_size_request_handler),
+ container);
+
+ GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
+}
+
+static void
+glade_design_layout_remove (GtkContainer *container, GtkWidget *widget)
+{
+ g_signal_handlers_disconnect_by_func(G_OBJECT (widget),
+ G_CALLBACK (child_size_request_handler),
+ container);
+
+ GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
+}
+
+static void
+glade_design_layout_dispose (GObject *object)
+{
+ GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+
+ if (priv->cursor_resize_bottom != NULL) {
+ gdk_cursor_unref (priv->cursor_resize_bottom);
+ priv->cursor_resize_bottom = NULL;
+ }
+ if (priv->cursor_resize_right != NULL) {
+ gdk_cursor_unref (priv->cursor_resize_right);
+ priv->cursor_resize_right = NULL;
+ }
+ if (priv->cursor_resize_bottom_right != NULL) {
+ gdk_cursor_unref (priv->cursor_resize_bottom_right);
+ priv->cursor_resize_bottom_right = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+glade_design_layout_finalize (GObject *object)
+{
+ GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+
+ g_free (priv->current_size_request);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+glade_design_layout_expose_event (GtkWidget *widget, GdkEventExpose *ev)
+{
+ GladeDesignLayout *layout;
+ GdkGC *outline_gc;
+ GdkGCValues gc_values;
+ GtkWidget *child;
+ double x, y, w, h;
+ int border_width;
+
+ layout = GLADE_DESIGN_LAYOUT (widget);
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->base_gc [GTK_WIDGET_STATE (widget)],
+ TRUE,
+ widget->allocation.x + border_width,
+ widget->allocation.y + border_width,
+ widget->allocation.width - 2 * border_width,
+ widget->allocation.height - 2 * border_width);
+
+ child = GTK_BIN (widget)->child;
+
+ if (child && GTK_WIDGET_VISIBLE (child))
+ {
+ x = child->allocation.x - OUTLINE_WIDTH / 2;
+ y = child->allocation.y - OUTLINE_WIDTH / 2;
+ w = child->allocation.width + OUTLINE_WIDTH;
+ h = child->allocation.height + OUTLINE_WIDTH;
+
+ /* configure outline_gc */
+ outline_gc = gdk_gc_new (widget->window);
+ gdk_gc_copy (outline_gc, widget->style->light_gc[GTK_STATE_SELECTED]);
+ gc_values.line_width = OUTLINE_WIDTH;
+ gdk_gc_set_values (outline_gc, &gc_values, GDK_GC_LINE_WIDTH);
+
+ gdk_draw_rectangle (widget->window,
+ outline_gc,
+ FALSE,
+ x, y, w, h);
+
+ g_object_unref (outline_gc);
+
+ if (GTK_WIDGET_NO_WINDOW (child))
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_STATE_NORMAL],
+ TRUE,
+ child->allocation.x, child->allocation.y,
+ child->allocation.width, child->allocation.height);
+
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, ev);
+}
+
+static void
+glade_design_layout_init (GladeDesignLayout *layout)
+{
+ GladeDesignLayoutPrivate *priv;
+
+ layout->priv = priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (layout), GTK_NO_WINDOW);
+
+ priv->event_window = NULL;
+ priv->activity = GLADE_ACTIVITY_NONE;
+
+ priv->current_size_request = g_new0 (GtkRequisition, 1);
+
+ priv->cursor_resize_bottom = gdk_cursor_new (GDK_BOTTOM_SIDE);
+ priv->cursor_resize_right = gdk_cursor_new (GDK_RIGHT_SIDE);
+ priv->cursor_resize_bottom_right = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
+
+ priv->new_width = -1;
+ priv->new_height = -1;
+
+}
+
+static void
+glade_design_layout_class_init (GladeDesignLayoutClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ parent_class = g_type_class_peek_parent (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+ container_class = GTK_CONTAINER_CLASS (class);
+
+ object_class->dispose = glade_design_layout_dispose;
+ object_class->finalize = glade_design_layout_finalize;
+
+ container_class->add = glade_design_layout_add;
+ container_class->remove = glade_design_layout_remove;
+
+ widget_class->motion_notify_event = glade_design_layout_motion_notify_event;
+ widget_class->leave_notify_event = glade_design_layout_leave_notify_event;
+ widget_class->button_press_event = glade_design_layout_button_press_event;
+ widget_class->button_release_event = glade_design_layout_button_release_event;
+ widget_class->realize = glade_design_layout_realize;
+ widget_class->unrealize = glade_design_layout_unrealize;
+ widget_class->map = glade_design_layout_map;
+ widget_class->unmap = glade_design_layout_unmap;
+ widget_class->expose_event = glade_design_layout_expose_event;
+ widget_class->size_request = glade_design_layout_size_request;
+ widget_class->size_allocate = glade_design_layout_size_allocate;
+
+ g_type_class_add_private (object_class, sizeof (GladeDesignLayoutPrivate));
+
+}
+
+GtkWidget*
+glade_design_layout_new (void)
+{
+ GladeDesignLayout *layout;
+
+ layout = g_object_new (GLADE_TYPE_DESIGN_LAYOUT, NULL);
+
+ return GTK_WIDGET (layout);
+}
diff --git a/src/glade-design-layout.h b/src/glade-design-layout.h
new file mode 100644
index 00000000..1b6e00c2
--- /dev/null
+++ b/src/glade-design-layout.h
@@ -0,0 +1,64 @@
+/*
+ * glade-design-layout.h
+ *
+ * Copyright (C) 2006 Vincent Geddes
+ *
+ * Authors:
+ * Vincent Geddes <vgeddes@metroweb.co.za>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __GLADE_DESIGN_LAYOUT_H__
+#define __GLADE_DESIGN_LAYOUT_H__
+
+#include <gtk/gtkbin.h>
+
+G_BEGIN_DECLS
+
+#define GLADE_TYPE_DESIGN_LAYOUT (glade_design_layout_get_type ())
+#define GLADE_DESIGN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_DESIGN_LAYOUT, GladeDesignLayout))
+#define GLADE_DESIGN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_DESIGN_LAYOUT, GladeDesignLayoutClass))
+#define GLADE_IS_DESIGN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_DESIGN_LAYOUT))
+#define GLADE_IS_DESIGN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_DESIGN_LAYOUT))
+#define GLADE_DESIGN_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_DESIGN_LAYOUT, GladeDesignLayoutClass))
+
+typedef struct _GladeDesignLayout GladeDesignLayout;
+typedef struct _GladeDesignLayoutPrivate GladeDesignLayoutPrivate;
+typedef struct _GladeDesignLayoutClass GladeDesignLayoutClass;
+
+struct _GladeDesignLayout
+{
+ GtkBin bin; /* The parent is an event box */
+
+ GladeDesignLayoutPrivate *priv;
+};
+
+struct _GladeDesignLayoutClass
+{
+ GtkBinClass parent_class;
+
+};
+
+
+GType glade_design_layout_get_type (void) G_GNUC_CONST;
+
+GtkWidget *glade_design_layout_new (void);
+
+
+G_END_DECLS
+
+#endif /* __GLADE_DESIGN_LAYOUT_H__ */
diff --git a/src/glade-design-view.c b/src/glade-design-view.c
new file mode 100644
index 00000000..623df149
--- /dev/null
+++ b/src/glade-design-view.c
@@ -0,0 +1,194 @@
+/*
+ * glade-design-view.c
+ *
+ * Copyright (C) 2006 Vincent Geddes
+ *
+ * Authors:
+ * Vincent Geddes <vincent.geddes@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANDESIGN_VIEWILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glade.h"
+#include "glade-utils.h"
+#include "glade-design-view.h"
+#include "glade-design-layout.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#define GLADE_DESIGN_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GLADE_TYPE_DESIGN_VIEW, GladeDesignViewPrivate))
+
+#define GLADE_DESIGN_VIEW_KEY "GLADE_DESIGN_VIEW_KEY"
+
+enum
+{
+ PROP_0,
+ PROP_PROJECT,
+};
+
+struct _GladeDesignViewPrivate
+{
+ GtkWidget *layout;
+
+ GladeProject *project;
+};
+
+static GtkVBoxClass *parent_class = NULL;
+
+
+G_DEFINE_TYPE(GladeDesignView, glade_design_view, GTK_TYPE_VBOX)
+
+static void
+glade_design_view_set_project (GladeDesignView *view, GladeProject *project)
+{
+ g_return_if_fail (GLADE_IS_PROJECT (project));
+
+ view->priv->project = project;
+
+ g_object_set_data (G_OBJECT (view->priv->project), GLADE_DESIGN_VIEW_KEY, view);
+
+}
+
+static void
+glade_design_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PROJECT:
+ glade_design_view_set_project (GLADE_DESIGN_VIEW (object), g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+glade_design_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PROJECT:
+ g_value_set_object (value, GLADE_DESIGN_VIEW (object)->priv->project);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+glade_design_view_init (GladeDesignView *view)
+{
+ GtkWidget *sw;
+ GtkWidget *viewport;
+
+ view->priv = GLADE_DESIGN_VIEW_GET_PRIVATE (view);
+
+ view->priv->project = NULL;
+ view->priv->layout = glade_design_layout_new ();
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
+
+ viewport = gtk_viewport_new (NULL, NULL);
+ gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (viewport), view->priv->layout);
+ gtk_container_add (GTK_CONTAINER (sw), viewport);
+
+ gtk_widget_show (sw);
+ gtk_widget_show (viewport);
+ gtk_widget_show (view->priv->layout);
+
+ gtk_box_pack_start (GTK_BOX (view), sw, TRUE, TRUE, 0);
+
+ gtk_container_set_border_width (GTK_CONTAINER (view), 0);
+
+}
+
+static void
+glade_design_view_class_init (GladeDesignViewClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ object_class = G_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->get_property = glade_design_view_get_property;
+ object_class->set_property = glade_design_view_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_PROJECT,
+ g_param_spec_object ("project",
+ "Project",
+ "The project for this view",
+ GLADE_TYPE_PROJECT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (GladeDesignViewPrivate));
+}
+
+GladeProject*
+glade_design_view_get_project (GladeDesignView *view)
+{
+ g_return_val_if_fail (GLADE_IS_DESIGN_VIEW (view), NULL);
+
+ return view->priv->project;
+
+}
+
+GtkWidget *
+glade_design_view_new (GladeProject *project)
+{
+ GladeDesignView *view;
+
+ g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+
+ view = g_object_new (GLADE_TYPE_DESIGN_VIEW,
+ "project", project,
+ NULL);
+
+ return GTK_WIDGET (view);
+}
+
+GladeDesignView *
+glade_design_view_get_from_project (GladeProject *project)
+{
+ gpointer p;
+
+ g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+
+ p = g_object_get_data (G_OBJECT (project), GLADE_DESIGN_VIEW_KEY);
+
+ return (p != NULL) ? GLADE_DESIGN_VIEW (p) : NULL;
+
+}
+
+GladeDesignLayout *
+glade_design_view_get_layout (GladeDesignView *view)
+{
+ return GLADE_DESIGN_LAYOUT (view->priv->layout);
+}
diff --git a/src/glade-design-view.h b/src/glade-design-view.h
new file mode 100644
index 00000000..3e655153
--- /dev/null
+++ b/src/glade-design-view.h
@@ -0,0 +1,73 @@
+/*
+ * glade-design-view.h
+ *
+ * Copyright (C) 2006 Vincent Geddes
+ *
+ * Authors:
+ * Vincent Geddes <vincent.geddes@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANDESIGN_VIEWILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __GLADE_DESIGN_VIEW_H__
+#define __GLADE_DESIGN_VIEW_H__
+
+#include "glade.h"
+#include "glade-project.h"
+#include "glade-design-layout.h"
+
+#include <gtk/gtkvbox.h>
+
+G_BEGIN_DECLS
+
+#define GLADE_TYPE_DESIGN_VIEW (glade_design_view_get_type ())
+#define GLADE_DESIGN_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_DESIGN_VIEW, GladeDesignView))
+#define GLADE_DESIGN_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_DESIGN_VIEW, GladeDesignViewClass))
+#define GLADE_IS_DESIGN_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_DESIGN_VIEW))
+#define GLADE_IS_DESIGN_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_DESIGN_VIEW))
+#define GLADE_DESIGN_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_DESIGN_VIEW, GladeDesignViewClass))
+
+typedef struct _GladeDesignView GladeDesignView;
+typedef struct _GladeDesignViewPrivate GladeDesignViewPrivate;
+typedef struct _GladeDesignViewClass GladeDesignViewClass;
+
+struct _GladeDesignView
+{
+ GtkVBox vbox; /* The parent is a box */
+
+ GladeDesignViewPrivate *priv;
+};
+
+struct _GladeDesignViewClass
+{
+ GtkVBoxClass parent_class;
+
+};
+
+GType glade_design_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget *glade_design_view_new (GladeProject *project);
+
+GladeProject *glade_design_view_get_project (GladeDesignView *view);
+
+GladeDesignView *glade_design_view_get_from_project (GladeProject *project);
+
+GladeDesignLayout *glade_design_view_get_layout (GladeDesignView *view);
+
+
+G_END_DECLS
+
+#endif /* __GLADE_DESIGN_VIEW_H__ */
diff --git a/src/glade-project-view.c b/src/glade-project-view.c
index cd9e3c08..a79e372c 100644
--- a/src/glade-project-view.c
+++ b/src/glade-project-view.c
@@ -37,6 +37,12 @@
#define GLADE_PROJECT_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object),\
GLADE_TYPE_PROJECT_VIEW, \
GladeProjectViewPrivate))
+
+enum
+{
+ ITEM_ACTIVATED,
+ LAST_SIGNAL
+};
enum
{
@@ -100,6 +106,7 @@ typedef struct
GList *list;
} GPVAccumPair;
+static guint glade_project_view_signals[LAST_SIGNAL] = {0};
static GtkScrolledWindow *parent_class = NULL;
static void gpv_project_data_free (GPVProjectData *pdata);
@@ -664,6 +671,24 @@ glade_project_view_class_init (GladeProjectViewClass *class)
class->remove_item = glade_project_view_remove_item;
class->widget_name_changed = glade_project_view_widget_name_changed;
class->selection_update = glade_project_view_selection_update;
+
+ /**
+ * GladeProjectView::item-activated:
+ * @view the #GladeProjectView which received the signal.
+ * @widget: the #GladeWidget that was activated.
+ *
+ * Emitted when a item is activated in the GtkTreeView of a GladeProjectView.
+ */
+ glade_project_view_signals[ITEM_ACTIVATED] =
+ g_signal_new ("item_activated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GladeProjectViewClass, item_activated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GLADE_TYPE_WIDGET);
g_type_class_add_private (object_class, sizeof (GladeProjectViewPrivate));
}
@@ -761,7 +786,7 @@ glade_project_view_init (GladeProjectView *view)
#endif
priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->model));
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), TRUE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
/* the view now holds a reference, we can get rid of our own */
g_object_unref (G_OBJECT (priv->model));
diff --git a/src/glade-project-view.h b/src/glade-project-view.h
index 731aea9d..2b8a5086 100644
--- a/src/glade-project-view.h
+++ b/src/glade-project-view.h
@@ -32,6 +32,8 @@ struct _GladeProjectViewClass
void (*remove_item) (GladeProjectView *view,
GladeWidget *widget);
void (*widget_name_changed) (GladeProjectView *view,
+ GladeWidget *widget);
+ void (*item_activated) (GladeProjectView *view,
GladeWidget *widget);
/* Selection update is when the project changes the selection
diff --git a/src/glade-project-window.c b/src/glade-project-window.c
index a99c98b9..a59e2ea4 100644
--- a/src/glade-project-window.c
+++ b/src/glade-project-window.c
@@ -31,21 +31,28 @@
#include <gtk/gtkstock.h>
#include "glade.h"
-
+#include "glade-design-view.h"
#include "glade-project-window.h"
-#define CONFIG_RECENT_PROJECTS "Recent Projects"
-#define CONFIG_RECENT_PROJECTS_MAX "max_recent_projects"
-
#define GLADE_ACTION_GROUP_STATIC "GladeStatic"
#define GLADE_ACTION_GROUP_PROJECT "GladeProject"
-#define GLADE_ACTION_GROUP_RECENT "GladeRecent"
#define GLADE_ACTION_GROUP_PROJECTS_LIST_MENU "GladeProjectsList"
-struct _GladeProjectWindowPriv {
+#define READONLY_INDICATOR (_("[Read Only]"))
+
+#define GLADE_PROJECT_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
+ GLADE_TYPE_PROJECT_WINDOW, \
+ GladeProjectWindowPrivate))
+
+struct _GladeProjectWindowPrivate
+{
/* Application widgets */
GtkWidget *window; /* Main window */
GtkWidget *main_vbox;
+
+ GtkWidget *notebook;
+ GladeDesignView *active_view;
+ gint num_tabs;
GtkWidget *statusbar; /* A pointer to the status bar. */
guint statusbar_menu_context_id; /* The context id of the menu bar */
@@ -56,22 +63,12 @@ struct _GladeProjectWindowPriv {
GtkActionGroup *static_actions; /* All the static actions */
GtkActionGroup *project_actions;/* All the project actions */
- GtkActionGroup *recent_actions; /* Recent projects actions */
GtkActionGroup *projects_list_menu_actions;/* Projects list menu actions */
-
- GQueue *recent_projects; /* A GtkAction queue */
- gint rp_max; /* Maximum Recent Projects entries */
-
- GtkWindow *palette_window; /* The window that will contain the palette */
- GtkWindow *editor_window; /* The window that will contain the editor */
- GtkWidget *expand; /* Expand/Collapse the treeview */
- GtkWidget *collapse;
+
+ GtkLabel *label; /* the title of property editor dock */
};
-
-#define READONLY_INDICATOR (_("[read-only]"))
-
const gint GLADE_WIDGET_TREE_WIDTH = 230;
const gint GLADE_WIDGET_TREE_HEIGHT = 300;
const gint GLADE_PALETTE_DEFAULT_HEIGHT = 450;
@@ -80,176 +77,89 @@ static gpointer parent_class = NULL;
static void gpw_refresh_undo_redo (GladeProjectWindow *gpw);
+
+G_DEFINE_TYPE(GladeProjectWindow, glade_project_window, GLADE_TYPE_APP)
+
static void
gpw_refresh_title (GladeProjectWindow *gpw)
{
- GladeProject *active_project;
- gchar *title, *project_name;
+ GladeProject *project;
+ gchar *title, *name = NULL;
- active_project = glade_app_get_project ();
- if (active_project)
+ if (gpw->priv->active_view)
{
- project_name = glade_project_display_name (active_project, TRUE, FALSE, FALSE);
+ project = glade_design_view_get_project (gpw->priv->active_view);
+
+ name = glade_project_display_name (project, TRUE, FALSE, FALSE);
- if (active_project->readonly != FALSE)
- title = g_strdup_printf ("%s %s - %s", project_name,
+ if (project->readonly != FALSE)
+ title = g_strdup_printf ("%s %s - %s", name,
READONLY_INDICATOR, g_get_application_name ());
else
- title = g_strdup_printf ("%s - %s", project_name,
+ title = g_strdup_printf ("%s - %s", name,
g_get_application_name ());
- g_free (project_name);
+ g_free (name);
}
else
title = g_strdup_printf ("%s", g_get_application_name ());
gtk_window_set_title (GTK_WINDOW (gpw->priv->window), title);
- g_free (title);
-}
-
-static void
-gpw_new_cb (GtkAction *action, GladeProjectWindow *gpw)
-{
- glade_project_window_new_project (gpw);
-}
-
-static void
-gpw_recent_project_delete (GtkAction *action, GladeProjectWindow *gpw)
-{
- guint merge_id = GPOINTER_TO_UINT(g_object_get_data (G_OBJECT (action), "merge_id"));
-
- gtk_ui_manager_remove_ui(gpw->priv->ui, merge_id);
- gtk_action_group_remove_action (gpw->priv->recent_actions, action);
- g_queue_remove (gpw->priv->recent_projects, action);
- gtk_ui_manager_ensure_update (gpw->priv->ui);
-}
-static void
-gpw_recent_project_open_cb (GtkAction *action, GladeProjectWindow *gpw)
-{
- gchar *path = (gchar *) g_object_get_data (G_OBJECT (action), "project_path");
-
- if (path == NULL) return;
-
- if (!glade_app_is_project_loaded (path))
- gpw_recent_project_delete (action, gpw);
-
- glade_project_window_open_project (gpw, path);
-}
-
-static gint gpw_rp_cmp (gconstpointer a, gconstpointer b)
-{
- /* a is a GtkAction from the queue and b is a gchar* */
- return strcmp (g_object_get_data (G_OBJECT (a), "project_path"), b);
+ g_free (title);
}
static void
-gpw_recent_project_add (GladeProjectWindow *gpw, const gchar *project_path)
+project_selection_changed_cb (GladeProject *project, GladeProjectWindow *gpw)
{
- GtkAction *action;
- gchar *label, *action_name;
- guint merge_id;
+ GladeWidget *glade_widget = NULL;
+ GtkLabel *label;
+ GList *list;
+ gchar *text;
+ gint num;
- /* Need to check if it's already loaded */
- if (g_queue_find_custom (gpw->priv->recent_projects,
- project_path, gpw_rp_cmp))
- return;
+ g_return_if_fail (GLADE_IS_PROJECT (project));
+ g_return_if_fail (GLADE_IS_PROJECT_WINDOW (gpw));
- label = glade_util_duplicate_underscores (project_path);
- if (!label) return;
-
- action_name = g_strdup_printf ("open[%s]", project_path);
- /* We don't want '/'s in the menu path */
- glade_util_replace (action_name, '/', ' ');
-
- /* Add action */
- action = gtk_action_new (action_name, label, NULL, NULL);
- gtk_action_group_add_action_with_accel (gpw->priv->recent_actions, action, "");
- g_signal_connect (G_OBJECT (action), "activate", (GCallback)gpw_recent_project_open_cb, gpw);
-
- /* Add menuitem */
- merge_id = gtk_ui_manager_new_merge_id (gpw->priv->ui);
- gtk_ui_manager_add_ui (gpw->priv->ui, merge_id,
- "/MenuBar/FileMenu/Recents", label, action_name,
- GTK_UI_MANAGER_MENUITEM, TRUE);
-
- /* Set extra data to action */
- g_object_set_data(G_OBJECT (action), "merge_id", GUINT_TO_POINTER(merge_id));
- g_object_set_data_full (G_OBJECT (action), "project_path", g_strdup (project_path), g_free);
-
- /* Push action into recent project queue */
- g_queue_push_head (gpw->priv->recent_projects, action);
-
- /* If there is more entries than rp_max, delete the last one.*/
- if (g_queue_get_length(gpw->priv->recent_projects) > gpw->priv->rp_max)
- {
- GtkAction *last_action = (GtkAction *)g_queue_pop_tail(gpw->priv->recent_projects);
- gpw_recent_project_delete (last_action, gpw);
- }
-
- /* Set submenu sensitive */
- gtk_widget_set_sensitive (gtk_ui_manager_get_widget
- (gpw->priv->ui, "/MenuBar/FileMenu/Recents"),
- TRUE);
- g_free (label);
- g_free (action_name);
-}
+ label = gpw->priv->label;
-static void
-gpw_recent_project_config_load (GladeProjectWindow *gpw)
-{
- gchar *filename, key[8];
- gint i;
-
- gpw->priv->rp_max = g_key_file_get_integer (
- glade_app_get_config (),
- CONFIG_RECENT_PROJECTS,
- CONFIG_RECENT_PROJECTS_MAX, NULL);
-
- /* Some default value for recent projects maximum */
- if (gpw->priv->rp_max == 0) gpw->priv->rp_max = 5;
-
- for (i = 0; i < gpw->priv->rp_max; i++)
+ /* Only update the editor if the selection has changed on
+ * the currently active project.
+ */
+ if (glade_app_get_editor() &&
+ (project == glade_app_get_project ()))
{
- g_snprintf(key, 8, "%d", i);
+ list = glade_project_selection_get (project);
+ num = g_list_length (list);
+
+ if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data))
+ {
- filename = g_key_file_get_string (glade_app_get_config (),
- CONFIG_RECENT_PROJECTS, key, NULL);
- if (filename)
+ glade_widget = glade_widget_get_from_gobject (G_OBJECT (list->data));
+
+ text = g_strdup_printf ("%s [%s] - Properties",
+ glade_widget_get_name (glade_widget),
+ G_OBJECT_TYPE_NAME (glade_widget->object));
+
+ gtk_label_set_text (label, text);
+
+ g_free (text);
+ }
+ else
{
- if (g_file_test (filename, G_FILE_TEST_EXISTS))
- gpw_recent_project_add (gpw, filename);
+ gtk_label_set_text (label, "Properties");
}
- else break;
+
}
+
}
-static void
-gpw_recent_project_config_save (GladeProjectWindow *gpw)
+static GladeDesignView *
+glade_project_window_get_active_view (GladeProjectWindow *gpw)
{
- GKeyFile *config = glade_app_get_config ();
- GList *list;
- gchar key[8];
- gint i = 0;
-
- g_key_file_remove_group (config, CONFIG_RECENT_PROJECTS, NULL);
-
- g_key_file_set_integer (config,
- CONFIG_RECENT_PROJECTS,
- CONFIG_RECENT_PROJECTS_MAX,
- gpw->priv->rp_max);
-
- for (list = gpw->priv->recent_projects->tail; list; list = list->prev, i++)
- {
- gchar *path = g_object_get_data (G_OBJECT (list->data), "project_path");
-
- if( path )
- {
- g_snprintf (key, 8, "%d", i);
- g_key_file_set_string (config, CONFIG_RECENT_PROJECTS,
- key, path);
- }
- }
+ g_return_val_if_fail (GLADE_IS_PROJECT_WINDOW (gpw), NULL);
+
+ return gpw->priv->active_view;
}
static void
@@ -279,6 +189,43 @@ gpw_refresh_projects_list_item (GladeProjectWindow *gpw, GladeProject *project)
}
static void
+gpw_refresh_next_prev_project_sensitivity (GladeProjectWindow *gpw)
+{
+ GladeDesignView *view;
+ GtkAction *action;
+ gint view_number;
+
+ view = glade_project_window_get_active_view (gpw);
+
+ if (view != NULL)
+ {
+ view_number = gtk_notebook_page_num (GTK_NOTEBOOK (gpw->priv->notebook), GTK_WIDGET (view));
+ g_return_if_fail (view_number >= 0);
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "PreviousProject");
+ gtk_action_set_sensitive (action, view_number != 0);
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "NextProject");
+ gtk_action_set_sensitive (action,
+ view_number < gtk_notebook_get_n_pages (GTK_NOTEBOOK (gpw->priv->notebook)) - 1);
+ }
+ else
+ {
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "PreviousProject");
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = gtk_action_group_get_action (gpw->priv->project_actions, "NextProject");
+ gtk_action_set_sensitive (action, FALSE);
+ }
+}
+
+static void
+gpw_new_cb (GtkAction *action, GladeProjectWindow *gpw)
+{
+ glade_project_window_new_project (gpw);
+}
+
+static void
gpw_project_notify_handler_cb (GladeProject *project, GParamSpec *spec, GladeProjectWindow *gpw)
{
GtkAction *action;
@@ -323,69 +270,87 @@ gpw_clipboard_notify_handler_cb (GladeClipboard *clipboard, GParamSpec *spec, Gl
}
}
+static GtkWidget*
+gpw_construct_dock_item (GladeProjectWindow *gpw, const gchar *title, GtkWidget *child)
+{
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *alignment;
+
+ vbox = gtk_vbox_new (FALSE, 0);
+
+ label = gtk_label_new (title);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (label), 2, 5);
+
+ alignment = gtk_alignment_new (0, 0, 1, 1);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 0, 12);
+
+ gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (alignment), label);
+
+ gtk_box_pack_start (GTK_BOX (vbox), child, TRUE, TRUE, 0);
+
+ gtk_widget_show (alignment);
+ gtk_widget_show (label);
+ gtk_widget_show (child);
+ gtk_widget_show (vbox);
+
+ /* FIXME: naughty */
+ g_object_set_data (G_OBJECT (vbox), "dock-label", label);
+
+ return vbox;
+}
+
static void
-gpw_set_sensitivity_according_to_project (GladeProjectWindow *gpw, GladeProject *project)
+gpw_set_sensitivity_according_to_project (GladeProjectWindow *window, GladeProject *project)
{
GtkAction *action;
- gboolean is_first_in_list = FALSE, is_last_in_list = FALSE;
- action = gtk_action_group_get_action (gpw->priv->project_actions, "Save");
+ action = gtk_action_group_get_action (window->priv->project_actions, "Save");
gtk_action_set_sensitive (action,
!glade_project_get_readonly (project));
- action = gtk_action_group_get_action (gpw->priv->project_actions, "Cut");
+ action = gtk_action_group_get_action (window->priv->project_actions, "Cut");
gtk_action_set_sensitive (action,
glade_project_get_has_selection (project));
- action = gtk_action_group_get_action (gpw->priv->project_actions, "Copy");
+ action = gtk_action_group_get_action (window->priv->project_actions, "Copy");
gtk_action_set_sensitive (action,
glade_project_get_has_selection (project));
- action = gtk_action_group_get_action (gpw->priv->project_actions, "Paste");
+ action = gtk_action_group_get_action (window->priv->project_actions, "Paste");
gtk_action_set_sensitive (action,
glade_clipboard_get_has_selection
(glade_app_get_clipboard ()));
- action = gtk_action_group_get_action (gpw->priv->project_actions, "Delete");
+ action = gtk_action_group_get_action (window->priv->project_actions, "Delete");
gtk_action_set_sensitive (action,
glade_project_get_has_selection (project));
- action = GTK_ACTION (g_object_get_data (G_OBJECT (project), "project-list-action"));
- g_return_if_fail (GTK_IS_ACTION (action));
- is_first_in_list = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "is-first-in-list"));
- is_last_in_list = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "is-last-in-list"));
-
-
- action = gtk_action_group_get_action (gpw->priv->project_actions, "PreviousProject");
- gtk_action_set_sensitive (action, !is_first_in_list);
-
- action = gtk_action_group_get_action (gpw->priv->project_actions, "NextProject");
- gtk_action_set_sensitive (action, !is_last_in_list);
+ gpw_refresh_next_prev_project_sensitivity (window);
}
static void
-gpw_projects_list_menu_activate_cb (GtkAction *action, GladeProjectWindow *gpw)
+gpw_projects_list_menu_activate_cb (GtkAction *action, GladeProjectWindow *window)
{
- GladeProject *project;
-
- project = GLADE_PROJECT (g_object_get_data (G_OBJECT (action), "project"));
- g_assert (GLADE_IS_PROJECT (project));
-
- glade_app_set_project (project);
+ gint n;
- gpw_set_sensitivity_according_to_project (gpw, project);
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) == FALSE)
+ return;
- gpw_refresh_title (gpw);
+ n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook), n);
}
static void
-gpw_refresh_projects_list_menu (GladeProjectWindow *gpw)
+gpw_refresh_projects_list_menu (GladeProjectWindow *window)
{
- GladeProjectWindowPriv *p = gpw->priv;
- GList *projects, *actions, *l;
+ GladeProjectWindowPrivate *p = window->priv;
+ GList *actions, *l;
GSList *group = NULL;
- gint i = 0;
+ gint n, i;
guint id;
if (p->projects_list_menu_ui_id != 0)
@@ -395,65 +360,70 @@ gpw_refresh_projects_list_menu (GladeProjectWindow *gpw)
actions = gtk_action_group_list_actions (p->projects_list_menu_actions);
for (l = actions; l != NULL; l = l->next)
{
- g_signal_handlers_disconnect_by_func
- (GTK_ACTION (l->data),
- G_CALLBACK (gpw_projects_list_menu_activate_cb), gpw);
+ g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
+ G_CALLBACK (gpw_projects_list_menu_activate_cb), window);
gtk_action_group_remove_action (p->projects_list_menu_actions, GTK_ACTION (l->data));
}
g_list_free (actions);
- projects = glade_app_get_projects ();
+ n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (p->notebook));
- id = (projects != NULL) ? gtk_ui_manager_new_merge_id (p->ui) : 0;
- p->projects_list_menu_ui_id = id;
+ id = (n > 0) ? gtk_ui_manager_new_merge_id (p->ui) : 0;
/* Add an action for each project */
- for (l = projects; l != NULL; l = l->next, i++)
+ for (i = 0; i < n; i++)
{
+ GtkWidget *view;
GladeProject *project;
GtkRadioAction *action;
gchar *action_name;
gchar *project_name;
- gchar *tooltip = NULL;
+ gchar *name;
+ gchar *tooltip;
gchar *accel;
- project = GLADE_PROJECT (l->data);
+ view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (p->notebook), i);
+ project = glade_design_view_get_project (GLADE_DESIGN_VIEW (view));
- action_name = g_strdup_printf ("Project_%d", i);
- project_name = glade_project_display_name (project, TRUE, FALSE, TRUE);
- if (project->readonly != FALSE && project->path)
- tooltip = g_strdup_printf ("%s %s",project->path, READONLY_INDICATOR);
- else
- tooltip = g_strdup (project->path);
- action = gtk_radio_action_new (action_name, project_name, tooltip, NULL, i);
+ /* NOTE: the action is associated to the position of the tab in
+ * the notebook not to the tab itself! This is needed to work
+ * around the gtk+ bug #170727: gtk leaves around the accels
+ * of the action. Since the accel depends on the tab position
+ * the problem is worked around, action with the same name always
+ * get the same accel.
+ */
+ action_name = g_strdup_printf ("Tab_%d", i);
+ project_name = glade_project_display_name (project, TRUE, FALSE, FALSE);
+ name = glade_util_duplicate_underscores (project_name);
+ tooltip = g_strdup_printf (_("Activate %s"), project_name);
+
+ /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
+ accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
+
+ action = gtk_radio_action_new (action_name,
+ name,
+ tooltip,
+ NULL,
+ i);
/* Link action and project */
g_object_set_data (G_OBJECT (project), "project-list-action", action);
g_object_set_data (G_OBJECT (action), "project", project);
- /* add additional data for Previous/Next Project actions */
- if (l->prev == NULL)
- g_object_set_data (G_OBJECT (action), "is-first-in-list", GINT_TO_POINTER (TRUE));
- if (l->next == NULL)
- g_object_set_data (G_OBJECT (action), "is-last-in-list", GINT_TO_POINTER (TRUE));
-
if (group != NULL)
gtk_radio_action_set_group (action, group);
+ /* note that group changes each time we add an action, so it must be updated */
group = gtk_radio_action_get_group (action);
- /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
- accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
-
- gtk_action_group_add_action_with_accel (p->projects_list_menu_actions, GTK_ACTION (action), accel);
+ gtk_action_group_add_action_with_accel (p->projects_list_menu_actions,
+ GTK_ACTION (action),
+ accel);
g_signal_connect (action, "activate",
G_CALLBACK (gpw_projects_list_menu_activate_cb),
- gpw);
-
- if (project == glade_app_get_project ())
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+ window);
gtk_ui_manager_add_ui (p->ui, id,
"/MenuBar/ProjectMenu/ProjectsListPlaceholder",
@@ -461,36 +431,19 @@ gpw_refresh_projects_list_menu (GladeProjectWindow *gpw)
GTK_UI_MANAGER_MENUITEM,
FALSE);
+ if (GLADE_DESIGN_VIEW (view) == p->active_view)
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
g_object_unref (action);
g_free (action_name);
g_free (project_name);
+ g_free (name);
g_free (tooltip);
g_free (accel);
}
-}
-static gchar *
-gpw_get_recent_dir (GladeProjectWindow *gpw)
-{
- const gchar *project_path;
- gchar *dir = NULL;
-
- if (gpw->priv->recent_projects->head)
- {
- GtkAction *action = gpw->priv->recent_projects->head->data;
-
- project_path = g_object_get_data (G_OBJECT (action), "project_path");
-
- if (project_path)
- dir = g_path_get_dirname (project_path);
- }
-
- /* this is wrong on win32 */
- if (!dir)
- dir = g_strdup (g_get_home_dir ());
-
- return dir;
+ p->projects_list_menu_ui_id = id;
}
static void
@@ -498,16 +451,10 @@ gpw_open_cb (GtkAction *action, GladeProjectWindow *gpw)
{
GtkWidget *filechooser;
gchar *path = NULL;
- gchar *dir;
filechooser = glade_util_file_dialog_new (_("Open\342\200\246"), GTK_WINDOW (gpw->priv->window),
GLADE_FILE_DIALOG_ACTION_OPEN);
- if ((dir = gpw_get_recent_dir (gpw)) != NULL)
- {
- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser), dir);
- g_free (dir);
- }
if (gtk_dialog_run (GTK_DIALOG(filechooser)) == GTK_RESPONSE_OK)
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
@@ -522,40 +469,6 @@ gpw_open_cb (GtkAction *action, GladeProjectWindow *gpw)
}
static void
-gpw_recent_project_clear_cb (GtkAction *action, GladeProjectWindow *gpw)
-{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gpw->priv->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- "<big><b>%s</b></big>\n\n%s",
- _("Are you sure you want to clear the\nlist of recent projects?"),
- _("If you clear the list of recent projects, they will be\npermanently deleted."));
-
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_CLEAR, GTK_RESPONSE_OK,
- NULL);
-
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
- {
- /* Remove all Recent Projects items */
- g_queue_foreach (gpw->priv->recent_projects, (GFunc)gpw_recent_project_delete, gpw);
- /* Set submenu insensitive */
- gtk_widget_set_sensitive (gtk_ui_manager_get_widget
- (gpw->priv->ui, "/MenuBar/FileMenu/Recents"),
- FALSE);
-
- /* Save it */
- gpw_recent_project_config_save (gpw);
- glade_app_config_save ();
- }
- gtk_widget_destroy (dialog);
-}
-
-static void
gpw_save (GladeProjectWindow *gpw, GladeProject *project, const gchar *path)
{
GError *error = NULL;
@@ -579,11 +492,7 @@ gpw_save (GladeProjectWindow *gpw, GladeProject *project, const gchar *path)
glade_app_update_instance_count (project);
/* Get display_name here, it could have changed with "Save As..." */
- display_name = glade_project_display_name (project, FALSE, FALSE, FALSE),
-
- gpw_recent_project_add (gpw, project->path);
- gpw_recent_project_config_save (gpw);
- glade_app_config_save ();
+ display_name = glade_project_display_name (project, FALSE, FALSE, FALSE);
/* refresh names */
gpw_refresh_title (gpw);
@@ -598,40 +507,30 @@ gpw_save (GladeProjectWindow *gpw, GladeProject *project, const gchar *path)
}
static void
-gpw_save_as (GladeProjectWindow *gpw, const gchar *dialog_title)
+gpw_save_as (GladeProjectWindow *gpw)
{
GladeProject *project, *another_project;
GtkWidget *filechooser;
gchar *path = NULL;
gchar *real_path, *ch;
- if ((project = glade_app_get_project ()) == NULL)
+ project = glade_design_view_get_project (gpw->priv->active_view);
+
+ if (project == NULL)
{
- /* Just incase the menu-item is not insensitive */
- glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN,
- _("No open projects to save"));
+ /* Just in case the menu-item is not insensitive */
+ glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("No open projects to save"));
return;
}
- filechooser = glade_util_file_dialog_new (dialog_title,
+ filechooser = glade_util_file_dialog_new (_("Save As\342\200\246"),
GTK_WINDOW (gpw->priv->window),
GLADE_FILE_DIALOG_ACTION_SAVE);
if (project->path)
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser), project->path);
- else
- {
- gchar *dir;
- if ((dir = gpw_get_recent_dir (gpw)) != NULL)
- {
- gtk_file_chooser_set_current_folder
- (GTK_FILE_CHOOSER (filechooser), dir);
- g_free (dir);
- }
-
- gtk_file_chooser_set_current_name
- (GTK_FILE_CHOOSER (filechooser), project->name);
- }
+ else
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filechooser), project->name);
if (gtk_dialog_run (GTK_DIALOG(filechooser)) == GTK_RESPONSE_OK)
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
@@ -685,14 +584,14 @@ gpw_save_as (GladeProjectWindow *gpw, const gchar *dialog_title)
static void
gpw_save_cb (GtkAction *action, GladeProjectWindow *gpw)
{
- GladeProject *project;
+ GladeProject *project;
- if ((project = glade_app_get_project ()) == NULL)
+ project = glade_design_view_get_project (gpw->priv->active_view);
+
+ if (project == NULL)
{
- /* Just incase the menu-item or button is not insensitive */
- glade_util_ui_message (gpw->priv->window,
- GLADE_UI_WARN,
- _("No open projects to save"));
+ /* Just in case the menu-item or button is not insensitive */
+ glade_util_ui_message (gpw->priv->window, GLADE_UI_WARN, _("No open projects to save"));
return;
}
@@ -703,26 +602,23 @@ gpw_save_cb (GtkAction *action, GladeProjectWindow *gpw)
}
/* If instead we dont have a path yet, fire up a file selector */
- gpw_save_as (gpw, _("Save\342\200\246"));
+ gpw_save_as (gpw);
}
static void
gpw_save_as_cb (GtkAction *action, GladeProjectWindow *gpw)
{
- gpw_save_as (gpw, _("Save as\342\200\246"));
+ gpw_save_as (gpw);
}
-
static gboolean
gpw_confirm_close_project (GladeProjectWindow *gpw, GladeProject *project)
{
GtkWidget *dialog;
gboolean close = FALSE;
- char *msg;
+ gchar *msg;
gint ret;
GError *error = NULL;
- g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
-
msg = g_strdup_printf (_("<span weight=\"bold\" size=\"larger\">Save changes to project \"%s\" before closing?</span>\n\n"
"Your changes will be lost if you don't save them.\n"), project->name);
@@ -767,19 +663,12 @@ gpw_confirm_close_project (GladeProjectWindow *gpw, GladeProject *project)
{
GtkWidget *filechooser;
gchar *path = NULL;
- gchar *dir;
filechooser =
- glade_util_file_dialog_new (_("Save ..."),
+ glade_util_file_dialog_new (_("Save\342\200\246"),
GTK_WINDOW (gpw->priv->window),
GLADE_FILE_DIALOG_ACTION_SAVE);
- if ((dir = gpw_get_recent_dir (gpw)) != NULL)
- {
- gtk_file_chooser_set_current_folder
- (GTK_FILE_CHOOSER (filechooser), dir);
- g_free (dir);
- }
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER (filechooser), project->name);
@@ -816,36 +705,31 @@ gpw_confirm_close_project (GladeProjectWindow *gpw, GladeProject *project)
}
static void
-do_close (GladeProjectWindow *gpw, GladeProject *project)
+do_close (GladeProjectWindow *gpw, GladeDesignView *view)
{
- GladeProject *active_project;
-
- g_signal_handlers_disconnect_by_func (G_OBJECT (project),
- G_CALLBACK (gpw_project_notify_handler_cb),
- gpw);
-
- glade_app_remove_project (project);
-
- gpw_refresh_projects_list_menu (gpw);
-
- gpw_refresh_title (gpw);
-
- active_project = glade_app_get_project ();
- if (active_project != NULL)
- gpw_set_sensitivity_according_to_project (gpw, active_project);
- else
- gtk_action_group_set_sensitive (gpw->priv->project_actions, FALSE);
+ gint n;
+
+ n = gtk_notebook_page_num (GTK_NOTEBOOK (gpw->priv->notebook), GTK_WIDGET (view));
+
+ g_object_ref (view);
+
+ gtk_notebook_remove_page (GTK_NOTEBOOK (gpw->priv->notebook), n);
+
+ g_object_unref (view);
}
static void
gpw_close_cb (GtkAction *action, GladeProjectWindow *gpw)
{
+ GladeDesignView *view;
GladeProject *project;
gboolean close;
- project = glade_app_get_project ();
+ view = gpw->priv->active_view;
- if (!project)
+ project = glade_design_view_get_project (view);
+
+ if (view == NULL)
return;
if (project->changed)
@@ -854,13 +738,13 @@ gpw_close_cb (GtkAction *action, GladeProjectWindow *gpw)
if (!close)
return;
}
- do_close (gpw, project);
+ do_close (gpw, view);
}
static void
gpw_quit_cb (GtkAction *action, GladeProjectWindow *gpw)
{
- GList *list;
+/* GList *list;
for (list = glade_app_get_projects (); list; list = list->next)
{
@@ -879,7 +763,7 @@ gpw_quit_cb (GtkAction *action, GladeProjectWindow *gpw)
GladeProject *project = GLADE_PROJECT (glade_app_get_projects ()->data);
do_close (gpw, project);
}
-
+*/
gtk_main_quit ();
}
@@ -934,74 +818,6 @@ gpw_redo_cb (GtkAction *action, GladeProjectWindow *gpw)
glade_app_command_redo ();
}
-static gboolean
-gpw_hide_palette_on_delete (GtkWidget *palette, gpointer not_used, GtkUIManager *ui)
-{
- glade_util_hide_window (GTK_WINDOW (palette));
- return TRUE;
-}
-
-static void
-gpw_create_palette (GladeProjectWindow *gpw)
-{
- g_return_if_fail (gpw != NULL);
-
- gpw->priv->palette_window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
- gtk_window_set_default_size (GTK_WINDOW (gpw->priv->palette_window), -1,
- GLADE_PALETTE_DEFAULT_HEIGHT);
-
-
- gtk_window_set_title (gpw->priv->palette_window, _("Palette"));
- gtk_window_set_resizable (gpw->priv->palette_window, TRUE);
- gtk_window_move (gpw->priv->palette_window, 0, 250);
-
- gtk_container_add (GTK_CONTAINER (gpw->priv->palette_window),
- GTK_WIDGET (glade_app_get_palette()));
-
- /* Delete event, don't destroy it */
- g_signal_connect (G_OBJECT (gpw->priv->palette_window), "delete_event",
- G_CALLBACK (gpw_hide_palette_on_delete), gpw->priv->ui);
-}
-
-static void
-gpw_show_palette (GladeProjectWindow *gpw, gboolean raise)
-{
- g_return_if_fail (gpw != NULL);
-
- if (gpw->priv->palette_window == NULL)
- gpw_create_palette (gpw);
-
- gtk_widget_show (GTK_WIDGET (gpw->priv->palette_window));
-
- if (raise)
- gtk_window_present (gpw->priv->palette_window);
-}
-
-static gboolean
-gpw_hide_editor_on_delete (GtkWidget *editor, gpointer not_used,
- GtkUIManager *ui)
-{
- glade_util_hide_window (GTK_WINDOW (editor));
- return TRUE;
-}
-
-static gint
-gpw_hijack_editor_key_press (GtkWidget *editor_win,
- GdkEventKey *event,
- GladeProjectWindow *gpw)
-{
- if (event->keyval == GDK_Delete || /* Filter Delete from accelerator keys */
- ((event->state & GDK_CONTROL_MASK) && /* CNTL keys... */
- ((event->keyval == GDK_c || event->keyval == GDK_C) || /* CNTL-C (copy) */
- (event->keyval == GDK_x || event->keyval == GDK_X) || /* CNTL-X (cut) */
- (event->keyval == GDK_v || event->keyval == GDK_V)))) /* CNTL-V (paste) */
- {
- return gtk_widget_event (GTK_WINDOW (editor_win)->focus_widget,
- (GdkEvent *)event);
- }
- return FALSE;
-}
-
static void
gpw_doc_search_cb (GladeEditor *editor,
const gchar *book,
@@ -1012,106 +828,6 @@ gpw_doc_search_cb (GladeEditor *editor,
glade_util_search_devhelp (book, page, search);
}
-static void
-gpw_create_editor (GladeProjectWindow *gpw)
-{
- g_return_if_fail (gpw != NULL);
-
- gpw->priv->editor_window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
- gtk_window_set_default_size (GTK_WINDOW (gpw->priv->editor_window), 400, 450);
-
- gtk_window_set_title (gpw->priv->editor_window, _("Properties"));
- gtk_window_move (gpw->priv->editor_window, 550, 0);
-
- gtk_container_set_border_width (GTK_CONTAINER (gpw->priv->editor_window), 6);
-
- gtk_container_add (GTK_CONTAINER (gpw->priv->editor_window),
- GTK_WIDGET (glade_app_get_editor ()));
-
- /* Delete event, don't destroy it */
- g_signal_connect (G_OBJECT (gpw->priv->editor_window), "delete_event",
- G_CALLBACK (gpw_hide_editor_on_delete), gpw->priv->ui);
-
- g_signal_connect (G_OBJECT (gpw->priv->editor_window), "key-press-event",
- G_CALLBACK (gpw_hijack_editor_key_press), gpw);
-}
-
-static void
-gpw_show_editor (GladeApp *app, gboolean raise)
-{
- GladeProjectWindow *gpw = GLADE_PROJECT_WINDOW (app);
-
- g_return_if_fail (GLADE_IS_PROJECT_WINDOW (gpw));
-
- gtk_widget_show (GTK_WIDGET (gpw->priv->editor_window));
-
- if (raise)
- gtk_window_present (gpw->priv->editor_window);
-}
-
-static void
-gpw_hide_editor (GladeApp *app)
-{
- GladeProjectWindow *gpw = GLADE_PROJECT_WINDOW (app);
-
- g_return_if_fail (GLADE_IS_PROJECT_WINDOW (gpw));
-
- glade_util_hide_window (gpw->priv->editor_window);
-}
-
-static void
-gpw_expand_treeview_cb (GtkButton *button, GladeProjectView *view)
-{
- glade_project_view_expand_all (view);
-}
-
-static void
-gpw_collapse_treeview_cb (GtkButton *button, GladeProjectView *view)
-{
- glade_project_view_collapse_all (view);
-}
-
-static GtkWidget*
-gpw_create_widget_tree_contents (GladeProjectWindow *gpw)
-{
- GtkWidget *hbox, *vbox;
- GtkWidget *view;
-
- view = glade_project_view_new ();
- glade_app_add_project_view (GLADE_PROJECT_VIEW (view));
-
- gtk_container_set_border_width (GTK_CONTAINER (view), GLADE_GENERIC_BORDER_WIDTH);
-
- /* Add control buttons to the treeview. */
- hbox = gtk_hbutton_box_new ();
- vbox = gtk_vbox_new (FALSE, 0);
-
- gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_START);
-
- gpw->priv->expand = gtk_button_new_with_mnemonic (_("E_xpand all"));
- gtk_container_set_border_width (GTK_CONTAINER (gpw->priv->expand),
- GLADE_GENERIC_BORDER_WIDTH);
-
- gpw->priv->collapse = gtk_button_new_with_mnemonic (_("_Collapse all"));
- gtk_container_set_border_width (GTK_CONTAINER (gpw->priv->collapse),
- GLADE_GENERIC_BORDER_WIDTH);
-
- gtk_box_pack_start (GTK_BOX (hbox), gpw->priv->expand, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (hbox), gpw->priv->collapse, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (view), TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
- g_signal_connect (G_OBJECT (gpw->priv->expand), "clicked",
- G_CALLBACK (gpw_expand_treeview_cb),
- view);
-
- g_signal_connect (G_OBJECT (gpw->priv->collapse), "clicked",
- G_CALLBACK (gpw_collapse_treeview_cb),
- view);
-
- return vbox;
-}
-
static gboolean
gpw_hide_clipboard_view_on_delete (GtkWidget *clipboard_view, gpointer not_used,
GtkUIManager *ui)
@@ -1150,88 +866,156 @@ gpw_show_clipboard_view (GladeProjectWindow *gpw)
}
static void
-gpw_palette_appearance_change_cb (GtkRadioAction *action,
- GtkRadioAction *current,
- GladeProjectWindow *gpw)
+glade_project_window_previous_project_cb (GtkAction *action, GladeProjectWindow *window)
{
- gint value;
-
- value = gtk_radio_action_get_current_value (action);
-
- glade_palette_set_item_appearance (glade_app_get_palette (), value);
-
+ gtk_notebook_prev_page (GTK_NOTEBOOK (window->priv->notebook));
}
static void
-gpw_palette_toggle_small_icons_cb (GtkAction *action, GladeProjectWindow *gpw)
+glade_project_window_next_project_cb (GtkAction *action, GladeProjectWindow *window)
{
- if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
- glade_palette_set_use_small_item_icons (glade_app_get_palette(), TRUE);
- else
- glade_palette_set_use_small_item_icons (glade_app_get_palette(), FALSE);
-
+ gtk_notebook_next_page (GTK_NOTEBOOK (window->priv->notebook));
}
static void
-gpw_show_palette_cb (GtkAction *action, GladeProjectWindow *gpw)
+gpw_notebook_switch_page_cb (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ guint page_num,
+ GladeProjectWindow *gpw)
{
- gpw_show_palette (gpw, TRUE);
-}
+ GladeDesignView *view;
+ GladeProject *project;
+ GtkAction *action;
+ gchar *action_name;
+
+ view = GLADE_DESIGN_VIEW (gtk_notebook_get_nth_page (notebook, page_num));
+
+ /* CHECK: I don't know why but it seems notebook_switch_page is called
+ two times every time the user change the active tab */
+ if (view == gpw->priv->active_view)
+ return;
+
+ gpw->priv->active_view = view;
+
+ project = glade_design_view_get_project (view);
+
+ /* FIXME: this does not feel good */
+ glade_app_set_project (project);
+
+ gpw_refresh_title (gpw);
+ gpw_set_sensitivity_according_to_project (gpw, project);
+
+ /* activate the corresponding item in the project menu */
+ action_name = g_strdup_printf ("Tab_%d", page_num);
+ action = gtk_action_group_get_action (gpw->priv->projects_list_menu_actions,
+ action_name);
+
+ /* sometimes the action doesn't exist yet, and the proper action
+ * is set active during the documents list menu creation
+ * CHECK: would it be nicer if active_view was a property and we monitored the notify signal?
+ */
+ if (action != NULL)
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
+ g_free (action_name);
-static void
-gpw_show_editor_cb (GtkAction *action, GladeProjectWindow *gpw)
-{
- gpw_show_editor (GLADE_APP (gpw), TRUE);
}
static void
-gpw_show_clipboard_cb (GtkAction *action, GladeProjectWindow *gpw)
+gpw_notebook_tab_added_cb (GtkNotebook *notebook,
+ GladeDesignView *view,
+ guint page_num,
+ GladeProjectWindow *gpw)
{
- gpw_show_clipboard_view (gpw);
+ GladeProject *project;
+
+ ++gpw->priv->num_tabs;
+
+ project = glade_design_view_get_project (view);
+
+ g_signal_connect (G_OBJECT (project), "notify::has-unsaved-changes",
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+ g_signal_connect (G_OBJECT (project), "selection-changed",
+ G_CALLBACK (project_selection_changed_cb), gpw);
+ g_signal_connect (G_OBJECT (project), "notify::has-selection",
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+ g_signal_connect (G_OBJECT (project), "notify::read-only",
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+
+ gpw_set_sensitivity_according_to_project (gpw, project);
+
+ gpw_refresh_projects_list_menu (gpw);
+
+ gpw_refresh_title (gpw);
+
+ if (gpw->priv->num_tabs > 0)
+ gtk_action_group_set_sensitive (gpw->priv->project_actions, TRUE);
+
}
-void
-glade_project_window_prev_project_cb (GtkAction *action, GladeProjectWindow *window)
+static void
+gpw_notebook_tab_removed_cb (GtkNotebook *notebook,
+ GladeDesignView *view,
+ guint page_num,
+ GladeProjectWindow *gpw)
{
GladeProject *project;
- GtkToggleAction *project_list_action;
- GList *l;
- project = glade_app_get_project ();
+ --gpw->priv->num_tabs;
- l = glade_app_get_projects ();
- l = g_list_find (l, project);
+ if (gpw->priv->num_tabs == 0)
+ gpw->priv->active_view = NULL;
- if ((l = g_list_previous (l)) != NULL)
- {
- project = GLADE_PROJECT (l->data);
-
- project_list_action = GTK_TOGGLE_ACTION (g_object_get_data (G_OBJECT (project), "project-list-action"));
+ project = glade_design_view_get_project (view);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (project),
+ G_CALLBACK (gpw_project_notify_handler_cb),
+ gpw);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (project),
+ G_CALLBACK (project_selection_changed_cb),
+ gpw);
+
+ /* FIXME: this function needs to be preferably called somewhere else */
+ glade_app_remove_project (project);
+
+ gpw_refresh_projects_list_menu (gpw);
+
+ gpw_refresh_title (gpw);
+
+ if (gpw->priv->active_view)
+ gpw_set_sensitivity_according_to_project (gpw, glade_design_view_get_project (gpw->priv->active_view));
+ else
+ gtk_action_group_set_sensitive (gpw->priv->project_actions, FALSE);
- gtk_toggle_action_set_active (project_list_action, TRUE);
- }
}
-void
-glade_project_window_next_project_cb (GtkAction *action, GladeProjectWindow *gpw)
+static void
+gpw_palette_appearance_change_cb (GtkRadioAction *action,
+ GtkRadioAction *current,
+ GladeProjectWindow *gpw)
{
- GladeProject *project;
- GtkToggleAction *project_list_action;
- GList *l;
+ gint value;
- project = glade_app_get_project ();
+ value = gtk_radio_action_get_current_value (action);
- l = glade_app_get_projects ();
- l = g_list_find (l, project);
+ glade_palette_set_item_appearance (glade_app_get_palette (), value);
- if ((l = g_list_next (l)) != NULL)
- {
- project = GLADE_PROJECT (l->data);
-
- project_list_action = GTK_TOGGLE_ACTION (g_object_get_data (G_OBJECT (project), "project-list-action"));
+}
- gtk_toggle_action_set_active (project_list_action, TRUE);
- }
+static void
+gpw_palette_toggle_small_icons_cb (GtkAction *action, GladeProjectWindow *gpw)
+{
+ glade_palette_set_use_small_item_icons (glade_app_get_palette(),
+ gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+}
+
+static void
+gpw_show_clipboard_cb (GtkAction *action, GladeProjectWindow *gpw)
+{
+ gpw_show_clipboard_view (gpw);
}
static void
@@ -1337,10 +1121,6 @@ static const gchar *ui_info =
" <menu action='FileMenu'>\n"
" <menuitem action='New'/>\n"
" <menuitem action='Open'/>\n"
-" <menu action='Recents'>\n"
-" <separator/>\n"
-" <menuitem action='ClearRecents'/>\n"
-" </menu>\n"
" <separator/>\n"
" <menuitem action='Save'/>\n"
" <menuitem action='SaveAs'/>\n"
@@ -1358,9 +1138,7 @@ static const gchar *ui_info =
" <menuitem action='Delete'/>\n"
" </menu>\n"
" <menu action='ViewMenu'>\n"
-" <menuitem action='PropertyEditor'/>\n"
" <menuitem action='Clipboard'/>\n"
-" <menuitem action='Palette'/>\n"
" <separator/>\n"
" <menu action='PaletteAppearance'>\n"
" <menuitem action='IconsAndLabels'/>\n"
@@ -1384,11 +1162,16 @@ static const gchar *ui_info =
" </menu>\n"
" </menubar>\n"
" <toolbar name='ToolBar'>"
+" <toolitem action='New'/>"
" <toolitem action='Open'/>"
" <toolitem action='Save'/>"
" <separator/>\n"
" <toolitem action='Undo'/>"
" <toolitem action='Redo'/>"
+" <separator/>\n"
+" <toolitem action='Cut'/>"
+" <toolitem action='Copy'/>"
+" <toolitem action='Paste'/>"
" </toolbar>"
"</ui>\n";
@@ -1406,11 +1189,6 @@ static GtkActionEntry static_entries[] = {
{ "Open", GTK_STOCK_OPEN, N_("_Open"),"<control>O",
N_("Open a project"), G_CALLBACK (gpw_open_cb) },
- { "Recents", NULL, N_("Open _Recent"), NULL, NULL },
-
- { "ClearRecents", GTK_STOCK_CLEAR, N_("Clear Recent Projects"), NULL,
- NULL, G_CALLBACK (gpw_recent_project_clear_cb) },
-
{ "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q",
N_("Quit the program"), G_CALLBACK (gpw_quit_cb) },
@@ -1458,14 +1236,6 @@ static GtkActionEntry project_entries[] = {
N_("Delete the selection"), G_CALLBACK (gpw_delete_cb) },
/* ViewMenu */
-
- { "PropertyEditor", NULL, N_("Property _Editor"), NULL,
- N_("Show the property editor"),
- G_CALLBACK (gpw_show_editor_cb) },
-
- { "Palette", NULL, N_("_Palette"), NULL,
- N_("Show the palette of widgets"),
- G_CALLBACK (gpw_show_palette_cb) },
{ "Clipboard", NULL, N_("_Clipboard"), NULL,
N_("Show the clipboard"),
@@ -1473,7 +1243,7 @@ static GtkActionEntry project_entries[] = {
/* ProjectsMenu */
{ "PreviousProject", NULL, N_("_Previous Project"), "<control>Page_Up",
- N_("Activate previous project"), G_CALLBACK (glade_project_window_prev_project_cb) },
+ N_("Activate previous project"), G_CALLBACK (glade_project_window_previous_project_cb) },
{ "NextProject", NULL, N_("_Next Project"), "<control>Page_Down",
N_("Activate next project"), G_CALLBACK (glade_project_window_next_project_cb) }
@@ -1595,10 +1365,6 @@ gpw_construct_menu (GladeProjectWindow *gpw)
gtk_action_group_new (GLADE_ACTION_GROUP_PROJECTS_LIST_MENU);
gtk_action_group_set_translation_domain (gpw->priv->projects_list_menu_actions,
GETTEXT_PACKAGE);
-
- gpw->priv->recent_actions = gtk_action_group_new (GLADE_ACTION_GROUP_RECENT);
- gtk_action_group_set_translation_domain (gpw->priv->recent_actions,
- GETTEXT_PACKAGE);
gpw->priv->ui = gtk_ui_manager_new ();
@@ -1609,7 +1375,6 @@ gpw_construct_menu (GladeProjectWindow *gpw)
gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->static_actions, 0);
gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->project_actions, 1);
- gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->recent_actions, 2);
gtk_ui_manager_insert_action_group (gpw->priv->ui, gpw->priv->projects_list_menu_actions, 3);
gtk_window_add_accel_group (GTK_WINDOW (gpw->priv->window),
@@ -1620,10 +1385,6 @@ gpw_construct_menu (GladeProjectWindow *gpw)
g_message ("Building menus failed: %s", error->message);
g_error_free (error);
}
-
- gtk_widget_set_sensitive (gtk_ui_manager_get_widget
- (gpw->priv->ui, "/MenuBar/FileMenu/Recents"),
- FALSE);
return gtk_ui_manager_get_widget (gpw->priv->ui, "/MenuBar");
}
@@ -1703,37 +1464,92 @@ gpw_delete_event (GtkWindow *w, GdkEvent *event, GladeProjectWindow *gpw)
static void
glade_project_window_create (GladeProjectWindow *gpw)
{
- GtkWidget *app;
+ GtkWidget *window;
GtkWidget *vbox;
+ GtkWidget *hpaned1;
+ GtkWidget *hpaned2;
+ GtkWidget *vpaned;
GtkWidget *menubar;
GtkWidget *toolbar;
- GtkWidget *project_view;
+ GladeProjectView *project_view;
GtkWidget *statusbar;
GtkWidget *editor_item, *docs_item;
+ GtkWidget *palette;
+ GtkWidget *editor;
+ GtkWidget *dockitem;
- app = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_move (GTK_WINDOW (app), 0, 0);
- gtk_window_set_default_size (GTK_WINDOW (app), 300, 450);
-
- gpw->priv->window = app;
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gpw->priv->window = window;
+ gtk_window_maximize (GTK_WINDOW (window));
vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (app), vbox);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
gpw->priv->main_vbox = vbox;
+ /* menubar */
menubar = gpw_construct_menu (gpw);
- toolbar = gtk_ui_manager_get_widget (gpw->priv->ui, "/ToolBar");
- project_view = gpw_create_widget_tree_contents (gpw);
- statusbar = gpw_construct_statusbar (gpw);
-
+ gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0);
gtk_widget_show (menubar);
+
+ /* toolbar */
+ toolbar = gtk_ui_manager_get_widget (gpw->priv->ui, "/ToolBar");
+ gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
gtk_widget_show (toolbar);
- gtk_widget_show_all (project_view);
+
+ /* main contents */
+ hpaned1 = gtk_hpaned_new ();
+ hpaned2 = gtk_hpaned_new ();
+ vpaned = gtk_vpaned_new ();
+
+ /* minimum size for far-right pane */
+ gtk_widget_set_size_request (vpaned, 310, -1);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hpaned1, TRUE, TRUE, 0);
+ gtk_paned_pack1 (GTK_PANED (hpaned1), hpaned2, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned, FALSE, FALSE);
+
+ gtk_widget_show_all (hpaned1);
+ gtk_widget_show_all (hpaned2);
+ gtk_widget_show_all (vpaned);
+
+ /* palette */
+ palette = GTK_WIDGET (glade_app_get_palette ());
+ dockitem = gpw_construct_dock_item (gpw, _("Palette"), palette);
+ gtk_paned_pack1 (GTK_PANED (hpaned2), dockitem, FALSE, FALSE);
+
+ /* notebook */
+ gpw->priv->notebook = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (gpw->priv->notebook), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (gpw->priv->notebook), FALSE);
+ gtk_paned_pack2 (GTK_PANED (hpaned2), gpw->priv->notebook, TRUE, FALSE);
+ gtk_widget_show (gpw->priv->notebook);
+
+ /* project view */
+ project_view = GLADE_PROJECT_VIEW (glade_project_view_new ());
+ glade_app_add_project_view (project_view);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (project_view),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (project_view), GTK_SHADOW_IN);
+ dockitem = gpw_construct_dock_item (gpw, _("Inspector"), GTK_WIDGET (project_view));
+ gtk_paned_pack1 (GTK_PANED (vpaned), dockitem, FALSE, FALSE);
+ gtk_widget_show_all (GTK_WIDGET (project_view));
+
+ /* editor */
+ editor = GTK_WIDGET (glade_app_get_editor ());
+ dockitem = gpw_construct_dock_item (gpw, _("Properties"), editor);
+ gpw->priv->label = GTK_LABEL (g_object_get_data (G_OBJECT (dockitem), "dock-label"));
+ gtk_label_set_ellipsize (GTK_LABEL (gpw->priv->label), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (gpw->priv->label), 0, 0.5);
+ gtk_paned_pack2 (GTK_PANED (vpaned), dockitem, FALSE, FALSE);
+
+ /* status bar */
+ statusbar = gpw_construct_statusbar (gpw);
+ gtk_box_pack_end (GTK_BOX (vbox), statusbar, FALSE, TRUE, 0);
gtk_widget_show (statusbar);
- gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
+ gtk_widget_show (vbox);
+ /* devhelp */
editor_item = gtk_ui_manager_get_widget (gpw->priv->ui,
"/MenuBar/ViewMenu/PropertyEditorHelp");
docs_item = gtk_ui_manager_get_widget (gpw->priv->ui,
@@ -1742,53 +1558,49 @@ glade_project_window_create (GladeProjectWindow *gpw)
gtk_widget_set_sensitive (editor_item, FALSE);
gtk_widget_set_sensitive (docs_item, FALSE);
-
- gtk_box_pack_start (GTK_BOX (vbox), project_view, TRUE, TRUE, 0);
- gtk_box_pack_end (GTK_BOX (vbox), statusbar, FALSE, TRUE, 0);
-
- gtk_widget_show (vbox);
-
- gpw_recent_project_config_load (gpw);
/* support for opening a file by dragging onto the project window */
- gtk_drag_dest_set (app,
+ gtk_drag_dest_set (GTK_WIDGET (window),
GTK_DEST_DEFAULT_ALL,
drop_types, G_N_ELEMENTS (drop_types),
GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect (G_OBJECT (app), "drag-data-received",
+ g_signal_connect (G_OBJECT (window), "drag-data-received",
G_CALLBACK (gpw_drag_data_received), gpw);
- g_signal_connect (G_OBJECT (app), "delete_event",
+ g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (gpw_delete_event), gpw);
+
+ /* Connect signals notebook */
+ g_signal_connect (gpw->priv->notebook,
+ "switch-page",
+ G_CALLBACK (gpw_notebook_switch_page_cb),
+ gpw);
+ g_signal_connect (gpw->priv->notebook,
+ "page-added",
+ G_CALLBACK (gpw_notebook_tab_added_cb),
+ gpw);
+ g_signal_connect (gpw->priv->notebook,
+ "page-removed",
+ G_CALLBACK (gpw_notebook_tab_removed_cb),
+ gpw);
}
static void
glade_project_window_add_project (GladeProjectWindow *gpw, GladeProject *project)
{
+ GtkWidget *view;
+
g_return_if_fail (GLADE_IS_PROJECT (project));
+
+ view = glade_design_view_new (project);
+ gtk_widget_show (view);
glade_app_add_project (project);
- /* Connect callback handler for notify signals emitted by projects */
- g_signal_connect (G_OBJECT (project), "notify::has-unsaved-changes",
- G_CALLBACK (gpw_project_notify_handler_cb),
- gpw);
- g_signal_connect (G_OBJECT (project), "notify::has-selection",
- G_CALLBACK (gpw_project_notify_handler_cb),
- gpw);
- g_signal_connect (G_OBJECT (project), "notify::read-only",
- G_CALLBACK (gpw_project_notify_handler_cb),
- gpw);
-
- gpw_refresh_projects_list_menu (gpw);
-
- gpw_set_sensitivity_according_to_project (gpw, project);
-
- gpw_refresh_title (gpw);
-
- if (gtk_action_group_get_sensitive (gpw->priv->project_actions) == FALSE)
- gtk_action_group_set_sensitive (gpw->priv->project_actions, TRUE);
+ gtk_notebook_append_page (GTK_NOTEBOOK (gpw->priv->notebook), GTK_WIDGET (view), NULL);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (gpw->priv->notebook), -1);
+
}
void
@@ -1807,9 +1619,6 @@ glade_project_window_new_project (GladeProjectWindow *gpw)
glade_project_window_add_project (gpw, project);
}
-/*
- * Opens the project specified by path and adds it to the GladeProjectWindow.
- */
void
glade_project_window_open_project (GladeProjectWindow *gpw, const gchar *path)
{
@@ -1830,10 +1639,6 @@ glade_project_window_open_project (GladeProjectWindow *gpw, const gchar *path)
if ((project = glade_project_open (path)) == NULL)
return;
- gpw_recent_project_add (gpw, project->path);
- gpw_recent_project_config_save (gpw);
- glade_app_config_save ();
-
glade_project_window_add_project (gpw, project);
}
@@ -1917,75 +1722,40 @@ glade_project_window_update_ui (GladeApp *app)
void
glade_project_window_show_all (GladeProjectWindow *gpw)
{
- gpw_show_palette (gpw, FALSE);
- gpw_show_editor (GLADE_APP (gpw), FALSE);
gtk_widget_show (gpw->priv->window);
}
static void
glade_project_window_finalize (GObject *object)
{
- GladeProjectWindow *gpw = GLADE_PROJECT_WINDOW (object);
-
- g_queue_foreach (gpw->priv->recent_projects, (GFunc)g_object_unref, NULL);
- g_queue_free (gpw->priv->recent_projects);
-
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
-glade_project_window_class_init (GladeProjectWindowClass * klass)
+glade_project_window_class_init (GladeProjectWindowClass * class)
{
GObjectClass *object_class;
GladeAppClass *app_class;
- g_return_if_fail (klass != NULL);
+ g_return_if_fail (class != NULL);
-
-
- parent_class = g_type_class_peek_parent (klass);
- object_class = G_OBJECT_CLASS (klass);
- app_class = GLADE_APP_CLASS (klass);
+ parent_class = g_type_class_peek_parent (class);
+ object_class = G_OBJECT_CLASS (class);
+ app_class = GLADE_APP_CLASS (class);
object_class->finalize = glade_project_window_finalize;
app_class->update_ui_signal = glade_project_window_update_ui;
- app_class->show_properties = gpw_show_editor;
- app_class->hide_properties = gpw_hide_editor;
+
+ g_type_class_add_private (object_class, sizeof (GladeProjectWindowPrivate));
}
static void
glade_project_window_init (GladeProjectWindow *gpw)
{
- gpw->priv = g_new0 (GladeProjectWindowPriv, 1);
-
- /* initialize widgets */
- gpw->priv->recent_projects = g_queue_new ();
-}
-
-GType
-glade_project_window_get_type ()
-{
- static GType obj_type = 0;
+ gpw->priv = GLADE_PROJECT_WINDOW_GET_PRIVATE (gpw);
- if (!obj_type)
- {
- static const GTypeInfo obj_info =
- {
- sizeof (GladeProjectWindowClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) glade_project_window_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (GladeProjectWindow),
- 0, /* n_preallocs */
- (GInstanceInitFunc) glade_project_window_init,
- NULL /* value_table */
- };
- obj_type = g_type_register_static (GLADE_TYPE_APP,
- "GladeProjectWindow", &obj_info, 0);
- }
- return obj_type;
+ gpw->priv->label = NULL;
+
}
GladeProjectWindow *
@@ -1997,16 +1767,12 @@ glade_project_window_new (void)
gpw = g_object_new (GLADE_TYPE_PROJECT_WINDOW, NULL);
glade_project_window_create (gpw);
- gpw_create_palette (gpw);
- gpw_create_editor (gpw);
glade_app_set_window (gpw->priv->window);
accel_group = gtk_ui_manager_get_accel_group(gpw->priv->ui);
glade_app_set_accel_group (accel_group);
- gtk_window_add_accel_group(gpw->priv->palette_window, accel_group);
- gtk_window_add_accel_group(gpw->priv->editor_window, accel_group);
gtk_window_add_accel_group(GTK_WINDOW (glade_app_get_clipboard_view ()), accel_group);
/* Connect callback handler for notify signals emitted by clipboard */
diff --git a/src/glade-project-window.h b/src/glade-project-window.h
index 9d54f604..f0e6350e 100644
--- a/src/glade-project-window.h
+++ b/src/glade-project-window.h
@@ -15,7 +15,7 @@ G_BEGIN_DECLS
typedef struct _GladeProjectWindow GladeProjectWindow;
typedef struct _GladeProjectWindowClass GladeProjectWindowClass;
-typedef struct _GladeProjectWindowPriv GladeProjectWindowPriv;
+typedef struct _GladeProjectWindowPrivate GladeProjectWindowPrivate;
/* A GladeProjectWindow specifies a loaded glade application.
* it contains pointers to all the components that make up
@@ -25,7 +25,8 @@ typedef struct _GladeProjectWindowPriv GladeProjectWindowPriv;
struct _GladeProjectWindow
{
GladeApp parent;
- GladeProjectWindowPriv *priv;
+
+ GladeProjectWindowPrivate *priv;
};
struct _GladeProjectWindowClass
diff --git a/src/glade-widget.c b/src/glade-widget.c
index 5d048ece..8d96a0ec 100644
--- a/src/glade-widget.c
+++ b/src/glade-widget.c
@@ -44,6 +44,8 @@
#include "glade-popup.h"
#include "glade-editor.h"
#include "glade-app.h"
+#include "glade-design-view.h"
+
static void glade_widget_set_adaptor (GladeWidget *widget,
@@ -61,6 +63,10 @@ static GladeWidget *glade_widget_new_from_widget_info (GladeWidgetInfo *i
GladeProject *project,
GladeWidget *parent);
+static gboolean glade_window_is_embedded (GtkWindow *window);
+static void glade_widget_embed (GladeWidget *widget);
+static void glade_widget_embed_using_signals (GladeWidget *widget);
+
enum
{
ADD_SIGNAL_HANDLER,
@@ -2173,40 +2179,36 @@ glade_widget_debug (GladeWidget *widget)
glade_widget_debug_real (widget, 0);
}
-static void
-glade_widget_save_coords (GladeWidget *widget)
-{
- if (GTK_IS_WINDOW (widget->object))
- {
- gtk_window_get_position (GTK_WINDOW (widget->object),
- &(widget->save_x), &(widget->save_y));
- widget->pos_saved = TRUE;
- }
-}
-
/**
* glade_widget_show:
* @widget: A #GladeWidget
*
- * Display @widget
+ * Display @widget in it's project's GladeDesignView
*/
void
glade_widget_show (GladeWidget *widget)
{
+ GladeDesignView *view;
+ GtkWidget *layout;
+
g_return_if_fail (GLADE_IS_WIDGET (widget));
-
+
/* Position window at saved coordinates or in the center */
if (GTK_IS_WINDOW (widget->object))
{
- if (widget->pos_saved)
- gtk_window_move (GTK_WINDOW (widget->object),
- widget->save_x, widget->save_y);
- else
- gtk_window_set_position (GTK_WINDOW (widget->object),
- GTK_WIN_POS_CENTER);
+ if (!glade_window_is_embedded (GTK_WINDOW (widget->object)))
+ glade_widget_embed_using_signals (widget);
+
+ view = glade_design_view_get_from_project (glade_widget_get_project (widget));
+ layout = GTK_WIDGET (glade_design_view_get_layout (view));
+
+ if (gtk_bin_get_child (GTK_BIN (layout)) != NULL)
+ gtk_container_remove (GTK_CONTAINER (layout), gtk_bin_get_child (GTK_BIN (layout)));
+
+ gtk_container_add (GTK_CONTAINER (layout), GTK_WIDGET (widget->object));
gtk_widget_show_all (GTK_WIDGET (widget->object));
- gtk_window_present (GTK_WINDOW (widget->object));
+
} else if (GTK_IS_WIDGET (widget->object)) {
gtk_widget_show_all (GTK_WIDGET (widget->object));
}
@@ -2226,7 +2228,6 @@ glade_widget_hide (GladeWidget *widget)
if (GTK_IS_WINDOW (widget->object))
{
/* Save coordinates */
- glade_widget_save_coords (widget);
gtk_widget_hide (GTK_WIDGET (widget->object));
}
widget->visible = FALSE;
@@ -2418,9 +2419,6 @@ glade_widget_rebuild (GladeWidget *glade_widget)
g_return_if_fail (GLADE_IS_WIDGET (glade_widget));
adaptor = glade_widget->adaptor;
-
- /* Save coordinates incase its a toplevel */
- glade_widget_save_coords (glade_widget);
/* Extract and keep the child hierarchies aside... */
children = glade_widget_extract_children (glade_widget);
@@ -3673,3 +3671,496 @@ glade_widget_pop_superuser (void)
}
glade_property_pop_superuser ();
}
+
+
+/*******************************************************************************
+ Toplevel GladeWidget Embedding
+ *******************************************************************************
+ *
+ * This code has two implemententations, one that stores original class handlers in
+ * a hashtable, and another that uses signal connection to emulate vfuncs.
+ *
+ * Signal Connection: glade_widget_embed_using_signals ()
+ *
+ * Hashtable: glade_widget_embed ()
+ *
+ */
+
+
+typedef struct
+{
+ /* pointers to the original class handlers */
+ void (* realize) (GtkWidget *widget);
+ void (* map) (GtkWidget *widget);
+ void (* unmap) (GtkWidget *widget);
+ void (* show) (GtkWidget *widget);
+ void (* hide) (GtkWidget *widget);
+ void (* size_allocate) (GtkWidget *widget, GtkAllocation *allocation);
+
+} GladeOriginalHandlers;
+
+static GHashTable *original_handlers_table = NULL;
+
+static GQuark glade_embedded_window_quark = 0;
+
+
+static gboolean
+glade_window_is_embedded (GtkWindow *window)
+{
+ return GPOINTER_TO_INT (g_object_get_qdata ((GObject *) window, glade_embedded_window_quark));
+}
+
+static GtkBinClass*
+get_bin_class_ancestor (gpointer descendant_class)
+{
+ gpointer parent_class;
+ gpointer class;
+
+ class = descendant_class;
+
+ if (!GTK_IS_BIN_CLASS (class))
+ return NULL;
+
+ while (GTK_IS_BIN_CLASS (parent_class = g_type_class_peek_parent (class)))
+ {
+ class = parent_class;
+ parent_class = g_type_class_peek_parent (class);
+
+ }
+
+ return GTK_BIN_CLASS (class);
+}
+
+static GladeOriginalHandlers*
+obtain_handlers (GType instance_type)
+{
+ GladeOriginalHandlers *handlers = NULL;
+ GType type = instance_type;
+
+ while (!handlers && type != 0)
+ {
+ handlers = (GladeOriginalHandlers *) g_hash_table_lookup (original_handlers_table, &type);
+
+ type = g_type_parent (type);
+ }
+
+ return handlers;
+}
+
+static void
+embedded_window_map (GtkWidget *widget)
+{
+ GtkBinClass *bin_class;
+
+ bin_class = get_bin_class_ancestor (GTK_WIDGET_GET_CLASS (widget));
+
+ GTK_WIDGET_CLASS (bin_class)->map (widget);
+}
+
+static void
+embedded_window_unmap (GtkWidget *widget)
+{
+ GtkBinClass *bin_class;
+
+ bin_class = get_bin_class_ancestor (GTK_WIDGET_GET_CLASS (widget));
+
+ GTK_WIDGET_CLASS (bin_class)->unmap (widget);
+}
+
+static void
+embedded_window_show (GtkWidget *widget)
+{
+ GtkBinClass *bin_class;
+
+ bin_class = get_bin_class_ancestor (GTK_WIDGET_GET_CLASS (widget));
+
+ GTK_WIDGET_CLASS (bin_class)->show (widget);
+}
+
+static void
+embedded_window_hide (GtkWidget *widget)
+{
+ GtkBinClass *bin_class;
+
+ bin_class = get_bin_class_ancestor (GTK_WIDGET_GET_CLASS (widget));
+
+ GTK_WIDGET_CLASS (bin_class)->hide (widget);
+}
+
+static void
+embedded_window_realize (GtkWidget *widget)
+{
+ GtkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ window = GTK_WINDOW (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK |
+ GDK_FOCUS_CHANGE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_STRUCTURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+
+ gdk_window_enable_synchronized_configure (widget->window);
+
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+embedded_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ GtkWindow *window;
+ GtkAllocation child_allocation;
+
+ window = GTK_WINDOW (widget);
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window, allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+
+ if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
+ {
+ child_allocation.x = GTK_CONTAINER (widget)->border_width;
+ child_allocation.y = GTK_CONTAINER (widget)->border_width;
+ child_allocation.width = MAX (1, allocation->width - GTK_CONTAINER (widget)->border_width * 2);
+ child_allocation.height = MAX (1, allocation->height - GTK_CONTAINER (widget)->border_width * 2);
+
+ gtk_widget_size_allocate (window->bin.child, &child_allocation);
+ }
+}
+
+static void
+embedded_window_realize_proxy (GtkWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->realize (widget);
+ }
+ else
+ {
+ embedded_window_realize (widget);
+ }
+}
+
+static void
+embedded_window_size_allocate_proxy (GtkWidget *widget, GtkAllocation *allocation)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->size_allocate (widget, allocation);
+ }
+ else
+ {
+ embedded_window_size_allocate (widget, allocation);
+ }
+}
+
+static void
+embedded_window_map_proxy (GtkWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->map (widget);
+ }
+ else
+ {
+ embedded_window_map (widget);
+ }
+}
+
+static void
+embedded_window_unmap_proxy (GtkWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->unmap (widget);
+ }
+ else
+ {
+ embedded_window_unmap (widget);
+ }
+}
+
+
+static void
+embedded_window_show_proxy (GtkWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->show (widget);
+ }
+ else
+ {
+ embedded_window_show (widget);
+ }
+}
+
+static void
+embedded_window_hide_proxy (GtkWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+
+ if (!glade_window_is_embedded ((GtkWindow *) widget))
+ {
+ original_handlers = obtain_handlers (G_OBJECT_TYPE (widget));
+
+ g_assert (original_handlers != NULL);
+
+ original_handlers->hide (widget);
+ }
+ else
+ {
+ embedded_window_hide (widget);
+ }
+}
+
+static guint
+glade_gtype_hash (const GType *v)
+{
+ return *v % G_MAXUINT;
+}
+
+static gboolean
+glade_gtype_equal (const GType *v1, const GType *v2)
+{
+ return *v1 == *v2;
+}
+
+static void
+embedded_data_ensure (void)
+{
+
+ if (original_handlers_table == NULL)
+ {
+ original_handlers_table = g_hash_table_new_full ((GHashFunc) glade_gtype_hash,
+ (GEqualFunc) glade_gtype_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ }
+
+ if (glade_embedded_window_quark == 0)
+ glade_embedded_window_quark = g_quark_from_string ("GladeEmbedWindow");
+}
+
+/**
+ * glade_widget_window:
+ * @window: a #GtkWindow
+ *
+ * Embeds a window by overriding class-wide methods
+ */
+static void
+glade_widget_embed (GladeWidget *widget)
+{
+ GladeOriginalHandlers *original_handlers;
+ GtkWindow *window;
+ GType *key;
+
+ g_return_if_fail (GLADE_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WINDOW (widget->object));
+
+ window = GTK_WINDOW (widget->object);
+
+ /* do some validity checks */
+ if (glade_window_is_embedded (window) || GTK_WIDGET_REALIZED (GTK_WIDGET (window))) {
+ g_critical ("Cannot embed a window that is already realized or embedded");
+ return;
+ }
+
+ embedded_data_ensure ();
+
+ GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (window), GTK_TOPLEVEL);
+ gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_PARENT);
+
+ /* create key (GType) for the hashtable */
+ key = (GType *) g_malloc (sizeof (GType));
+ *key = G_OBJECT_TYPE (window);
+
+ /* see if the class handlers are already in the hashtable */
+ original_handlers = (GladeOriginalHandlers *) g_hash_table_lookup (original_handlers_table, key);
+
+ if (original_handlers == NULL)
+ {
+ /* now we override the class handlers, and store the overridden handlers in the hashtable */
+ original_handlers = g_new0 (GladeOriginalHandlers, 1);
+
+ original_handlers->realize = GTK_WIDGET_GET_CLASS (window)->realize;
+ original_handlers->map = GTK_WIDGET_GET_CLASS (window)->map;
+ original_handlers->unmap = GTK_WIDGET_GET_CLASS (window)->unmap;
+ original_handlers->show = GTK_WIDGET_GET_CLASS (window)->show;
+ original_handlers->hide = GTK_WIDGET_GET_CLASS (window)->hide;
+ original_handlers->size_allocate = GTK_WIDGET_GET_CLASS (window)->size_allocate;
+
+ GTK_WIDGET_GET_CLASS (window)->realize = embedded_window_realize_proxy;
+ GTK_WIDGET_GET_CLASS (window)->map = embedded_window_map_proxy;
+ GTK_WIDGET_GET_CLASS (window)->unmap = embedded_window_unmap_proxy;
+ GTK_WIDGET_GET_CLASS (window)->show = embedded_window_show_proxy;
+ GTK_WIDGET_GET_CLASS (window)->hide = embedded_window_hide_proxy;
+ GTK_WIDGET_GET_CLASS (window)->size_allocate = embedded_window_size_allocate_proxy;
+
+ g_hash_table_insert (original_handlers_table, key, original_handlers);
+ }
+
+ /* mark window as embedded */
+ g_object_set_qdata (G_OBJECT (window),
+ glade_embedded_window_quark, GINT_TO_POINTER (TRUE));
+}
+
+
+/* signal connection method */
+
+static void
+embedded_window_realize_handler (GtkWidget *widget)
+{
+ GtkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ window = GTK_WINDOW (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK |
+ GDK_FOCUS_CHANGE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_STRUCTURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ /* destroy the previously created window */
+ if (GDK_IS_WINDOW (widget->window))
+ {
+ gdk_window_hide (widget->window);
+ }
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+
+ gdk_window_enable_synchronized_configure (widget->window);
+
+ gdk_window_set_user_data (widget->window, window);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+}
+
+static void
+embedded_window_size_allocate_handler (GtkWidget *widget)
+{
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+}
+
+/**
+ * glade_widget_embed_using_signals:
+ * @window: a #GtkWindow
+ *
+ * Embeds a window by using signal connection method
+ */
+static void
+glade_widget_embed_using_signals (GladeWidget *widget)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (GLADE_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WINDOW (widget->object));
+
+ window = GTK_WINDOW (widget->object);
+
+ if (glade_window_is_embedded (window) || GTK_WIDGET_REALIZED (GTK_WIDGET (window))) {
+ g_critical ("Cannot embed a window that is already realized or embedded");
+ return;
+ }
+
+ GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (window), GTK_TOPLEVEL);
+ gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_PARENT);
+
+ g_signal_connect (G_OBJECT (window), "realize",
+ G_CALLBACK (embedded_window_realize_handler), NULL);
+ g_signal_connect (G_OBJECT (window), "size-allocate",
+ G_CALLBACK (embedded_window_size_allocate_handler), NULL);
+
+ /* mark window as embedded */
+ if (glade_embedded_window_quark == 0)
+ glade_embedded_window_quark = g_quark_from_string ("GladeEmbedWindow");
+
+ g_object_set_qdata (G_OBJECT (widget),
+ glade_embedded_window_quark, GINT_TO_POINTER (TRUE));
+}
diff --git a/src/glade-widget.h b/src/glade-widget.h
index 5096a195..d5788f48 100644
--- a/src/glade-widget.h
+++ b/src/glade-widget.h
@@ -84,12 +84,6 @@ struct _GladeWidget
* added/removed from the project).
*/
- /* Save toplevel positions */
- gint save_x;
- gint save_y;
- gboolean pos_saved;
-
-
/* Construct parameters: */
GladeWidget *construct_template;
GladeWidgetInfo *construct_info;