Cleaned up session management and changed the format of sessionrc in a way

2003-10-10  Michael Natterer  <mitch@gimp.org>

	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.
This commit is contained in:
Michael Natterer 2003-10-10 15:59:12 +00:00 committed by Michael Natterer
parent c87b6cb423
commit 87480880c3
16 changed files with 1167 additions and 727 deletions

View file

@ -1,3 +1,37 @@
2003-10-10 Michael Natterer <mitch@gimp.org>
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 <sven@gimp.org>
* plug-ins/script-fu/scripts/burn-in-anim.scm: repaired this script

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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;
}

View file

@ -148,6 +148,8 @@ libappwidgets_a_sources = \
gimppropwidgets.h \
gimpselectioneditor.c \
gimpselectioneditor.h \
gimpsessioninfo.c \
gimpsessioninfo.h \
gimpstrokeeditor.c \
gimpstrokeeditor.h \
gimptemplateeditor.c \

View file

@ -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,

View file

@ -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))

View file

@ -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,

View file

@ -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__ */

View file

@ -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,

View file

@ -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,

View file

@ -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 <mitch@gimp.org>
*
* 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 <string.h>
#include <gtk/gtk.h>
#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;
}

View file

@ -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 <mitch@gimp.org>
*
* 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__ */

View file

@ -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 */

View file

@ -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