diff options
author | Tristan Van Berkom <tvb@src.gnome.org> | 2006-10-26 00:45:22 +0000 |
---|---|---|
committer | Tristan Van Berkom <tvb@src.gnome.org> | 2006-10-26 00:45:22 +0000 |
commit | 90ba661ff990afb46e400b59459b0fc64f647ef8 (patch) | |
tree | 3a04cb1802510edbd7aa7508291de49a9dafb2a0 | |
parent | 3a66616b3a9133032106b3a24e046cbc058e8c30 (diff) | |
download | glade-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-- | ChangeLog | 16 | ||||
-rw-r--r-- | INSTALL | 16 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/glade-design-layout.c | 742 | ||||
-rw-r--r-- | src/glade-design-layout.h | 64 | ||||
-rw-r--r-- | src/glade-design-view.c | 194 | ||||
-rw-r--r-- | src/glade-design-view.h | 73 | ||||
-rw-r--r-- | src/glade-project-view.c | 27 | ||||
-rw-r--r-- | src/glade-project-view.h | 2 | ||||
-rw-r--r-- | src/glade-project-window.c | 1160 | ||||
-rw-r--r-- | src/glade-project-window.h | 5 | ||||
-rw-r--r-- | src/glade-widget.c | 539 | ||||
-rw-r--r-- | src/glade-widget.h | 6 |
13 files changed, 2110 insertions, 738 deletions
@@ -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 @@ -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 = >K_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; |