Commit e86dd963 authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

Reimplemented GtkMenuItem and subclasses from top to bottom


	* plugins/gtk+/gtk+.xml.in, plugins/gtk+/glade-gtk.c: 
	Reimplemented GtkMenuItem and subclasses from top to bottom

	* plugins/gtk+/glade-image-item-editor.[ch], plugins/gtk+/Makefile.am:
	New GtkImageMenuItem editor (that embeds the child image editor when needed)

	* gladeui/glade-command.[ch]: Added glade_command_[un]protect_widget()

	* gladeui/glade-widget.[ch]: Added glade_widget_[un]protect()
	protected widgets come with a message and cannot be manually deleted
	from the project.

	* plugins/gtk+/glade-image-editor.c, plugins/gtk+/glade-button-editor.c,
	plugins/gtk+/glade-tool-button-editor.c, gladeui/glade-editor-table.c:
	Fixed to:
	- not reffer to child editables in finalize
	- always removed external signals and weak references from finalize

	* gladeui/glade-base-editor.c: Fixed to allow properties expand/fill
	in both label and entry.


svn path=/trunk/; revision=2006
parent c20614b4
2008-10-28 Tristan Van Berkom <tvb@gnome.org>
* plugins/gtk+/gtk+.xml.in, plugins/gtk+/glade-gtk.c:
Reimplemented GtkMenuItem and subclasses from top to bottom
* plugins/gtk+/glade-image-item-editor.[ch], plugins/gtk+/Makefile.am:
New GtkImageMenuItem editor (that embeds the child image editor when needed)
* gladeui/glade-command.[ch]: Added glade_command_[un]protect_widget()
* gladeui/glade-widget.[ch]: Added glade_widget_[un]protect()
protected widgets come with a message and cannot be manually deleted
from the project.
* plugins/gtk+/glade-image-editor.c, plugins/gtk+/glade-button-editor.c,
plugins/gtk+/glade-tool-button-editor.c, gladeui/glade-editor-table.c:
Fixed to:
- not reffer to child editables in finalize
- always removed external signals and weak references from finalize
* gladeui/glade-base-editor.c: Fixed to allow properties expand/fill
in both label and entry.
2008-10-27 Tristan Van Berkom <tvb@gnome.org>
* plugins/gtk+/gtk+.xml.in, plugins/gtk+/glade-gtk.c:
......
......@@ -319,14 +319,14 @@ glade_base_editor_table_attach (GladeBaseEditor *e,
if (child1)
{
gtk_table_attach (table, child1, 0, 1, row, row + 1,
GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0);
GTK_EXPAND | GTK_FILL, GTK_FILL, 2, 0);
gtk_widget_show (child1);
}
if (child2)
{
gtk_table_attach (table, child2, 1, 2, row, row + 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0);
GTK_EXPAND | GTK_FILL, GTK_FILL, 2, 0);
gtk_widget_show (child2);
}
......@@ -378,7 +378,8 @@ static gboolean
glade_base_editor_update_properties_idle (gpointer data)
{
GladeBaseEditor *editor = (GladeBaseEditor *)data;
glade_base_editor_treeview_cursor_changed (NULL, editor);
glade_base_editor_treeview_cursor_changed
(GTK_TREE_VIEW (editor->priv->treeview), editor);
editor->priv->properties_idle = 0;
return FALSE;
}
......@@ -1709,16 +1710,13 @@ void
glade_base_editor_add_editable (GladeBaseEditor *editor,
GladeWidget *gchild)
{
GladeEditorProperty *eprop;
GladeEditable *editable;
va_list args;
gchar *property;
GladeEditable *editable;
gint row;
g_return_if_fail (GLADE_IS_BASE_EDITOR (editor));
g_return_if_fail (GLADE_IS_WIDGET (gchild));
editable = (GtkWidget *)glade_widget_adaptor_create_editable (gchild->adaptor, GLADE_PAGE_GENERAL);
editable = glade_widget_adaptor_create_editable (gchild->adaptor, GLADE_PAGE_GENERAL);
glade_editable_set_show_name (editable, FALSE);
glade_editable_load (editable, gchild);
gtk_widget_show (GTK_WIDGET (editable));
......@@ -1758,8 +1756,9 @@ glade_base_editor_add_label (GladeBaseEditor *editor, gchar *str)
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
gtk_misc_set_padding (GTK_MISC (label), 0, 6);
gtk_table_attach (GTK_TABLE (editor->priv->table), label, 0, 2, row, row + 1,
GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0);
GTK_FILL, GTK_FILL, 2, 0);
gtk_widget_show (label);
editor->priv->row++;
......
......@@ -1106,6 +1106,12 @@ glade_command_remove (GList *widgets)
_("You cannot remove a widget internal to a composite widget."));
return;
}
if (widget->protection)
{
glade_util_ui_message (glade_app_get_window(),
GLADE_UI_WARN, NULL, widget->protection);
return;
}
}
me->project = glade_widget_get_project (widget);
......@@ -1618,6 +1624,7 @@ glade_command_clipboard_add_remove_collapse (GladeCommand *this_cmd, GladeComman
/**
* glade_command_create:
* @adaptor: A #GladeWidgetAdaptor
* @parent: the parent #GladeWidget to add the new widget to.
* @placeholder: the placeholder which will be substituted by the widget
* @project: the project his widget belongs to.
*
......@@ -2529,3 +2536,154 @@ glade_command_set_project_naming_policy (GladeProject *project,
/******************************************************************************
*
* This command sets protection warnings on widgets
*
*****************************************************************************/
typedef struct {
GladeCommand parent;
GladeWidget *widget;
gchar *warning;
gboolean protecting;
} GladeCommandProtect;
GLADE_MAKE_COMMAND (GladeCommandProtect, glade_command_protect);
#define GLADE_COMMAND_PROTECT_TYPE (glade_command_protect_get_type ())
#define GLADE_COMMAND_PROTECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GLADE_COMMAND_PROTECT_TYPE, GladeCommandProtect))
#define GLADE_COMMAND_PROTECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GLADE_COMMAND_PROTECT_TYPE, GladeCommandProtectClass))
#define GLADE_IS_COMMAND_PROTECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GLADE_COMMAND_PROTECT_TYPE))
#define GLADE_IS_COMMAND_PROTECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GLADE_COMMAND_PROTECT_TYPE))
static gboolean
glade_command_protect_execute(GladeCommand *cmd)
{
GladeCommandProtect *me = (GladeCommandProtect *)cmd;
/* set the new policy */
if (me->protecting)
glade_widget_protect (me->widget, me->warning);
else
glade_widget_unprotect (me->widget);
/* swap the current values with the old values to prepare for undo */
me->protecting = !me->protecting;
return TRUE;
}
static gboolean
glade_command_protect_undo(GladeCommand *cmd)
{
return glade_command_protect_execute(cmd);
}
static void
glade_command_protect_finalize(GObject *obj)
{
GladeCommandProtect *me = (GladeCommandProtect *)obj;
g_object_unref (me->widget);
glade_command_finalize(obj);
}
static gboolean
glade_command_protect_unifies (GladeCommand *this_cmd, GladeCommand *other_cmd)
{
/* GladeCommandProtect *cmd1; */
/* GladeCommandProtect *cmd2; */
/* No point here, this command undoubtedly always runs in groups */
return FALSE;
}
static void
glade_command_protect_collapse (GladeCommand *this_cmd, GladeCommand *other_cmd)
{
/* this command is the one that will be used for an undo of the sequence of like commands */
//GladeCommandProtect *this = GLADE_COMMAND_PROTECT (this_cmd);
/* the other command contains the values that will be used for a redo */
//GladeCommandProtect *other = GLADE_COMMAND_PROTECT (other_cmd);
g_return_if_fail (GLADE_IS_COMMAND_PROTECT (this_cmd) && GLADE_IS_COMMAND_PROTECT (other_cmd));
/* no unify/collapse */
}
/**
* glade_command_protect_widget:
* @widget: A #GladeWidget
* @warning: the warning to print when a user tries to delete this widget
*
* Sets the protection status and @warning on @widget
*/
void
glade_command_protect_widget (GladeWidget *widget,
const gchar *warning)
{
GladeCommandProtect *me;
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (widget->protection == NULL);
g_return_if_fail (warning && warning[0]);
/* load up the command */
me = g_object_new(GLADE_COMMAND_PROTECT_TYPE, NULL);
me->widget = g_object_ref (widget);
me->protecting = TRUE;
me->warning = g_strdup (warning);
GLADE_COMMAND(me)->description = g_strdup_printf(_("Protecting %s"), widget->name);
glade_command_check_group(GLADE_COMMAND(me));
/* execute the command and push it on the stack if successful
* this sets the actual policy
*/
if (glade_command_protect_execute(GLADE_COMMAND(me)))
glade_project_push_undo(glade_app_get_project(), GLADE_COMMAND(me));
else
g_object_unref(G_OBJECT(me));
}
/**
* glade_command_unprotect_widget:
* @widget: A #GladeWidget
*
* Unsets the protection status of @widget
*/
void
glade_command_unprotect_widget (GladeWidget *widget)
{
GladeCommandProtect *me;
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (widget->protection && widget->protection[0]);
/* load up the command */
me = g_object_new(GLADE_COMMAND_PROTECT_TYPE, NULL);
me->widget = g_object_ref (widget);
me->protecting = FALSE;
me->warning = g_strdup (widget->protection);
GLADE_COMMAND(me)->description = g_strdup_printf(_("Unprotecting %s"), widget->name);
glade_command_check_group(GLADE_COMMAND(me));
/* execute the command and push it on the stack if successful
* this sets the actual policy
*/
if (glade_command_protect_execute(GLADE_COMMAND(me)))
glade_project_push_undo(glade_app_get_project(), GLADE_COMMAND(me));
else
g_object_unref(G_OBJECT(me));
}
......@@ -114,6 +114,13 @@ void glade_command_set_properties_list (GladeProject *project,
void glade_command_set_name (GladeWidget *glade_widget, const gchar *name);
/************************ protection ******************************/
void glade_command_protect_widget (GladeWidget *widget,
const gchar *warning);
void glade_command_unprotect_widget (GladeWidget *widget);
/************************ create/delete ******************************/
void glade_command_delete (GList *widgets);
......
......@@ -431,18 +431,7 @@ static void
glade_editor_property_load_common (GladeEditorProperty *eprop,
GladeProperty *property)
{
/* Hide properties that are removed for some particular widgets.
*/
if (property)
{
gtk_widget_show (GTK_WIDGET (eprop));
gtk_widget_show (eprop->item_label);
}
else
{
gtk_widget_hide (GTK_WIDGET (eprop));
gtk_widget_hide (eprop->item_label);
}
/* NOTE THIS CODE IS FINALIZE SAFE */
/* disconnect anything from previously loaded property */
if (eprop->property != property && eprop->property != NULL)
......
......@@ -59,6 +59,12 @@ glade_editor_table_finalize (GObject *object)
table->properties =
(g_list_free (table->properties), NULL);
/* the entry is finalized anyway, just avoid setting
* text in it from _load();
*/
table->name_entry = NULL;
glade_editable_load (GLADE_EDITABLE (table), NULL);
G_OBJECT_CLASS (glade_editor_table_parent_class)->finalize (object);
......@@ -69,7 +75,7 @@ glade_editor_table_grab_focus (GtkWidget *widget)
{
GladeEditorTable *editor_table = GLADE_EDITOR_TABLE (widget);
if (editor_table->name_entry)
if (editor_table->name_entry && GTK_WIDGET_MAPPED (editor_table->name_entry))
gtk_widget_grab_focus (editor_table->name_entry);
else if (editor_table->properties)
gtk_widget_grab_focus (GTK_WIDGET (editor_table->properties->data));
......@@ -322,9 +328,11 @@ append_name_field (GladeEditorTable *table)
table->name_label = gtk_label_new (_("Name:"));
gtk_misc_set_alignment (GTK_MISC (table->name_label), 0.0, 0.5);
gtk_widget_show (table->name_label);
gtk_widget_set_no_show_all (table->name_label, TRUE);
table->name_entry = gtk_entry_new ();
gtk_widget_show (table->name_entry);
gtk_widget_set_no_show_all (table->name_entry, TRUE);
gtk_widget_set_tooltip_text (table->name_label, text);
gtk_widget_set_tooltip_text (table->name_entry, text);
......
......@@ -954,7 +954,7 @@ glade_widget_adaptor_object_write_widget (GladeWidgetAdaptor *adaptor,
GladeWidget *child = glade_widget_get_from_gobject (l->data);
if (child)
glade_widget_write_child (child, context, node);
glade_widget_write_child (widget, child, context, node);
else if (GLADE_IS_PLACEHOLDER (l->data))
glade_widget_write_placeholder (widget,
G_OBJECT (l->data),
......@@ -2269,6 +2269,7 @@ glade_widget_adaptor_from_catalog (GladeCatalog *catalog,
* outside of the hierarchy.
* @internal_object: the #GObject
* @internal_name: a string identifier for this internal widget.
* @parent_name: the generic name of the parent used for fancy child names.
* @anarchist: Whether or not this widget is a widget outside
* of the parent's hierarchy (like a popup window)
* @reason: The #GladeCreateReason for which this internal widget
......@@ -2296,7 +2297,7 @@ glade_widget_adaptor_create_internal (GladeWidget *parent,
g_return_val_if_fail (GLADE_IS_WIDGET (parent), NULL);
project = glade_widget_get_project (parent);
if ((adaptor = glade_widget_adaptor_get_by_name
if ((adaptor = glade_widget_adaptor_get_by_name
(G_OBJECT_TYPE_NAME (internal_object))) == NULL)
{
g_critical ("Unable to find widget class for type %s",
......
......@@ -3633,7 +3633,8 @@ glade_widget_read (GladeProject *project,
/**
* glade_widget_write_child:
* @widget: The #GladeWidget
* @widget: A #GladeWidget
* @child: The child #GladeWidget to write
* @context: A #GladeXmlContext
* @node: A #GladeXmlNode
*
......@@ -3642,13 +3643,16 @@ glade_widget_read (GladeProject *project,
*/
void
glade_widget_write_child (GladeWidget *widget,
GladeWidget *child,
GladeXmlContext *context,
GladeXmlNode *node)
{
g_return_if_fail (widget->parent);
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (GLADE_IS_WIDGET (child));
g_return_if_fail (child->parent == widget);
glade_widget_adaptor_write_child (widget->parent->adaptor,
widget, context, node);
glade_widget_adaptor_write_child (widget->adaptor,
child, context, node);
}
......@@ -4161,3 +4165,25 @@ glade_widget_set_support_warning (GladeWidget *widget,
g_object_notify (G_OBJECT (widget), "support-warning");
}
void
glade_widget_protect (GladeWidget *widget,
const gchar *warning)
{
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (warning && warning[0]);
if (widget->protection)
g_free (widget->protection);
widget->protection = g_strdup (warning);
}
void
glade_widget_unprotect (GladeWidget *widget)
{
g_return_if_fail (GLADE_IS_WIDGET (widget));
if (widget->protection)
g_free (widget->protection);
widget->protection = NULL;
}
......@@ -41,6 +41,12 @@ struct _GladeWidget
* in this widget
*/
gchar *protection; /* custom editors are allowed to add protected widgets that
* cannot be deleted by the user in normal ways.
* (this is a message to be displayed in the dialog
* when the user tries to delete it).
*/
gchar *internal; /* If the widget is an internal child of
* another widget this is the name of the
* internal child, otherwise is NULL.
......@@ -224,6 +230,7 @@ void glade_widget_write (GladeWidget *wi
GladeXmlNode *node);
void glade_widget_write_child (GladeWidget *widget,
GladeWidget *child,
GladeXmlContext *context,
GladeXmlNode *node);
......@@ -403,6 +410,10 @@ void glade_widget_pop_superuser (void);
void glade_widget_set_support_warning (GladeWidget *widget,
const gchar *warning);
void glade_widget_protect (GladeWidget *widget,
const gchar *warning);
void glade_widget_unprotect (GladeWidget *widget);
G_END_DECLS
#endif /* __GLADE_WIDGET_H__ */
......@@ -25,7 +25,8 @@ libgladegtk_la_CFLAGS = \
libgladegtk_la_SOURCES = glade-gtk.c glade-accels.c glade-attributes.c glade-convert.c fixed-bg.xpm \
glade-column-types.c glade-model-data.c glade-text-button.c glade-cell-renderer-button.c \
glade-icon-sources.c glade-button-editor.c glade-tool-button-editor.c glade-image-editor.c
glade-icon-sources.c glade-button-editor.c glade-tool-button-editor.c glade-image-editor.c \
glade-image-item-editor.c
libgladegtk_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
libgladegtk_la_LIBADD = $(libgladeui) $(GTK_LIBS)
......@@ -33,7 +34,7 @@ libgladegtk_la_LIBADD = $(libgladeui) $(GTK_LIBS)
libgladegtkincludedir= $(includedir)/libgladeui-1.0/gladeui
libgladegtkinclude_HEADERS = glade-gtk.h glade-accels.h glade-attributes.h glade-column-types.h glade-model-data.h \
glade-text-button.h glade-cell-renderer-button.h glade-icon-sources.h glade-button-editor.h \
glade-tool-button-editor.h glade-image-editor.h
glade-tool-button-editor.h glade-image-editor.h glade-image-item-editor.h
if PLATFORM_WIN32
libgladegtk_la_LDFLAGS += -no-undefined
......
......@@ -121,7 +121,8 @@ glade_button_editor_load (GladeEditable *editable,
}
/* load the embedded editable... */
glade_editable_load (GLADE_EDITABLE (button_editor->embed), widget);
if (button_editor->embed)
glade_editable_load (GLADE_EDITABLE (button_editor->embed), widget);
for (l = button_editor->properties; l; l = l->next)
glade_editor_property_load_by_widget (GLADE_EDITOR_PROPERTY (l->data), widget);
......@@ -190,6 +191,10 @@ glade_button_editor_finalize (GObject *object)
if (button_editor->properties)
g_list_free (button_editor->properties);
button_editor->properties = NULL;
button_editor->embed = NULL;
glade_editable_load (GLADE_EDITABLE (object), NULL);
G_OBJECT_CLASS (glade_button_editor_parent_class)->finalize (object);
}
......
This diff is collapsed.
......@@ -119,12 +119,12 @@ glade_image_editor_load (GladeEditable *editable,
}
/* load the embedded editable... */
glade_editable_load (GLADE_EDITABLE (image_editor->embed), widget);
if (image_editor->embed)
glade_editable_load (GLADE_EDITABLE (image_editor->embed), widget);
for (l = image_editor->properties; l; l = l->next)
glade_editor_property_load_by_widget (GLADE_EDITOR_PROPERTY (l->data), widget);
if (widget)
{
glade_widget_property_get (widget, "image-mode", &image_mode);
......@@ -170,6 +170,10 @@ glade_image_editor_finalize (GObject *object)
if (image_editor->properties)
g_list_free (image_editor->properties);
image_editor->properties = NULL;
image_editor->embed = NULL;
glade_editable_load (GLADE_EDITABLE (object), NULL);
G_OBJECT_CLASS (glade_image_editor_parent_class)->finalize (object);
}
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2008 Tristan Van Berkom.
*
* 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.
*
* Authors:
* Tristan Van Berkom <tvb@gnome.org>
*/
#include <config.h>
#include <gladeui/glade.h>
#include <glib/gi18n-lib.h>
#include <gdk/gdkkeysyms.h>
#include "glade-image-item-editor.h"
static void glade_image_item_editor_finalize (GObject *object);
static void glade_image_item_editor_editable_init (GladeEditableIface *iface);
static void glade_image_item_editor_grab_focus (GtkWidget *widget);
G_DEFINE_TYPE_WITH_CODE (GladeImageItemEditor, glade_image_item_editor, GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE (GLADE_TYPE_EDITABLE,
glade_image_item_editor_editable_init));
static void
glade_image_item_editor_class_init (GladeImageItemEditorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = glade_image_item_editor_finalize;
widget_class->grab_focus = glade_image_item_editor_grab_focus;
}
static void
glade_image_item_editor_init (GladeImageItemEditor *self)
{
}
static void
project_changed (GladeProject *project,
GladeCommand *command,
gboolean execute,
GladeImageItemEditor *item_editor)
{
if (item_editor->modifying ||
!GTK_WIDGET_MAPPED (item_editor))
return;
/* Reload on all commands */
glade_editable_load (GLADE_EDITABLE (item_editor), item_editor->loaded_widget);
}
static void
project_finalized (GladeImageItemEditor *item_editor,
GladeProject *where_project_was)
{
item_editor->loaded_widget = NULL;
glade_editable_load (GLADE_EDITABLE (item_editor), NULL);
}
static GladeWidget *
get_image_widget (GladeWidget *widget)
{
GtkWidget *image;
image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget->object));
return image ? glade_widget_get_from_gobject (image) : NULL;
}
static void
glade_image_item_editor_load (GladeEditable *editable,
GladeWidget *widget)
{
GladeImageItemEditor *item_editor = GLADE_IMAGE_ITEM_EDITOR (editable);
GladeWidget *image_widget;
GList *l;
gboolean use_stock = FALSE;
item_editor->loading = TRUE;
/* Since we watch the project*/
if (item_editor->loaded_widget)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (item_editor->loaded_widget->project),
G_CALLBACK (project_changed), item_editor);
/* The widget could die unexpectedly... */
g_object_weak_unref (G_OBJECT (item_editor->loaded_widget->project),
(GWeakNotify)project_finalized,
item_editor);
}