Commit 51f4b3f3 authored by Tristan Van Berkom's avatar Tristan Van Berkom

* Another major refactor, tasks accomplished:

	  - Removed GladeApp selection handling, only on the project now
	  - Removed "Copy" as a command, copying widgets no longer dirty documents (bug 546873)
	  - Removed GladeApp "active_project" concept, every interaction is associated with
	    a GladeProject
	  - Simplified GladeClipboard, the clipboard now only has a list of widgets and
	    not a "selection", everything is removed from the clipboard when new widgets are
	    added there.
	  - GladePalette now has a "project" property and does not need to be refreshed
	    by an external entity.

	19 files changed, 652 insertions(+), 1135 deletions(-)
parent d4835f02
......@@ -16,6 +16,20 @@
* plugins/gtk+/gtk+.xml.in: Mark the "preview" action as "important" so it shows
up in the app toolbar automatically.
* Another major refactor, tasks accomplished:
- Removed GladeApp selection handling, only on the project now
- Removed "Copy" as a command, copying widgets no longer dirty documents (bug 546873)
- Removed GladeApp "active_project" concept, every interaction is associated with
a GladeProject
- Simplified GladeClipboard, the clipboard now only has a list of widgets and
not a "selection", everything is removed from the clipboard when new widgets are
added there.
- GladePalette now has a "project" property and does not need to be refreshed
by an external entity.
19 files changed, 652 insertions(+), 1135 deletions(-)
2011-01-02 Tristan Van Berkom <tristanvb@openismus.com>
* gladeui/glade-project.c: Fixed GladeProject to only ever report widgets that are
......
......@@ -64,7 +64,6 @@ enum
enum
{
PROP_0,
PROP_ACTIVE_PROJECT,
PROP_POINTER_MODE
};
......@@ -73,8 +72,6 @@ struct _GladeAppPrivate
GtkWidget *window;
GladePalette *palette; /* See glade-palette */
GladeProject *active_project; /* Currently active project (if there is at least one
* project; then this is always valid) */
GladeEditor *editor; /* See glade-editor */
GladeClipboard *clipboard; /* See glade-clipboard */
GList *catalogs; /* See glade-catalog */
......@@ -90,8 +87,6 @@ struct _GladeAppPrivate
GtkAccelGroup *accel_group; /* Default acceleration group for this app */
GladePointerMode pointer_mode; /* Current mode for the pointer in the workspace */
guint selection_changed_id; /* for queue_selection_changed() */
};
static guint glade_app_signals[LAST_SIGNAL] = { 0 };
......@@ -211,9 +206,6 @@ glade_app_set_property (GObject * object,
{
switch (property_id)
{
case PROP_ACTIVE_PROJECT:
glade_app_set_project (g_value_get_object (value));
break;
case PROP_POINTER_MODE:
glade_app_set_pointer_mode (g_value_get_enum (value));
break;
......@@ -232,9 +224,6 @@ glade_app_get_property (GObject * object,
switch (property_id)
{
case PROP_ACTIVE_PROJECT:
g_value_set_object (value, app->priv->active_project);
break;
case PROP_POINTER_MODE:
g_value_set_enum (value, app->priv->pointer_mode);
break;
......@@ -442,12 +431,6 @@ glade_app_class_init (GladeAppClass * klass)
NULL, NULL,
glade_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
g_object_class_install_property
(object_class, PROP_ACTIVE_PROJECT,
g_param_spec_object
("active-project", _("Active Project"),
_("The active project"), GLADE_TYPE_PROJECT, G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_POINTER_MODE,
g_param_spec_enum
......@@ -461,29 +444,6 @@ glade_app_class_init (GladeAppClass * klass)
/*****************************************************************
* Public API *
*****************************************************************/
static void
on_project_selection_changed_cb (GladeProject * project, GladeApp * app)
{
GList *list;
gint num;
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (GLADE_IS_APP (app));
/* Only update the editor if the selection has changed on
* the currently active project.
*/
if (app->priv->editor && (project == glade_app_get_project ()))
{
list = glade_project_selection_get (project);
num = g_list_length (list);
if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data))
glade_editor_load_widget (app->priv->editor,
glade_widget_get_from_gobject (list->data));
else
glade_editor_load_widget (app->priv->editor, NULL);
}
}
/**
* glade_app_config_save
......@@ -708,21 +668,6 @@ glade_app_get_clipboard (void)
return app->priv->clipboard;
}
GladeProject *
glade_app_get_project (void)
{
GladeApp *app = glade_app_get ();
return app->priv->active_project;
}
GladeProject *
glade_app_check_get_project (void)
{
if (singleton_app)
return glade_app_get_project ();
return NULL;
}
GList *
glade_app_get_projects (void)
{
......@@ -836,21 +781,10 @@ glade_app_add_project (GladeProject * project)
/* If the project was previously loaded, don't re-load */
if (g_list_find (app->priv->projects, project) != NULL)
{
glade_app_set_project (project);
return;
}
return;
/* Take a reference for GladeApp here... */
app->priv->projects = g_list_append (app->priv->projects,
g_object_ref (project));
/* connect to the project signals so that the editor can be updated */
g_signal_connect (G_OBJECT (project), "selection_changed",
G_CALLBACK (on_project_selection_changed_cb), app);
glade_app_set_project (project);
app->priv->projects = g_list_append (app->priv->projects, g_object_ref (project));
/* Select the first window in the project */
if (g_list_length (app->priv->projects) == 1 ||
......@@ -877,7 +811,6 @@ glade_app_add_project (GladeProject * project)
/* XXX I think the palette & editor should detect this by itself */
gtk_widget_set_sensitive (GTK_WIDGET (app->priv->palette), TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (app->priv->editor), TRUE);
}
void
......@@ -890,10 +823,6 @@ glade_app_remove_project (GladeProject * project)
app->priv->projects = g_list_remove (app->priv->projects, project);
/* this is needed to prevent clearing the selection of a closed project
*/
app->priv->active_project = NULL;
/* If no more projects */
if (app->priv->projects == NULL)
{
......@@ -906,8 +835,6 @@ glade_app_remove_project (GladeProject * project)
glade_editor_load_widget (app->priv->editor, NULL);
gtk_widget_set_sensitive (GTK_WIDGET (app->priv->editor), FALSE);
}
else
glade_app_set_project (g_list_last (app->priv->projects)->data);
/* Its safe to just release the project as the project emits a
* "close" signal and everyone is responsable for cleaning up at
......@@ -916,46 +843,6 @@ glade_app_remove_project (GladeProject * project)
g_object_unref (project);
}
/**
* glade_app_set_project:
* @project: A #GladeProject
*
* Sets the active project in the #GladeApp to @project.
*/
void
glade_app_set_project (GladeProject * project)
{
GladeApp *app = glade_app_get ();
g_return_if_fail (GLADE_IS_PROJECT (project));
if (app->priv->active_project == project)
return;
if (!g_list_find (app->priv->projects, project))
{
g_warning ("Could not set project because it could not "
" be found in the app->priv->project list\n");
return;
}
/* clear the selection in the previous project */
if (app->priv->active_project)
glade_project_selection_clear (app->priv->active_project, FALSE);
app->priv->active_project = project;
/* (XXX really ?) trigger the selection changed signal to update the editor */
glade_project_selection_changed (project);
/* refresh palette for active project */
glade_palette_refresh (glade_app_get_palette ());
g_object_notify (G_OBJECT (app), "active-project");
}
/**
* glade_app_set_pointer_mode:
* @mode: A #GladePointerMode
......@@ -988,272 +875,6 @@ glade_app_get_pointer_mode (void)
return app->priv->pointer_mode;
}
/**
* glade_app_command_copy:
* @app: A #GladeApp
*
* Copy the active project's selection (the new copies
* will end up on the clipboard and will be set as
* the clipboards selection).
*/
void
glade_app_command_copy (void)
{
GladeApp *app;
GList *widgets = NULL, *list;
GladeWidget *widget;
gboolean failed = FALSE;
app = glade_app_get ();
if (app->priv->active_project == NULL ||
glade_project_is_loading (app->priv->active_project))
return;
for (list = glade_app_get_selection (); list && list->data; list = list->next)
{
widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, widget);
}
if (failed == FALSE && widgets != NULL)
glade_command_copy (widgets);
else if (widgets == NULL)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("No widget selected."));
if (widgets)
g_list_free (widgets);
}
/**
* glade_app_command_cut:
* @app: A #GladeApp
*
* Cut the active project's selection (the cut objects
* will end up on the clipboard and will be set as
* the clipboards selection).
*/
void
glade_app_command_cut (void)
{
GladeApp *app;
GList *widgets = NULL, *list;
GladeWidget *widget;
gboolean failed = FALSE;
app = glade_app_get ();
if (app->priv->active_project == NULL ||
glade_project_is_loading (app->priv->active_project))
return;
for (list = glade_app_get_selection (); list && list->data; list = list->next)
{
widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, widget);
}
if (failed == FALSE && widgets != NULL)
glade_command_cut (widgets);
else if (widgets == NULL)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("No widget selected."));
if (widgets)
g_list_free (widgets);
}
/**
* glade_app_command_paste:
* @placeholder: A #GladePlaceholder
*
* Paste the clipboard selection to the active project's
* selection (the project must have only one object selected).
*/
void
glade_app_command_paste (GladePlaceholder * placeholder)
{
GladeApp *app;
GladeClipboard *clipboard;
GList *list;
GladeWidget *widget = NULL, *parent;
gint placeholder_relations = 0;
GladeFixed *fixed = NULL;
app = glade_app_get ();
if (app->priv->active_project == NULL ||
glade_project_is_loading (app->priv->active_project))
return;
if (placeholder)
{
if (glade_placeholder_get_project (placeholder) == NULL ||
glade_project_is_loading (glade_placeholder_get_project (placeholder)))
return;
}
list = glade_project_selection_get (app->priv->active_project);
clipboard = glade_app_get_clipboard ();
/* If there is a selection, paste in to the selected widget, otherwise
* paste into the placeholder's parent, or at the toplevel
*/
parent = list ? glade_widget_get_from_gobject (list->data) :
(placeholder) ? glade_placeholder_get_parent (placeholder) : NULL;
widget = clipboard->selection ? clipboard->selection->data : NULL;
/* Ignore parent argument if we are pasting a toplevel
*/
if (g_list_length (clipboard->selection) == 1 &&
widget && GWA_IS_TOPLEVEL (glade_widget_get_adaptor (widget)))
parent = NULL;
if (parent && GLADE_IS_FIXED (parent))
fixed = GLADE_FIXED (parent);
/* Check if parent is actually a container of any sort */
if (parent && !glade_widget_adaptor_is_container (glade_widget_get_adaptor (parent)))
{
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL,
_("Unable to paste to the selected parent"));
return;
}
/* Check if selection is good */
if ((list = glade_app_get_selection ()) != NULL)
{
if (g_list_length (list) != 1)
{
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL,
_("Unable to paste to multiple widgets"));
return;
}
}
/* Abort operation when adding a non scrollable widget to any kind of GtkScrolledWindow. */
if (parent && widget &&
glade_util_check_and_warn_scrollable (parent, glade_widget_get_adaptor (widget),
glade_app_get_window ()))
return;
/* Check if we have anything to paste */
if (g_list_length (clipboard->selection) == 0)
{
glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, NULL,
_("No widget selected on the clipboard"));
return;
}
/* Check that we have compatible heirarchies */
for (list = clipboard->selection; list && list->data; list = list->next)
{
widget = list->data;
if (!GWA_IS_TOPLEVEL (glade_widget_get_adaptor (widget)) && parent)
{
/* Count placeholder relations
*/
if (glade_widget_placeholder_relation (parent, widget))
placeholder_relations++;
}
}
g_assert (widget);
/* A GladeFixed that doesnt use placeholders can only paste one
* at a time
*/
if (GTK_IS_WIDGET (glade_widget_get_object (widget)) &&
parent && fixed &&
!GWA_USE_PLACEHOLDERS (glade_widget_get_adaptor (parent)) &&
g_list_length (clipboard->selection) != 1)
{
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL,
_("Only one widget can be pasted at a "
"time to this container"));
return;
}
/* Check that enough placeholders are available */
if (parent &&
GWA_USE_PLACEHOLDERS (glade_widget_get_adaptor (parent)) &&
glade_util_count_placeholders (parent) < placeholder_relations)
{
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL,
_("Insufficient amount of placeholders in "
"target container"));
return;
}
glade_command_paste (clipboard->selection, parent, placeholder);
}
/**
* glade_app_command_delete:
*
* Delete the active project's selection.
*/
void
glade_app_command_delete (void)
{
GladeApp *app;
GList *widgets = NULL, *list;
GladeWidget *widget;
gboolean failed = FALSE;
app = glade_app_get ();
if (app->priv->active_project == NULL ||
glade_project_is_loading (app->priv->active_project))
return;
for (list = glade_app_get_selection (); list && list->data; list = list->next)
{
widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, widget);
}
if (failed == FALSE && widgets != NULL)
glade_command_delete (widgets);
else if (widgets == NULL)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("No widget selected."));
if (widgets)
g_list_free (widgets);
}
/**
* glade_app_command_delete_clipboard:
*
* Delete the clipboard's selection.
*/
void
glade_app_command_delete_clipboard (void)
{
GladeClipboard *clipboard;
clipboard = glade_app_get_clipboard ();
if (clipboard->selection == NULL)
{
glade_util_ui_message (glade_app_get_window (), GLADE_UI_INFO, NULL,
_("No widget selected on the clipboard"));
return;
}
glade_command_delete (clipboard->selection);
}
/*
* glade_app_set_accel_group:
*
......@@ -1278,129 +899,6 @@ glade_app_get_accel_group (void)
return glade_app_get ()->priv->accel_group;
}
GList *
glade_app_get_selection (void)
{
GList *selection = NULL, *list;
GladeProject *project;
for (list = glade_app_get_projects (); list && list->data; list = list->next)
{
/* Only one project may have selection at a time
*/
project = list->data;
if (glade_project_selection_get (project))
{
selection = glade_project_selection_get (project);
break;
}
}
return selection;
}
gboolean
glade_app_is_selected (GObject * object)
{
return (g_list_find (glade_app_get_selection (), object) != NULL);
}
void
glade_app_selection_set (GObject * object, gboolean emit_signal)
{
GList *list;
GladeProject *project;
for (list = glade_app_get_projects (); list && list->data; list = list->next)
{
project = list->data;
if (glade_project_has_object (project, object))
glade_project_selection_set (project, object, emit_signal);
else
glade_project_selection_clear (project, emit_signal);
}
/* Instead of calling selection_set after all
* the selection_clear calls (lazy).
*/
if (GTK_IS_WIDGET (object))
glade_util_add_selection (GTK_WIDGET (object));
}
void
glade_app_selection_add (GObject * object, gboolean emit_signal)
{
GList *list;
GladeWidget *widget = glade_widget_get_from_gobject (object), *selected;
GladeProject *project = glade_widget_get_project (widget);
/* Ignore request if the there is a selection
* from another project.
*/
if ((list = glade_app_get_selection ()) != NULL)
{
selected = glade_widget_get_from_gobject (list->data);
if (glade_widget_get_project (selected) != project)
return;
}
glade_project_selection_add (project, object, emit_signal);
}
void
glade_app_selection_remove (GObject * object, gboolean emit_signal)
{
GladeWidget *widget = glade_widget_get_from_gobject (object);
GladeProject *project = glade_widget_get_project (widget);;
glade_project_selection_remove (project, object, emit_signal);
}
void
glade_app_selection_clear (gboolean emit_signal)
{
GList *list;
GladeProject *project;
glade_util_clear_selection ();
for (list = glade_app_get_projects (); list && list->data; list = list->next)
{
project = list->data;
glade_project_selection_clear (project, emit_signal);
}
}
void
glade_app_selection_changed (void)
{
GList *list;
GladeProject *project;
for (list = glade_app_get_projects (); list && list->data; list = list->next)
{
project = list->data;
glade_project_selection_changed (project);
}
}
static gboolean
selection_change_idle (GladeApp * app)
{
glade_app_selection_changed ();
app->priv->selection_changed_id = 0;
return FALSE;
}
void
glade_app_queue_selection_changed (void)
{
GladeApp *app = glade_app_get ();
if (app->priv->selection_changed_id == 0)
app->priv->selection_changed_id =
g_idle_add ((GSourceFunc) selection_change_idle, app);
}
GladeApp *
glade_app_new (void)
{
......
......@@ -108,12 +108,6 @@ GladePalette* glade_app_get_palette (void);
GladeClipboard* glade_app_get_clipboard (void);
GladeProject* glade_app_get_project (void);
GladeProject* glade_app_check_get_project (void);
void glade_app_set_project (GladeProject *project);
GladePointerMode glade_app_get_pointer_mode (void);
void glade_app_set_pointer_mode (GladePointerMode mode);
......@@ -133,22 +127,6 @@ GladeProject* glade_app_get_project_by_path (const gchar *project_path);
void glade_app_show_properties (gboolean raise);
void glade_app_hide_properties (void);
void glade_app_command_copy (void);
void glade_app_command_cut (void);
void glade_app_command_paste (GladePlaceholder *placeholder);
void glade_app_command_delete (void);
void glade_app_command_delete_clipboard (void);
void glade_app_command_undo (void);
void glade_app_command_redo (void);
gint glade_app_config_save (void);
......@@ -162,28 +140,6 @@ GtkAccelGroup *glade_app_get_accel_group (void);
GList *glade_app_get_selection (void);
/* These handle selection on a global scope and take care
* of multiple project logic.
*/
gboolean glade_app_is_selected (GObject *object);
void glade_app_selection_set (GObject *object,
gboolean emit_signal);
void glade_app_selection_add (GObject *object,
gboolean emit_signal);
void glade_app_selection_remove (GObject *object,
gboolean emit_signal);
void glade_app_selection_clear (gboolean emit_signal);
void glade_app_selection_changed (void);
void glade_app_queue_selection_changed (void);
/* package paths */
const gchar *glade_app_get_catalogs_dir (void) G_GNUC_CONST;
......
......@@ -1457,17 +1457,17 @@ glade_base_editor_class_init (GladeBaseEditorClass * klass)
("The container object this editor is currently editing"),
G_TYPE_OBJECT, G_PARAM_READWRITE));
/**
* GladeBaseEditor::child-selected:
* @gladebaseeditor: the #GladeBaseEditor which received the signal.
* @gchild: the selected #GladeWidget.
*
* Emited when the user selects a child in the editor's treeview.
* You can add the relevant child properties here using
* glade_base_editor_add_default_properties() and glade_base_editor_add_properties()
* You can also add labels with glade_base_editor_add_label to make the
* editor look pretty.
*/
/**
* GladeBaseEditor::child-selected:
* @gladebaseeditor: the #GladeBaseEditor which received the signal.
* @gchild: the selected #GladeWidget.
*
* Emited when the user selects a child in the editor's treeview.
* You can add the relevant child properties here using
* glade_base_editor_add_default_properties() and glade_base_editor_add_properties()
* You can also add labels with glade_base_editor_add_label to make the
* editor look pretty.
*/
glade_base_editor_signals[SIGNAL_CHILD_SELECTED] =
g_signal_new ("child-selected",
G_TYPE_FROM_CLASS (object_class),
......@@ -1476,14 +1476,14 @@ glade_base_editor_class_init (GladeBaseEditorClass * klass)
NULL, NULL,
glade_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
/**
* GladeBaseEditor::child-change-type:
* @gladebaseeditor: the #GladeBaseEditor which received the signal.
* @child: the #GObject being changed.
* @type: the new type for @child.
*
* Returns: TRUE to stop signal emision.
*/
/**
* GladeBaseEditor::child-change-type:
* @gladebaseeditor: the #GladeBaseEditor which received the signal.
* @child: the #GObject being changed.
* @type: the new type for @child.
*
* Returns: TRUE to stop signal emision.
*/
glade_base_editor_signals[SIGNAL_CHANGE_TYPE] =
g_signal_new ("change-type",
G_TYPE_FROM_CLASS (object_class),
......@@ -1493,14 +1493,14 @@ glade_base_editor_class_init (GladeBaseEditorClass * klass)
glade_marshal_BOOLEAN__OBJECT_UINT,
G_TYPE_BOOLEAN, 2, G_TYPE_OBJECT, G_TYPE_UINT);