From 87480880c3f6dc56c3b6dea4a01249d97e390a37 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Fri, 10 Oct 2003 15:59:12 +0000 Subject: [PATCH] Cleaned up session management and changed the format of sessionrc in a way 2003-10-10 Michael Natterer Cleaned up session management and changed the format of sessionrc in a way that allows extensions without changing the format during the 2.0 cycle: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpsessioninfo.[ch]: new files implementing the whole GimpSessionInfo stuff (parsing, saving, restoring, utility functions). Save / parse the position of GimpDock's panes (bug #122964). * app/widgets/gimpdialogfactory.[ch]: removed saving, restoring and session related utility functions and use the ones from the new files above. * app/gui/session.c: removed parsing and use the new stuff. * app/widgets/gimpdock.[ch]: added new virtual functions GimpDock::set_aux_info() and GimpDock::get_aux_info(): * app/widgets/gimpimagedock.c: implement them and handle the "auto_follow_active" and "show_image_menu" properties. * app/widgets/gimpdockable.[ch]: added the same virtual functions to the GimpDockable class. Enables forward-compatible per-dockable session management (bug #122964). * app/gui/dialogs-commands.c * app/gui/gui.c: changed accordingly. * etc/sessionrc: ditto. Look at this file and update your own sessionrc manually if you don't want to lose it. --- ChangeLog | 34 ++ app/actions/dialogs-commands.c | 1 + app/gui/dialogs-commands.c | 1 + app/gui/gui.c | 1 + app/gui/session.c | 251 +-------- app/widgets/Makefile.am | 2 + app/widgets/gimpdialogfactory.c | 440 +--------------- app/widgets/gimpdialogfactory.h | 24 - app/widgets/gimpdock.c | 21 + app/widgets/gimpdock.h | 53 +- app/widgets/gimpdockable.c | 44 ++ app/widgets/gimpdockable.h | 8 + app/widgets/gimpsessioninfo.c | 899 ++++++++++++++++++++++++++++++++ app/widgets/gimpsessioninfo.h | 82 +++ app/widgets/widgets-types.h | 4 + etc/sessionrc | 29 +- 16 files changed, 1167 insertions(+), 727 deletions(-) create mode 100644 app/widgets/gimpsessioninfo.c create mode 100644 app/widgets/gimpsessioninfo.h diff --git a/ChangeLog b/ChangeLog index acd9e816eb..59285feece 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2003-10-10 Michael Natterer + + Cleaned up session management and changed the format of sessionrc + in a way that allows extensions without changing the format during + the 2.0 cycle: + + * app/widgets/Makefile.am + * app/widgets/widgets-types.h + * app/widgets/gimpsessioninfo.[ch]: new files implementing the whole + GimpSessionInfo stuff (parsing, saving, restoring, utility functions). + Save / parse the position of GimpDock's panes (bug #122964). + + * app/widgets/gimpdialogfactory.[ch]: removed saving, restoring + and session related utility functions and use the ones from + the new files above. + + * app/gui/session.c: removed parsing and use the new stuff. + + * app/widgets/gimpdock.[ch]: added new virtual functions + GimpDock::set_aux_info() and GimpDock::get_aux_info(): + + * app/widgets/gimpimagedock.c: implement them and handle the + "auto_follow_active" and "show_image_menu" properties. + + * app/widgets/gimpdockable.[ch]: added the same virtual functions + to the GimpDockable class. Enables forward-compatible per-dockable + session management (bug #122964). + + * app/gui/dialogs-commands.c + * app/gui/gui.c: changed accordingly. + + * etc/sessionrc: ditto. Look at this file and update your own + sessionrc manually if you don't want to lose it. + 2003-10-10 Sven Neumann * plug-ins/script-fu/scripts/burn-in-anim.scm: repaired this script diff --git a/app/actions/dialogs-commands.c b/app/actions/dialogs-commands.c index dc9a6baf88..23017edd25 100644 --- a/app/actions/dialogs-commands.c +++ b/app/actions/dialogs-commands.c @@ -30,6 +30,7 @@ #include "widgets/gimpdockable.h" #include "widgets/gimpdockbook.h" #include "widgets/gimpimagedock.h" +#include "widgets/gimpsessioninfo.h" #include "dialogs.h" #include "dialogs-commands.h" diff --git a/app/gui/dialogs-commands.c b/app/gui/dialogs-commands.c index dc9a6baf88..23017edd25 100644 --- a/app/gui/dialogs-commands.c +++ b/app/gui/dialogs-commands.c @@ -30,6 +30,7 @@ #include "widgets/gimpdockable.h" #include "widgets/gimpdockbook.h" #include "widgets/gimpimagedock.h" +#include "widgets/gimpsessioninfo.h" #include "dialogs.h" #include "dialogs-commands.h" diff --git a/app/gui/gui.c b/app/gui/gui.c index 4f38af2be0..e36f868fe9 100644 --- a/app/gui/gui.c +++ b/app/gui/gui.c @@ -51,6 +51,7 @@ #include "widgets/gimphelp-ids.h" #include "widgets/gimpitemfactory.h" #include "widgets/gimpmenufactory.h" +#include "widgets/gimpsessioninfo.h" #include "widgets/gimpwidgets-utils.h" #include "dialogs.h" diff --git a/app/gui/session.c b/app/gui/session.c index 6d16a24b0e..4eacf36f7f 100644 --- a/app/gui/session.c +++ b/app/gui/session.c @@ -38,6 +38,7 @@ #include "config/gimpscanner.h" #include "widgets/gimpdialogfactory.h" +#include "widgets/gimpsessioninfo.h" #include "color-history.h" #include "session.h" @@ -45,30 +46,16 @@ #include "gimp-intl.h" -/* local function prototypes */ - -static GTokenType session_info_deserialize (GScanner *scanner, - Gimp *gimp); -static GTokenType session_info_dock_deserialize (GScanner *scanner, - GimpSessionInfo *info); - -/* public functions */ - enum { SESSION_INFO = 1, COLOR_HISTORY, - LAST_TIP_SHOWN, - - SESSION_INFO_POSITION, - SESSION_INFO_SIZE, - SESSION_INFO_OPEN, - SESSION_INFO_AUX, - SESSION_INFO_DOCK, - - SESSION_INFO_DOCK_BOOK + LAST_TIP_SHOWN }; + +/* public functions */ + void session_init (Gimp *gimp) { @@ -99,20 +86,6 @@ session_init (Gimp *gimp) g_scanner_scope_add_symbol (scanner, 0, "last-tip-shown", GINT_TO_POINTER (LAST_TIP_SHOWN)); - g_scanner_scope_add_symbol (scanner, SESSION_INFO, "position", - GINT_TO_POINTER (SESSION_INFO_POSITION)); - g_scanner_scope_add_symbol (scanner, SESSION_INFO, "size", - GINT_TO_POINTER (SESSION_INFO_SIZE)); - g_scanner_scope_add_symbol (scanner, SESSION_INFO, "open-on-exit", - GINT_TO_POINTER (SESSION_INFO_OPEN)); - g_scanner_scope_add_symbol (scanner, SESSION_INFO, "aux-info", - GINT_TO_POINTER (SESSION_INFO_AUX)); - g_scanner_scope_add_symbol (scanner, SESSION_INFO, "dock", - GINT_TO_POINTER (SESSION_INFO_DOCK)); - - g_scanner_scope_add_symbol (scanner, SESSION_INFO_DOCK, "book", - GINT_TO_POINTER (SESSION_INFO_DOCK_BOOK)); - token = G_TOKEN_LEFT_PAREN; while (g_scanner_peek_next_token (scanner) == token) @@ -129,7 +102,7 @@ session_init (Gimp *gimp) if (scanner->value.v_symbol == GINT_TO_POINTER (SESSION_INFO)) { g_scanner_set_scope (scanner, SESSION_INFO); - token = session_info_deserialize (scanner, gimp); + token = gimp_session_info_deserialize (scanner, SESSION_INFO); if (token == G_TOKEN_RIGHT_PAREN) g_scanner_set_scope (scanner, 0); @@ -245,215 +218,3 @@ session_clear (Gimp *gimp) g_print ("TODO: implement session_clear()\n"); } - - -/* private functions */ - -static GTokenType -session_info_deserialize (GScanner *scanner, - Gimp *gimp) -{ - GimpDialogFactory *factory; - GimpSessionInfo *info = NULL; - GTokenType token; - gchar *factory_name; - gchar *entry_name; - gchar *string; - - token = G_TOKEN_STRING; - - if (! gimp_scanner_parse_string (scanner, &factory_name)) - goto error; - - factory = gimp_dialog_factory_from_name (factory_name); - g_free (factory_name); - - if (! factory) - goto error; - - if (! gimp_scanner_parse_string (scanner, &entry_name)) - goto error; - - info = g_new0 (GimpSessionInfo, 1); - - if (strcmp (entry_name, "dock")) - { - info->toplevel_entry = gimp_dialog_factory_find_entry (factory, - entry_name); - g_free (entry_name); - - if (! info->toplevel_entry) - goto error; - } - else - { - g_free (entry_name); - } - - token = G_TOKEN_LEFT_PAREN; - - while (g_scanner_peek_next_token (scanner) == token) - { - token = g_scanner_get_next_token (scanner); - - switch (token) - { - case G_TOKEN_LEFT_PAREN: - token = G_TOKEN_SYMBOL; - break; - - case G_TOKEN_SYMBOL: - switch (GPOINTER_TO_INT (scanner->value.v_symbol)) - { - case SESSION_INFO_POSITION: - token = G_TOKEN_INT; - if (! gimp_scanner_parse_int (scanner, &info->x)) - goto error; - if (! gimp_scanner_parse_int (scanner, &info->y)) - goto error; - break; - - case SESSION_INFO_SIZE: - token = G_TOKEN_INT; - if (! gimp_scanner_parse_int (scanner, &info->width)) - goto error; - if (! gimp_scanner_parse_int (scanner, &info->height)) - goto error; - break; - - case SESSION_INFO_OPEN: - info->open = TRUE; - break; - - case SESSION_INFO_AUX: - while ((token = - g_scanner_peek_next_token (scanner)) == G_TOKEN_STRING) - { - if (gimp_scanner_parse_string (scanner, &string)) - info->aux_info = g_list_append (info->aux_info, string); - else - break; - } - - if (token != G_TOKEN_RIGHT_PAREN) - token = G_TOKEN_STRING; - - break; - - case SESSION_INFO_DOCK: - if (info->toplevel_entry) - goto error; - - g_scanner_set_scope (scanner, SESSION_INFO_DOCK); - token = session_info_dock_deserialize (scanner, info); - - if (token == G_TOKEN_LEFT_PAREN) - g_scanner_set_scope (scanner, SESSION_INFO); - else - goto error; - - break; - - default: - break; - } - token = G_TOKEN_RIGHT_PAREN; - break; - - case G_TOKEN_RIGHT_PAREN: - token = G_TOKEN_LEFT_PAREN; - break; - - default: - break; - } - } - - if (token == G_TOKEN_LEFT_PAREN) - { - token = G_TOKEN_RIGHT_PAREN; - - if (g_scanner_peek_next_token (scanner) == token) - { - factory->session_infos = g_list_append (factory->session_infos, info); - } - - return token; - } - - error: - if (info) - { - GList *list; - - for (list = info->sub_dialogs; list; list = g_list_next (list)) - { - g_list_foreach (list->data, (GFunc) g_free, NULL); - g_list_free (list->data); - } - - g_list_free (info->sub_dialogs); - g_free (info); - } - - return token; -} - -static GTokenType -session_info_dock_deserialize (GScanner *scanner, - GimpSessionInfo *info) -{ - GList *list; - gchar *string; - GTokenType token; - - token = G_TOKEN_LEFT_PAREN; - - while (g_scanner_peek_next_token (scanner) == token) - { - token = g_scanner_get_next_token (scanner); - - switch (token) - { - case G_TOKEN_LEFT_PAREN: - token = G_TOKEN_SYMBOL; - break; - - case G_TOKEN_SYMBOL: - switch (GPOINTER_TO_INT (scanner->value.v_symbol)) - { - case SESSION_INFO_DOCK_BOOK: - list = NULL; - while ((token = - g_scanner_peek_next_token (scanner)) == G_TOKEN_STRING) - { - if (gimp_scanner_parse_string (scanner, &string)) - list = g_list_append (list, string); - else - break; - } - - if (list) - info->sub_dialogs = g_list_append (info->sub_dialogs, list); - - if (token != G_TOKEN_RIGHT_PAREN) - token = G_TOKEN_STRING; - - break; - - default: - return token; - } - break; - - case G_TOKEN_RIGHT_PAREN: - token = G_TOKEN_LEFT_PAREN; - break; - - default: - break; - } - } - - return token; -} diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am index 44b7289fd8..f8c697d688 100644 --- a/app/widgets/Makefile.am +++ b/app/widgets/Makefile.am @@ -148,6 +148,8 @@ libappwidgets_a_sources = \ gimppropwidgets.h \ gimpselectioneditor.c \ gimpselectioneditor.h \ + gimpsessioninfo.c \ + gimpsessioninfo.h \ gimpstrokeeditor.c \ gimpstrokeeditor.h \ gimptemplateeditor.c \ diff --git a/app/widgets/gimpdialogfactory.c b/app/widgets/gimpdialogfactory.c index 155032f963..d2d720c2b8 100644 --- a/app/widgets/gimpdialogfactory.c +++ b/app/widgets/gimpdialogfactory.c @@ -32,17 +32,13 @@ #include "core/gimpcontext.h" -#include "config/gimpconfigwriter.h" - -#include "gimpcontainerview.h" -#include "gimpcontainerview-utils.h" #include "gimpcursor.h" #include "gimpdialogfactory.h" #include "gimpdock.h" #include "gimpdockbook.h" #include "gimpdockable.h" -#include "gimpimagedock.h" #include "gimpmenufactory.h" +#include "gimpsessioninfo.h" /* #define DEBUG_FACTORY */ @@ -90,14 +86,6 @@ static void gimp_dialog_factories_restore_foreach (gconstpointer key, static void gimp_dialog_factories_clear_foreach (gconstpointer key, GimpDialogFactory *factory, gpointer data); -static void gimp_dialog_factory_get_window_info (GtkWidget *window, - GimpSessionInfo *info); -static void gimp_dialog_factory_set_window_geometry (GtkWidget *window, - GimpSessionInfo *info); -static void gimp_dialog_factory_get_aux_info (GtkWidget *dialog, - GimpSessionInfo *info); -static void gimp_dialog_factory_set_aux_info (GtkWidget *dialog, - GimpSessionInfo *info); static void gimp_dialog_factories_hide_foreach (gconstpointer key, GimpDialogFactory *factory, gpointer data); @@ -348,9 +336,7 @@ gimp_dialog_factory_find_entry (GimpDialogFactory *factory, entry = (GimpDialogFactoryEntry *) list->data; if (! strcmp (identifier, entry->identifier)) - { - return entry; - } + return entry; } return NULL; @@ -761,7 +747,7 @@ gimp_dialog_factory_add_dialog (GimpDialogFactory *factory, entry->identifier)); if (entry->session_managed) - gimp_dialog_factory_set_window_geometry (info->widget, info); + gimp_session_info_set_geometry (info); break; } @@ -820,7 +806,7 @@ gimp_dialog_factory_add_dialog (GimpDialogFactory *factory, G_GNUC_FUNCTION, info, info->widget)); - gimp_dialog_factory_set_window_geometry (info->widget, info); + gimp_session_info_set_geometry (info); break; } @@ -1144,7 +1130,7 @@ gimp_dialog_factory_dialog_configure (GtkWidget *dialog, D (g_print ("%s: updating session info for \"%s\"\n", G_GNUC_FUNCTION, entry->identifier)); - gimp_dialog_factory_get_window_info (dialog, session_info); + gimp_session_info_get_geometry (session_info); break; } @@ -1158,17 +1144,11 @@ gimp_dialog_factories_save_foreach (gconstpointer key, GimpDialogFactory *factory, GimpConfigWriter *writer) { - GEnumClass *enum_class; - GList *list; + GList *infos; - enum_class = g_type_class_ref (GIMP_TYPE_TAB_STYLE); - - for (list = factory->session_infos; list; list = g_list_next (list)) + for (infos = factory->session_infos; infos; infos = g_list_next (infos)) { - GimpSessionInfo *info; - const gchar *dialog_name; - - info = (GimpSessionInfo *) list->data; + GimpSessionInfo *info = infos->data; /* we keep session info entries for all toplevel dialogs created * by the factory but don't save them if they don't want to be @@ -1178,138 +1158,8 @@ gimp_dialog_factories_save_foreach (gconstpointer key, (info->toplevel_entry && ! info->toplevel_entry->session_managed)) continue; - if (info->widget) - gimp_dialog_factory_get_window_info (info->widget, info); - - if (info->toplevel_entry) - dialog_name = info->toplevel_entry->identifier; - else - dialog_name = "dock"; - - gimp_config_writer_open (writer, "session-info"); - gimp_config_writer_string (writer, GIMP_OBJECT (factory)->name); - gimp_config_writer_string (writer, dialog_name); - - gimp_config_writer_open (writer, "position"); - gimp_config_writer_printf (writer, "%d %d", info->x, info->y); - gimp_config_writer_close (writer); - - if (info->width > 0 && info->height > 0) - { - gimp_config_writer_open (writer, "size"); - gimp_config_writer_printf (writer, "%d %d", - info->width, info->height); - gimp_config_writer_close (writer); - } - - if (info->open) - { - gimp_config_writer_open (writer, "open-on-exit"); - gimp_config_writer_close (writer); - } - - /* save aux-info */ - if (info->widget) - { - gimp_dialog_factory_get_aux_info (info->widget, info); - - if (info->aux_info) - { - GList *aux; - - gimp_config_writer_open (writer, "aux-info"); - - for (aux = info->aux_info; aux; aux = g_list_next (aux)) - gimp_config_writer_string (writer, (gchar *) aux->data); - - gimp_config_writer_close (writer); - - g_list_foreach (info->aux_info, (GFunc) g_free, NULL); - g_list_free (info->aux_info); - info->aux_info = NULL; - } - } - - if (! info->toplevel_entry && info->widget) - { - GimpDock *dock; - GList *books; - - dock = GIMP_DOCK (info->widget); - - gimp_config_writer_open (writer, "dock"); - - for (books = dock->dockbooks; books; books = g_list_next (books)) - { - GimpDockbook *dockbook; - GList *children; - GList *pages; - - dockbook = (GimpDockbook *) books->data; - - gimp_config_writer_open (writer, "book"); - - children = gtk_container_get_children (GTK_CONTAINER (dockbook)); - - for (pages = children; pages; pages = g_list_next (pages)) - { - GimpDockable *dockable; - GimpDialogFactoryEntry *entry; - - dockable = (GimpDockable *) pages->data; - - entry = g_object_get_data (G_OBJECT (dockable), - "gimp-dialog-factory-entry"); - - if (entry) - { - GimpContainerView *view; - GEnumValue *enum_value; - gchar *tab_style = "icon"; - gint preview_size = -1; - - gimp_config_writer_linefeed (writer); - - enum_value = g_enum_get_value (enum_class, - dockable->tab_style); - - if (enum_value) - tab_style = enum_value->value_nick; - - view = gimp_container_view_get_by_dockable (dockable); - - if (view && view->preview_size >= GIMP_PREVIEW_SIZE_TINY) - preview_size = view->preview_size; - - if (preview_size > 0 && - preview_size != entry->preview_size) - { - gimp_config_writer_printf (writer, "\"%s@%s:%d\"", - entry->identifier, - tab_style, - preview_size); - } - else - { - gimp_config_writer_printf (writer, "\"%s@%s\"", - entry->identifier, - tab_style); - } - } - } - - g_list_free (children); - - gimp_config_writer_close (writer); /* book */ - } - - gimp_config_writer_close (writer); /* dock */ - } - - gimp_config_writer_close (writer); /* session-info */ + gimp_session_info_save (info, GIMP_OBJECT (factory)->name, writer); } - - g_type_class_unref (enum_class); } static void @@ -1317,151 +1167,14 @@ gimp_dialog_factories_restore_foreach (gconstpointer key, GimpDialogFactory *factory, gpointer data) { - GList *list; + GList *infos; - for (list = factory->session_infos; list; list = g_list_next (list)) + for (infos = factory->session_infos; infos; infos = g_list_next (infos)) { - GimpSessionInfo *info; + GimpSessionInfo *info = infos->data; - info = (GimpSessionInfo *) list->data; - - if (! info->open) - continue; - - info->open = FALSE; - - if (info->toplevel_entry) - { - GtkWidget *dialog; - - dialog = - gimp_dialog_factory_dialog_new (factory, - info->toplevel_entry->identifier, - info->toplevel_entry->preview_size); - - if (dialog && info->aux_info) - gimp_dialog_factory_set_aux_info (dialog, info); - } - else - { - GimpDock *dock; - GList *books; - GEnumClass *enum_class; - - dock = GIMP_DOCK (gimp_dialog_factory_dock_new (factory)); - - enum_class = g_type_class_ref (GIMP_TYPE_TAB_STYLE); - - if (dock && info->aux_info) - gimp_dialog_factory_set_aux_info (GTK_WIDGET (dock), info); - - for (books = info->sub_dialogs; books; books = g_list_next (books)) - { - GtkWidget *dockbook; - GList *pages; - - dockbook = gimp_dockbook_new (dock->dialog_factory->menu_factory); - - gimp_dock_add_book (dock, GIMP_DOCKBOOK (dockbook), -1); - - for (pages = books->data; pages; pages = g_list_next (pages)) - { - GtkWidget *dockable; - gchar *identifier; - gchar *substring; - gint preview_size = -1; - GimpTabStyle tab_style = GIMP_TAB_STYLE_PREVIEW; - - identifier = (gchar *) pages->data; - - if ((substring = strstr (identifier, "@"))) - { - gchar **split; - - *substring = '\0'; - substring++; - - split = g_strsplit (substring, ":", 16); - - if (split[0]) - { - if (split[1] || ! g_ascii_isdigit (split[0][0])) - { - GEnumValue *enum_value; - - enum_value = g_enum_get_value_by_nick (enum_class, - split[0]); - - if (enum_value) - tab_style = enum_value->value; - } - else - { - preview_size = atoi (split[0]); - } - } - - if (split[1]) - preview_size = atoi (split[1]); - - g_strfreev (split); - } - - if (preview_size < GIMP_PREVIEW_SIZE_TINY || - preview_size > GIMP_PREVIEW_SIZE_GIGANTIC) - preview_size = -1; - - /* use the new dock's dialog factory to create dockables - * because it may be different from the dialog factory - * the dock was created from. - */ - dockable = - gimp_dialog_factory_dockable_new (dock->dialog_factory, - dock, - identifier, - preview_size); - - if (! GIMP_DOCKABLE (dockable)->get_preview_func) - { - switch (tab_style) - { - case GIMP_TAB_STYLE_PREVIEW: - tab_style = GIMP_TAB_STYLE_ICON; - break; - case GIMP_TAB_STYLE_PREVIEW_NAME: - tab_style = GIMP_TAB_STYLE_ICON_BLURB; - break; - case GIMP_TAB_STYLE_PREVIEW_BLURB: - tab_style = GIMP_TAB_STYLE_ICON_BLURB; - break; - default: - break; - } - } - - GIMP_DOCKABLE (dockable)->tab_style = tab_style; - - if (dockable) - gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), - GIMP_DOCKABLE (dockable), -1); - - g_free (identifier); - } - - g_list_free (books->data); - } - - g_list_free (info->sub_dialogs); - info->sub_dialogs = NULL; - - gtk_widget_show (GTK_WIDGET (dock)); - - g_type_class_unref (enum_class); - } - - g_list_foreach (info->aux_info, (GFunc) g_free, NULL); - g_list_free (info->aux_info); - info->aux_info = NULL; + if (info->open) + gimp_session_info_restore (info, factory); } } @@ -1487,131 +1200,6 @@ gimp_dialog_factories_clear_foreach (gconstpointer key, } } -static void -gimp_dialog_factory_get_window_info (GtkWidget *window, - GimpSessionInfo *info) -{ - g_return_if_fail (GTK_IS_WIDGET (window)); - g_return_if_fail (GTK_WIDGET_TOPLEVEL (window)); - g_return_if_fail (info != NULL); - - if (window->window) - { - gdk_window_get_root_origin (window->window, &info->x, &info->y); - - if (! info->toplevel_entry || info->toplevel_entry->remember_size) - { - info->width = window->allocation.width; - info->height = window->allocation.height; - } - else - { - info->width = 0; - info->height = 0; - } - } - - if (! info->toplevel_entry || info->toplevel_entry->remember_if_open) - info->open = GTK_WIDGET_VISIBLE (window); - else - info->open = FALSE; -} - -static void -gimp_dialog_factory_set_window_geometry (GtkWidget *window, - GimpSessionInfo *info) -{ - static gint screen_width = 0; - static gint screen_height = 0; - - gchar geom[32]; - - g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (GTK_WIDGET_TOPLEVEL (window)); - g_return_if_fail (info != NULL); - - if (screen_width == 0 || screen_height == 0) - { - screen_width = gdk_screen_width (); - screen_height = gdk_screen_height (); - } - - info->x = CLAMP (info->x, 0, screen_width - 128); - info->y = CLAMP (info->y, 0, screen_height - 128); - - g_snprintf (geom, sizeof (geom), "+%d+%d", info->x, info->y); - - gtk_window_parse_geometry (GTK_WINDOW (window), geom); - - if (! info->toplevel_entry || info->toplevel_entry->remember_size) - { - if (info->width > 0 && info->height > 0) - gtk_window_set_default_size (GTK_WINDOW (window), - info->width, info->height); - } -} - -static void -gimp_dialog_factory_get_aux_info (GtkWidget *dialog, - GimpSessionInfo *info) -{ - /* FIXME: make the aux-info stuff generic */ - - if (GIMP_IS_IMAGE_DOCK (dialog)) - { - GimpImageDock *dock; - - dock = GIMP_IMAGE_DOCK (dialog); - - info->aux_info = g_list_append (info->aux_info, - dock->show_image_menu ? - g_strdup ("menu-shown") : - g_strdup ("menu-hidden")); - - info->aux_info = g_list_append (info->aux_info, - dock->auto_follow_active ? - g_strdup ("follow-active-image") : - g_strdup ("dont-follow-active-image")); - } -} - -static void -gimp_dialog_factory_set_aux_info (GtkWidget *dialog, - GimpSessionInfo *info) -{ - GList *aux; - - /* FIXME: make the aux-info stuff generic */ - - if (GIMP_IS_IMAGE_DOCK (dialog)) - { - gboolean menu_shown = TRUE; - gboolean auto_follow = TRUE; - - for (aux = info->aux_info; aux; aux = g_list_next (aux)) - { - gchar *str; - - str = (gchar *) aux->data; - - if (! strcmp (str, "menu-shown")) - menu_shown = TRUE; - else if (! strcmp (str, "menu-hidden")) - menu_shown = FALSE; - - else if (! strcmp (str, "follow-active-image")) - auto_follow = TRUE; - else if (! strcmp (str, "dont-follow-active-image")) - auto_follow = FALSE; - } - - gimp_image_dock_set_show_image_menu (GIMP_IMAGE_DOCK (dialog), - menu_shown); - gimp_image_dock_set_auto_follow_active (GIMP_IMAGE_DOCK (dialog), - auto_follow); - } -} - static void gimp_dialog_factories_hide_foreach (gconstpointer key, GimpDialogFactory *factory, diff --git a/app/widgets/gimpdialogfactory.h b/app/widgets/gimpdialogfactory.h index 4306117e6d..87e060359f 100644 --- a/app/widgets/gimpdialogfactory.h +++ b/app/widgets/gimpdialogfactory.h @@ -31,9 +31,6 @@ typedef GtkWidget * (* GimpDialogNewFunc) (GimpDialogFactory *factory, gint preview_size); -typedef struct _GimpDialogFactoryEntry GimpDialogFactoryEntry; -typedef struct _GimpSessionInfo GimpSessionInfo; - struct _GimpDialogFactoryEntry { gchar *identifier; @@ -45,27 +42,6 @@ struct _GimpDialogFactoryEntry gboolean remember_if_open; }; -struct _GimpSessionInfo -{ - gint x; - gint y; - gint width; - gint height; - - GtkWidget *widget; - - /* only valid while restoring and saving the session */ - gboolean open; - - /* GList of gchar* of optional additional dialog specific info */ - GList *aux_info; - - /* only one of these is valid */ - GimpDialogFactoryEntry *toplevel_entry; - GimpDialogFactoryEntry *dockable_entry; - GList *sub_dialogs; /* GList of GLists of entries */ -}; - #define GIMP_TYPE_DIALOG_FACTORY (gimp_dialog_factory_get_type ()) #define GIMP_DIALOG_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DIALOG_FACTORY, GimpDialogFactory)) diff --git a/app/widgets/gimpdock.c b/app/widgets/gimpdock.c index bb5209d0e6..7dc8a195c4 100644 --- a/app/widgets/gimpdock.c +++ b/app/widgets/gimpdock.c @@ -330,6 +330,27 @@ gimp_dock_setup (GimpDock *dock, GIMP_DOCK_GET_CLASS (dock)->setup (dock, template); } +void +gimp_dock_set_aux_info (GimpDock *dock, + GList *aux_info) +{ + g_return_if_fail (GIMP_IS_DOCK (dock)); + + if (GIMP_DOCK_GET_CLASS (dock)->set_aux_info) + GIMP_DOCK_GET_CLASS (dock)->set_aux_info (dock, aux_info); +} + +GList * +gimp_dock_get_aux_info (GimpDock *dock) +{ + g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL); + + if (GIMP_DOCK_GET_CLASS (dock)->get_aux_info) + return GIMP_DOCK_GET_CLASS (dock)->get_aux_info (dock); + + return NULL; +} + void gimp_dock_add (GimpDock *dock, GimpDockable *dockable, diff --git a/app/widgets/gimpdock.h b/app/widgets/gimpdock.h index 67aa1476b8..d6c3da9051 100644 --- a/app/widgets/gimpdock.h +++ b/app/widgets/gimpdock.h @@ -54,37 +54,44 @@ struct _GimpDockClass GtkWindowClass parent_class; /* virtual functions */ - void (* setup) (GimpDock *dock, - const GimpDock *template); + void (* setup) (GimpDock *dock, + const GimpDock *template); + void (* set_aux_info) (GimpDock *dock, + GList *aux_info); + GList * (* get_aux_info) (GimpDock *dock); /* signals */ - void (* book_added) (GimpDock *dock, - GimpDockbook *dockbook); - void (* book_removed) (GimpDock *dock, - GimpDockbook *dockbook); + void (* book_added) (GimpDock *dock, + GimpDockbook *dockbook); + void (* book_removed) (GimpDock *dock, + GimpDockbook *dockbook); }; -GType gimp_dock_get_type (void) G_GNUC_CONST; +GType gimp_dock_get_type (void) G_GNUC_CONST; -gboolean gimp_dock_construct (GimpDock *dock, - GimpDialogFactory *dialog_factory, - GimpContext *context); -void gimp_dock_setup (GimpDock *dock, - const GimpDock *template); +gboolean gimp_dock_construct (GimpDock *dock, + GimpDialogFactory *dialog_factory, + GimpContext *context); -void gimp_dock_add (GimpDock *dock, - GimpDockable *dockable, - gint book, - gint index); -void gimp_dock_remove (GimpDock *dock, - GimpDockable *dockable); +void gimp_dock_setup (GimpDock *dock, + const GimpDock *template); +void gimp_dock_set_aux_info (GimpDock *dock, + GList *aux_info); +GList * gimp_dock_get_aux_info (GimpDock *dock); -void gimp_dock_add_book (GimpDock *dock, - GimpDockbook *dockbook, - gint index); -void gimp_dock_remove_book (GimpDock *dock, - GimpDockbook *dockbook); +void gimp_dock_add (GimpDock *dock, + GimpDockable *dockable, + gint book, + gint index); +void gimp_dock_remove (GimpDock *dock, + GimpDockable *dockable); + +void gimp_dock_add_book (GimpDock *dock, + GimpDockbook *dockbook, + gint index); +void gimp_dock_remove_book (GimpDock *dock, + GimpDockbook *dockbook); #endif /* __GIMP_DOCK_H__ */ diff --git a/app/widgets/gimpdockable.c b/app/widgets/gimpdockable.c index 168251ce12..b82980b24c 100644 --- a/app/widgets/gimpdockable.c +++ b/app/widgets/gimpdockable.c @@ -70,6 +70,9 @@ static void gimp_dockable_forall (GtkContainer *container, static void gimp_dockable_get_title_area (GimpDockable *dockable, GdkRectangle *area); +static void gimp_dockable_real_set_aux_info (GimpDockable *dockable, + GList *aux_info); +static GList * gimp_dockable_real_get_aux_info (GimpDockable *dockable); static GtkWidget * gimp_dockable_real_get_tab_widget (GimpDockable *dockable, GimpContext *context, GimpTabStyle tab_style, @@ -151,6 +154,8 @@ gimp_dockable_class_init (GimpDockableClass *klass) container_class->forall = gimp_dockable_forall; + klass->get_aux_info = gimp_dockable_real_get_aux_info; + klass->set_aux_info = gimp_dockable_real_set_aux_info; klass->get_tab_widget = gimp_dockable_real_get_tab_widget; klass->set_context = gimp_dockable_real_set_context; klass->get_menu = gimp_dockable_real_get_menu; @@ -636,6 +641,23 @@ gimp_dockable_new (const gchar *name, return GTK_WIDGET (dockable); } +void +gimp_dockable_set_aux_info (GimpDockable *dockable, + GList *aux_info) +{ + g_return_if_fail (GIMP_IS_DOCKABLE (dockable)); + + GIMP_DOCKABLE_GET_CLASS (dockable)->set_aux_info (dockable, aux_info); +} + +GList * +gimp_dockable_get_aux_info (GimpDockable *dockable) +{ + g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL); + + return GIMP_DOCKABLE_GET_CLASS (dockable)->get_aux_info (dockable); +} + GtkWidget * gimp_dockable_get_tab_widget (GimpDockable *dockable, GimpContext *context, @@ -720,6 +742,28 @@ gimp_dockable_get_title_area (GimpDockable *dockable, area->x += 2 * dockable->close_button->allocation.width; } +static void +gimp_dockable_real_set_aux_info (GimpDockable *dockable, + GList *aux_info) +{ + GList *aux; + + for (aux = aux_info; aux; aux = g_list_next (aux)) + { + gchar *str = (gchar *) aux->data; + + g_print ("dockable %s aux_info: %s\n", dockable->name, str); + } +} + +static GList * +gimp_dockable_real_get_aux_info (GimpDockable *dockable) +{ + GList *aux = NULL; + + return aux; +} + static GtkWidget * gimp_dockable_real_get_tab_widget (GimpDockable *dockable, GimpContext *context, diff --git a/app/widgets/gimpdockable.h b/app/widgets/gimpdockable.h index 9e790feec6..ae92568d73 100644 --- a/app/widgets/gimpdockable.h +++ b/app/widgets/gimpdockable.h @@ -75,6 +75,10 @@ struct _GimpDockableClass { GtkBinClass parent_class; + void (* set_aux_info) (GimpDockable *dockable, + GList *aux_info); + GList * (* get_aux_info) (GimpDockable *dockable); + GtkWidget * (* get_tab_widget) (GimpDockable *dockable, GimpContext *context, GimpTabStyle tab_style, @@ -97,6 +101,10 @@ GtkWidget * gimp_dockable_new (const gchar *name, GimpDockableSetContextFunc set_context_func, GimpDockableGetMenuFunc get_menu_func); +void gimp_dockable_set_aux_info (GimpDockable *dockable, + GList *aux_info); +GList * gimp_dockable_get_aux_info (GimpDockable *dockable); + GtkWidget * gimp_dockable_get_tab_widget (GimpDockable *dockable, GimpContext *context, GimpTabStyle tab_style, diff --git a/app/widgets/gimpsessioninfo.c b/app/widgets/gimpsessioninfo.c new file mode 100644 index 0000000000..70569e7744 --- /dev/null +++ b/app/widgets/gimpsessioninfo.c @@ -0,0 +1,899 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpsessioninfo.c + * Copyright (C) 2001-2003 Michael Natterer + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include + +#include "widgets-types.h" + +#include "config/gimpconfigwriter.h" +#include "config/gimpscanner.h" + +#include "gimpcontainerview.h" +#include "gimpcontainerview-utils.h" +#include "gimpdialogfactory.h" +#include "gimpdock.h" +#include "gimpdockable.h" +#include "gimpdockbook.h" +#include "gimpsessioninfo.h" + + +enum +{ + SESSION_INFO_POSITION, + SESSION_INFO_SIZE, + SESSION_INFO_OPEN, + SESSION_INFO_AUX, + + SESSION_INFO_DOCK, + + SESSION_INFO_BOOK, + SESSION_INFO_BOOK_POSITION, + SESSION_INFO_DOCKABLE, + + SESSION_INFO_DOCKABLE_TAB_STYLE, + SESSION_INFO_DOCKABLE_PREVIEW_SIZE, + SESSION_INFO_DOCKABLE_AUX_INFO +}; + + +/* local function prototypes */ + +static GTokenType session_info_dock_deserialize (GScanner *scanner, + GimpSessionInfo *info); +static GTokenType session_info_book_deserialize (GScanner *scanner, + GimpSessionInfo *info); +static GTokenType session_info_dockable_deserialize (GScanner *scanner, + GimpSessionInfoBook *book); +static void session_info_set_aux_info (GtkWidget *dialog, + GList *aux_info); +static GList * session_info_get_aux_info (GtkWidget *dialog); + + +/* public functions */ + +void +gimp_session_info_free (GimpSessionInfo *info) +{ + g_return_if_fail (info != NULL); + + if (info->aux_info) + { + g_list_foreach (info->aux_info, (GFunc) g_free, NULL); + g_list_free (info->aux_info); + } + + if (info->books) + { + g_list_foreach (info->books, (GFunc) gimp_session_info_book_free, NULL); + g_list_free (info->books); + } + + g_free (info); +} + +void +gimp_session_info_book_free (GimpSessionInfoBook *book) +{ + g_return_if_fail (book != NULL); + + if (book->dockables) + { + g_list_foreach (book->dockables, (GFunc) gimp_session_info_dockable_free, + NULL); + g_list_free (book->dockables); + } + + g_free (book); +} + +void +gimp_session_info_dockable_free (GimpSessionInfoDockable *dockable) +{ + g_return_if_fail (dockable != NULL); + + if (dockable->identifier) + g_free (dockable->identifier); + + if (dockable->aux_info) + { + g_list_foreach (dockable->aux_info, (GFunc) g_free, NULL); + g_list_free (dockable->aux_info); + } + + g_free (dockable); +} + +void +gimp_session_info_save (GimpSessionInfo *info, + const gchar *factory_name, + GimpConfigWriter *writer) +{ + GEnumClass *enum_class; + const gchar *dialog_name; + + g_return_if_fail (info != NULL); + g_return_if_fail (factory_name != NULL); + g_return_if_fail (writer != NULL); + + enum_class = g_type_class_ref (GIMP_TYPE_TAB_STYLE); + + if (info->widget) + gimp_session_info_get_geometry (info); + + if (info->toplevel_entry) + dialog_name = info->toplevel_entry->identifier; + else + dialog_name = "dock"; + + gimp_config_writer_open (writer, "session-info"); + gimp_config_writer_string (writer, factory_name); + gimp_config_writer_string (writer, dialog_name); + + gimp_config_writer_open (writer, "position"); + gimp_config_writer_printf (writer, "%d %d", info->x, info->y); + gimp_config_writer_close (writer); + + if (info->width > 0 && info->height > 0) + { + gimp_config_writer_open (writer, "size"); + gimp_config_writer_printf (writer, "%d %d", info->width, info->height); + gimp_config_writer_close (writer); + } + + if (info->open) + { + gimp_config_writer_open (writer, "open-on-exit"); + gimp_config_writer_close (writer); + } + + if (info->widget) + { + info->aux_info = session_info_get_aux_info (info->widget); + + if (info->aux_info) + { + GList *aux; + + gimp_config_writer_open (writer, "aux-info"); + + for (aux = info->aux_info; aux; aux = g_list_next (aux)) + gimp_config_writer_string (writer, (gchar *) aux->data); + + gimp_config_writer_close (writer); + + g_list_foreach (info->aux_info, (GFunc) g_free, NULL); + g_list_free (info->aux_info); + info->aux_info = NULL; + } + } + + if (! info->toplevel_entry && info->widget) + { + GimpDock *dock; + GList *books; + + dock = GIMP_DOCK (info->widget); + + gimp_config_writer_open (writer, "dock"); + + for (books = dock->dockbooks; books; books = g_list_next (books)) + { + GimpDockbook *dockbook = books->data; + GList *children; + GList *pages; + + gimp_config_writer_open (writer, "book"); + + if (GTK_IS_VPANED (GTK_WIDGET (dockbook)->parent)) + { + GtkPaned *paned = GTK_PANED (GTK_WIDGET (dockbook)->parent); + + if (GTK_WIDGET (dockbook) == paned->child2) + { + gimp_config_writer_open (writer, "position"); + gimp_config_writer_printf (writer, "%d", + gtk_paned_get_position (paned)); + gimp_config_writer_close (writer); + } + } + + children = gtk_container_get_children (GTK_CONTAINER (dockbook)); + + for (pages = children; pages; pages = g_list_next (pages)) + { + GimpDockable *dockable = pages->data; + GimpDialogFactoryEntry *entry; + + entry = g_object_get_data (G_OBJECT (dockable), + "gimp-dialog-factory-entry"); + + if (entry) + { + GimpContainerView *view; + GEnumValue *enum_value; + gchar *tab_style = "icon"; + gint preview_size = -1; + GList *aux_info; + + gimp_config_writer_open (writer, "dockable"); + gimp_config_writer_string (writer, entry->identifier); + + enum_value = g_enum_get_value (enum_class, + dockable->tab_style); + + if (enum_value) + tab_style = enum_value->value_nick; + + gimp_config_writer_open (writer, "tab-style"); + gimp_config_writer_print (writer, tab_style, -1); + gimp_config_writer_close (writer); + + view = gimp_container_view_get_by_dockable (dockable); + + if (view && view->preview_size >= GIMP_PREVIEW_SIZE_TINY) + preview_size = view->preview_size; + + if (preview_size > 0 && + preview_size != entry->preview_size) + { + gimp_config_writer_open (writer, "preview-size"); + gimp_config_writer_printf (writer, "%d", preview_size); + gimp_config_writer_close (writer); + } + + aux_info = session_info_get_aux_info (GTK_WIDGET (dockable)); + + if (aux_info) + { + GList *aux; + + gimp_config_writer_open (writer, "aux-info"); + + for (aux = aux_info; aux; aux = g_list_next (aux)) + gimp_config_writer_string (writer, (gchar *) aux->data); + + gimp_config_writer_close (writer); + + g_list_foreach (aux_info, (GFunc) g_free, NULL); + g_list_free (aux_info); + } + + gimp_config_writer_close (writer); /* dockable */ + } + } + + g_list_free (children); + + gimp_config_writer_close (writer); /* book */ + } + + gimp_config_writer_close (writer); /* dock */ + } + + gimp_config_writer_close (writer); /* session-info */ + + g_type_class_unref (enum_class); +} + +GTokenType +gimp_session_info_deserialize (GScanner *scanner, + gint scope) +{ + GimpDialogFactory *factory; + GimpSessionInfo *info = NULL; + GTokenType token; + gchar *factory_name; + gchar *entry_name; + gchar *string; + + g_return_val_if_fail (scanner != NULL, G_TOKEN_LEFT_PAREN); + + g_scanner_scope_add_symbol (scanner, scope, "position", + GINT_TO_POINTER (SESSION_INFO_POSITION)); + g_scanner_scope_add_symbol (scanner, scope, "size", + GINT_TO_POINTER (SESSION_INFO_SIZE)); + g_scanner_scope_add_symbol (scanner, scope, "open-on-exit", + GINT_TO_POINTER (SESSION_INFO_OPEN)); + g_scanner_scope_add_symbol (scanner, scope, "aux-info", + GINT_TO_POINTER (SESSION_INFO_AUX)); + g_scanner_scope_add_symbol (scanner, scope, "dock", + GINT_TO_POINTER (SESSION_INFO_DOCK)); + + g_scanner_scope_add_symbol (scanner, SESSION_INFO_DOCK, "book", + GINT_TO_POINTER (SESSION_INFO_BOOK)); + + g_scanner_scope_add_symbol (scanner, SESSION_INFO_BOOK, "position", + GINT_TO_POINTER (SESSION_INFO_BOOK_POSITION)); + g_scanner_scope_add_symbol (scanner, SESSION_INFO_BOOK, "dockable", + GINT_TO_POINTER (SESSION_INFO_DOCKABLE)); + + g_scanner_scope_add_symbol (scanner, SESSION_INFO_DOCKABLE, "tab-style", + GINT_TO_POINTER (SESSION_INFO_DOCKABLE_TAB_STYLE)); + g_scanner_scope_add_symbol (scanner, SESSION_INFO_DOCKABLE, "preview-size", + GINT_TO_POINTER (SESSION_INFO_DOCKABLE_PREVIEW_SIZE)); + g_scanner_scope_add_symbol (scanner, SESSION_INFO_DOCKABLE, "aux-info", + GINT_TO_POINTER (SESSION_INFO_DOCKABLE_AUX_INFO)); + + token = G_TOKEN_STRING; + + if (! gimp_scanner_parse_string (scanner, &factory_name)) + goto error; + + factory = gimp_dialog_factory_from_name (factory_name); + g_free (factory_name); + + if (! factory) + goto error; + + if (! gimp_scanner_parse_string (scanner, &entry_name)) + goto error; + + info = g_new0 (GimpSessionInfo, 1); + + if (strcmp (entry_name, "dock")) + { + info->toplevel_entry = gimp_dialog_factory_find_entry (factory, + entry_name); + g_free (entry_name); + + if (! info->toplevel_entry) + goto error; + } + else + { + g_free (entry_name); + } + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + switch (GPOINTER_TO_INT (scanner->value.v_symbol)) + { + case SESSION_INFO_POSITION: + token = G_TOKEN_INT; + if (! gimp_scanner_parse_int (scanner, &info->x)) + goto error; + if (! gimp_scanner_parse_int (scanner, &info->y)) + goto error; + break; + + case SESSION_INFO_SIZE: + token = G_TOKEN_INT; + if (! gimp_scanner_parse_int (scanner, &info->width)) + goto error; + if (! gimp_scanner_parse_int (scanner, &info->height)) + goto error; + break; + + case SESSION_INFO_OPEN: + info->open = TRUE; + break; + + case SESSION_INFO_AUX: + while ((token = + g_scanner_peek_next_token (scanner)) == G_TOKEN_STRING) + { + if (gimp_scanner_parse_string (scanner, &string)) + info->aux_info = g_list_append (info->aux_info, string); + else + break; + } + + if (token != G_TOKEN_RIGHT_PAREN) + token = G_TOKEN_STRING; + + break; + + case SESSION_INFO_DOCK: + if (info->toplevel_entry) + goto error; + + g_scanner_set_scope (scanner, SESSION_INFO_DOCK); + token = session_info_dock_deserialize (scanner, info); + + if (token == G_TOKEN_LEFT_PAREN) + g_scanner_set_scope (scanner, scope); + else + goto error; + + break; + + default: + break; + } + token = G_TOKEN_RIGHT_PAREN; + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_LEFT_PAREN; + break; + + default: + break; + } + } + + if (token == G_TOKEN_LEFT_PAREN) + { + token = G_TOKEN_RIGHT_PAREN; + + if (g_scanner_peek_next_token (scanner) == token) + factory->session_infos = g_list_append (factory->session_infos, info); + } + else + { + error: + gimp_session_info_free (info); + } + + g_scanner_scope_remove_symbol (scanner, scope, "position"); + g_scanner_scope_remove_symbol (scanner, scope, "size"); + g_scanner_scope_remove_symbol (scanner, scope, "open-on-exit"); + g_scanner_scope_remove_symbol (scanner, scope, "aux-info"); + g_scanner_scope_remove_symbol (scanner, scope, "dock"); + + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_DOCK, "book"); + + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_BOOK, "position"); + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_BOOK, "dockable"); + + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_DOCKABLE, "tab-style"); + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_DOCKABLE, "preview-size"); + g_scanner_scope_remove_symbol (scanner, SESSION_INFO_DOCKABLE, "aux-info"); + + return token; +} + +void +gimp_session_info_restore (GimpSessionInfo *info, + GimpDialogFactory *factory) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (GIMP_IS_DIALOG_FACTORY (factory)); + + info->open = FALSE; + + if (info->toplevel_entry) + { + GtkWidget *dialog; + + dialog = + gimp_dialog_factory_dialog_new (factory, + info->toplevel_entry->identifier, + info->toplevel_entry->preview_size); + + if (dialog && info->aux_info) + session_info_set_aux_info (dialog, info->aux_info); + } + else + { + GimpDock *dock; + GList *books; + + dock = GIMP_DOCK (gimp_dialog_factory_dock_new (factory)); + + if (dock && info->aux_info) + session_info_set_aux_info (GTK_WIDGET (dock), info->aux_info); + + for (books = info->books; books; books = g_list_next (books)) + { + GimpSessionInfoBook *book_info = books->data; + GtkWidget *dockbook; + GList *pages; + + dockbook = gimp_dockbook_new (dock->dialog_factory->menu_factory); + + gimp_dock_add_book (dock, GIMP_DOCKBOOK (dockbook), -1); + + book_info->widget = dockbook; + + for (pages = book_info->dockables; pages; pages = g_list_next (pages)) + { + GimpSessionInfoDockable *dockable_info = pages->data; + GtkWidget *dockable; + + if (dockable_info->preview_size < GIMP_PREVIEW_SIZE_TINY || + dockable_info->preview_size > GIMP_PREVIEW_SIZE_GIGANTIC) + dockable_info->preview_size = -1; + + /* use the new dock's dialog factory to create dockables + * because it may be different from the dialog factory + * the dock was created from. + */ + dockable = + gimp_dialog_factory_dockable_new (dock->dialog_factory, + dock, + dockable_info->identifier, + dockable_info->preview_size); + + if (! dockable) + continue; + + if (! GIMP_DOCKABLE (dockable)->get_preview_func) + { + switch (dockable_info->tab_style) + { + case GIMP_TAB_STYLE_PREVIEW: + dockable_info->tab_style = GIMP_TAB_STYLE_ICON; + break; + case GIMP_TAB_STYLE_PREVIEW_NAME: + dockable_info->tab_style = GIMP_TAB_STYLE_ICON_BLURB; + break; + case GIMP_TAB_STYLE_PREVIEW_BLURB: + dockable_info->tab_style = GIMP_TAB_STYLE_ICON_BLURB; + break; + default: + break; + } + } + + GIMP_DOCKABLE (dockable)->tab_style = dockable_info->tab_style; + + if (dockable_info->aux_info) + session_info_set_aux_info (dockable, dockable_info->aux_info); + + gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), + GIMP_DOCKABLE (dockable), -1); + } + } + + for (books = info->books; books; books = g_list_next (books)) + { + GimpSessionInfoBook *book_info = books->data; + GtkWidget *dockbook = book_info->widget; + + if (GTK_IS_VPANED (dockbook->parent)) + { + GtkPaned *paned = GTK_PANED (dockbook->parent); + + if (dockbook == paned->child2) + gtk_paned_set_position (paned, book_info->position); + } + } + + g_list_foreach (info->books, (GFunc) gimp_session_info_book_free, NULL); + g_list_free (info->books); + info->books = NULL; + + gtk_widget_show (GTK_WIDGET (dock)); + } + + g_list_foreach (info->aux_info, (GFunc) g_free, NULL); + g_list_free (info->aux_info); + info->aux_info = NULL; +} + +void +gimp_session_info_set_geometry (GimpSessionInfo *info) +{ + GdkScreen *screen; + gint screen_width; + gint screen_height; + gchar geom[32]; + + g_return_if_fail (info != NULL); + g_return_if_fail (GTK_IS_WINDOW (info->widget)); + + screen = gtk_widget_get_screen (info->widget); + + screen_width = gdk_screen_get_width (screen); + screen_height = gdk_screen_get_height (screen); + + info->x = CLAMP (info->x, 0, screen_width - 128); + info->y = CLAMP (info->y, 0, screen_height - 128); + + g_snprintf (geom, sizeof (geom), "+%d+%d", info->x, info->y); + + gtk_window_parse_geometry (GTK_WINDOW (info->widget), geom); + + if (! info->toplevel_entry || info->toplevel_entry->remember_size) + { + if (info->width > 0 && info->height > 0) + gtk_window_set_default_size (GTK_WINDOW (info->widget), + info->width, info->height); + } +} + +void +gimp_session_info_get_geometry (GimpSessionInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (GTK_IS_WINDOW (info->widget)); + + if (info->widget->window) + { + gdk_window_get_root_origin (info->widget->window, &info->x, &info->y); + + if (! info->toplevel_entry || info->toplevel_entry->remember_size) + { + info->width = info->widget->allocation.width; + info->height = info->widget->allocation.height; + } + else + { + info->width = 0; + info->height = 0; + } + } + + if (! info->toplevel_entry || info->toplevel_entry->remember_if_open) + info->open = GTK_WIDGET_VISIBLE (info->widget); + else + info->open = FALSE; +} + + +/* private functions */ + +static GTokenType +session_info_dock_deserialize (GScanner *scanner, + GimpSessionInfo *info) +{ + GTokenType token; + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + switch (GPOINTER_TO_INT (scanner->value.v_symbol)) + { + case SESSION_INFO_BOOK: + g_scanner_set_scope (scanner, SESSION_INFO_BOOK); + token = session_info_book_deserialize (scanner, info); + + if (token == G_TOKEN_LEFT_PAREN) + g_scanner_set_scope (scanner, SESSION_INFO_DOCK); + else + return token; + + break; + + default: + return token; + } + token = G_TOKEN_RIGHT_PAREN; + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_LEFT_PAREN; + break; + + default: + break; + } + } + + return token; +} + +static GTokenType +session_info_book_deserialize (GScanner *scanner, + GimpSessionInfo *info) +{ + GimpSessionInfoBook *book; + GTokenType token; + + book = g_new0 (GimpSessionInfoBook, 1); + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + switch (GPOINTER_TO_INT (scanner->value.v_symbol)) + { + case SESSION_INFO_BOOK_POSITION: + token = G_TOKEN_INT; + if (! gimp_scanner_parse_int (scanner, &book->position)) + goto error; + break; + + case SESSION_INFO_DOCKABLE: + g_scanner_set_scope (scanner, SESSION_INFO_DOCKABLE); + token = session_info_dockable_deserialize (scanner, book); + + if (token == G_TOKEN_LEFT_PAREN) + g_scanner_set_scope (scanner, SESSION_INFO_BOOK); + else + goto error; + + break; + + default: + goto error; + } + token = G_TOKEN_RIGHT_PAREN; + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_LEFT_PAREN; + break; + + default: + break; + } + } + + info->books = g_list_append (info->books, book); + + return token; + + error: + gimp_session_info_book_free (book); + + return token; +} + +static GTokenType +session_info_dockable_deserialize (GScanner *scanner, + GimpSessionInfoBook *book) +{ + GimpSessionInfoDockable *dockable; + gchar *string; + GEnumClass *enum_class; + GEnumValue *enum_value; + GTokenType token; + + dockable = g_new0 (GimpSessionInfoDockable, 1); + + enum_class = g_type_class_ref (GIMP_TYPE_TAB_STYLE); + + token = G_TOKEN_STRING; + if (! gimp_scanner_parse_string (scanner, &dockable->identifier)) + goto error; + + token = G_TOKEN_LEFT_PAREN; + + while (g_scanner_peek_next_token (scanner) == token) + { + token = g_scanner_get_next_token (scanner); + + switch (token) + { + case G_TOKEN_LEFT_PAREN: + token = G_TOKEN_SYMBOL; + break; + + case G_TOKEN_SYMBOL: + switch (GPOINTER_TO_INT (scanner->value.v_symbol)) + { + case SESSION_INFO_DOCKABLE_TAB_STYLE: + token = G_TOKEN_IDENTIFIER; + if (g_scanner_peek_next_token (scanner) != token) + goto error; + + g_scanner_get_next_token (scanner); + + enum_value = g_enum_get_value_by_nick (enum_class, + scanner->value.v_identifier); + + if (! enum_value) + enum_value = g_enum_get_value_by_name (enum_class, + scanner->value.v_identifier); + + if (enum_value) + dockable->tab_style = enum_value->value; + break; + + case SESSION_INFO_DOCKABLE_PREVIEW_SIZE: + token = G_TOKEN_INT; + if (! gimp_scanner_parse_int (scanner, &dockable->preview_size)) + goto error; + break; + + case SESSION_INFO_DOCKABLE_AUX_INFO: + while ((token = + g_scanner_peek_next_token (scanner)) == G_TOKEN_STRING) + { + if (gimp_scanner_parse_string (scanner, &string)) + dockable->aux_info = g_list_append (dockable->aux_info, + string); + else + goto error; + } + + if (token != G_TOKEN_RIGHT_PAREN) + token = G_TOKEN_STRING; + + break; + + default: + goto error; + } + token = G_TOKEN_RIGHT_PAREN; + break; + + case G_TOKEN_RIGHT_PAREN: + token = G_TOKEN_LEFT_PAREN; + break; + + default: + break; + } + } + + book->dockables = g_list_append (book->dockables, dockable); + g_type_class_unref (enum_class); + + return token; + + error: + gimp_session_info_dockable_free (dockable); + g_type_class_unref (enum_class); + + return token; +} + +static void +session_info_set_aux_info (GtkWidget *dialog, + GList *aux_info) +{ + /* FIXME: make the aux-info stuff generic */ + + if (GIMP_IS_DOCK (dialog)) + gimp_dock_set_aux_info (GIMP_DOCK (dialog), aux_info); + else if (GIMP_IS_DOCKABLE (dialog)) + gimp_dockable_set_aux_info (GIMP_DOCKABLE (dialog), aux_info); +} + +static GList * +session_info_get_aux_info (GtkWidget *dialog) +{ + /* FIXME: make the aux-info stuff generic */ + + if (GIMP_IS_DOCK (dialog)) + return gimp_dock_get_aux_info (GIMP_DOCK (dialog)); + else if (GIMP_IS_DOCKABLE (dialog)) + return gimp_dockable_get_aux_info (GIMP_DOCKABLE (dialog)); + + return NULL; +} diff --git a/app/widgets/gimpsessioninfo.h b/app/widgets/gimpsessioninfo.h new file mode 100644 index 0000000000..10dac11beb --- /dev/null +++ b/app/widgets/gimpsessioninfo.h @@ -0,0 +1,82 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpsessioninfo.h + * Copyright (C) 2001-2003 Michael Natterer + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GIMP_SESSION_INFO_H__ +#define __GIMP_SESSION_INFO_H__ + + +struct _GimpSessionInfo +{ + gint x; + gint y; + gint width; + gint height; + + GtkWidget *widget; + + /* only valid while restoring and saving the session */ + gboolean open; + + /* GList of gchar* of optional additional dialog specific info */ + GList *aux_info; + + /* only one of these is valid */ + GimpDialogFactoryEntry *toplevel_entry; + GimpDialogFactoryEntry *dockable_entry; + GList *books; /* GList of GimpSessionInfoBook */ +}; + +struct _GimpSessionInfoBook +{ + gint position; + GList *dockables; /* GList of GimpSessionInfoDockable */ + + GtkWidget *widget; /* only used while restoring the session */ +}; + +struct _GimpSessionInfoDockable +{ + gchar *identifier; + GimpTabStyle tab_style; + gint preview_size; + + /* GList of gchar* of optional additional dockable specific info */ + GList *aux_info; +}; + + +void gimp_session_info_free (GimpSessionInfo *info); +void gimp_session_info_book_free (GimpSessionInfoBook *book); +void gimp_session_info_dockable_free (GimpSessionInfoDockable *dockable); + +void gimp_session_info_save (GimpSessionInfo *info, + const gchar *factory_name, + GimpConfigWriter *writer); +GTokenType gimp_session_info_deserialize (GScanner *scanner, + gint old_scope); +void gimp_session_info_restore (GimpSessionInfo *info, + GimpDialogFactory *factory); + +void gimp_session_info_set_geometry (GimpSessionInfo *info); +void gimp_session_info_get_geometry (GimpSessionInfo *info); + + +#endif /* __GIMP_SESSION_INFO_H__ */ diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index 1410a8d40e..2444bd61d3 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -115,6 +115,10 @@ typedef struct _GimpTextEditor GimpTextEditor; /* structs */ typedef struct _GimpItemFactoryEntry GimpItemFactoryEntry; +typedef struct _GimpDialogFactoryEntry GimpDialogFactoryEntry; +typedef struct _GimpSessionInfo GimpSessionInfo; +typedef struct _GimpSessionInfoBook GimpSessionInfoBook; +typedef struct _GimpSessionInfoDockable GimpSessionInfoDockable; /* function types */ diff --git a/etc/sessionrc b/etc/sessionrc index b2321ec7a8..217a781dfa 100644 --- a/etc/sessionrc +++ b/etc/sessionrc @@ -11,7 +11,8 @@ (open-on-exit) (dock (book - "gimp-tool-options@preview"))) + (dockable "gimp-tool-options" + (tab-style preview))))) (session-info "dock" "dock" (position 300 48) (size 240 660) @@ -19,14 +20,24 @@ (aux-info "menu-shown" "follow-active-image") (dock (book - "gimp-layer-list@icon" - "gimp-channel-list@icon" - "gimp-vectors-list@icon" - "gimp-undo-history@icon") + (dockable "gimp-layer-list" + (tab-style icon) + (preview-size 32)) + (dockable "gimp-channel-list" + (tab-style icon) + (preview-size 32)) + (dockable "gimp-vectors-list" + (tab-style icon) + (preview-size 32)) + (dockable "gimp-undo-history" + (tab-style icon))) (book - "gimp-brush-grid@preview" - "gimp-pattern-grid@preview" - "gimp-gradient-list@preview" - "gimp-font-list@preview"))) + (position 370) + (dockable "gimp-brush-grid" + (tab-style preview)) + (dockable "gimp-pattern-grid" + (tab-style preview)) + (dockable "gimp-gradient-list" + (tab-style preview))))) # end of sessionrc