app/widgets/gimpdockable.[ch] added a "locked" propery to GimpDockable. A

2008-05-19  Sven Neumann  <sven@gimp.org>

	* app/widgets/gimpdockable.[ch]
	* app/widgets/gimpdockbook.[ch]: added a "locked" propery to
	GimpDockable. A locked dockable cannot be moved by drag-n-drop.
	Allows users to protect their dockables from accidental changes,
	mainly when working with a tablet.

	* app/widgets/gimpsessioninfo-dockable.[ch]: store the "locked"
	property in the session info.

	* app/actions/dockable-actions.c
	* app/actions/dockable-commands.[ch]: added an action for 
toggling
	the "locked" state.

	* app/widgets/gimphelp-ids.h: new help-id "gimp-dock-tab-lock".

	* menus/dockable-menu.xml.in: show the new menu item.

	* app/actions/plug-in-actions.c: formatting.


svn path=/trunk/; revision=25715
This commit is contained in:
Sven Neumann 2008-05-19 21:11:03 +00:00 committed by Sven Neumann
parent 62719d6703
commit 33b5a890cc
13 changed files with 300 additions and 81 deletions

View File

@ -1,3 +1,24 @@
2008-05-19 Sven Neumann <sven@gimp.org>
* app/widgets/gimpdockable.[ch]
* app/widgets/gimpdockbook.[ch]: added a "locked" propery to
GimpDockable. A locked dockable cannot be moved by drag-n-drop.
Allows users to protect their dockables from accidental changes,
mainly when working with a tablet.
* app/widgets/gimpsessioninfo-dockable.[ch]: store the "locked"
property in the session info.
* app/actions/dockable-actions.c
* app/actions/dockable-commands.[ch]: added an action for toggling
the "locked" state.
* app/widgets/gimphelp-ids.h: new help-id "gimp-dock-tab-lock".
* menus/dockable-menu.xml.in: show the new menu item.
* app/actions/plug-in-actions.c: formatting.
2008-05-19 Michael Natterer <mitch@gimp.org> 2008-05-19 Michael Natterer <mitch@gimp.org>
Unabstract image map tool settings load/save a bit before it's Unabstract image map tool settings load/save a bit before it's

View File

@ -104,6 +104,12 @@ static const GimpRadioActionEntry dockable_tab_style_actions[] =
static const GimpToggleActionEntry dockable_toggle_actions[] = static const GimpToggleActionEntry dockable_toggle_actions[] =
{ {
{ "dockable-lock-tab", NULL,
N_("Loc_k Tab to Dock"), NULL, NULL,
G_CALLBACK (dockable_lock_tab_cmd_callback),
FALSE,
GIMP_HELP_DOCK_TAB_LOCK },
{ "dockable-show-button-bar", NULL, { "dockable-show-button-bar", NULL,
N_("Show _Button Bar"), NULL, NULL, N_("Show _Button Bar"), NULL, NULL,
G_CALLBACK (dockable_show_button_bar_cmd_callback), G_CALLBACK (dockable_show_button_bar_cmd_callback),
@ -175,6 +181,7 @@ dockable_actions_update (GimpActionGroup *group,
GimpViewType view_type = -1; GimpViewType view_type = -1;
gboolean list_view_available = FALSE; gboolean list_view_available = FALSE;
gboolean grid_view_available = FALSE; gboolean grid_view_available = FALSE;
gboolean locked = FALSE;
GimpViewSize view_size = -1; GimpViewSize view_size = -1;
GimpTabStyle tab_style = -1; GimpTabStyle tab_style = -1;
gint n_pages = 0; gint n_pages = 0;
@ -250,7 +257,13 @@ dockable_actions_update (GimpActionGroup *group,
#define SET_SENSITIVE(action,sensitive) \ #define SET_SENSITIVE(action,sensitive) \
gimp_action_group_set_action_sensitive (group, action, (sensitive) != 0) gimp_action_group_set_action_sensitive (group, action, (sensitive) != 0)
SET_SENSITIVE ("dockable-detach-tab", n_pages > 1 || n_books > 1);
locked = gimp_dockable_is_locked (dockable);
SET_SENSITIVE ("dockable-detach-tab", (! locked &&
(n_pages > 1 || n_books > 1)));
SET_ACTIVE ("dockable-lock-tab", locked);
SET_VISIBLE ("dockable-preview-size-menu", view_size != -1); SET_VISIBLE ("dockable-preview-size-menu", view_size != -1);

View File

@ -40,6 +40,9 @@
#include "dockable-commands.h" #include "dockable-commands.h"
static GimpDockable * dockable_get_current (GimpDockbook *dockbook);
/* public functions */ /* public functions */
void void
@ -83,13 +86,7 @@ dockable_close_tab_cmd_callback (GtkAction *action,
gpointer data) gpointer data)
{ {
GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable; GimpDockable *dockable = dockable_get_current (dockbook);
gint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = (GimpDockable *)
gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (dockable) if (dockable)
gimp_dockbook_remove (dockbook, dockable); gimp_dockbook_remove (dockbook, dockable);
@ -100,18 +97,27 @@ dockable_detach_tab_cmd_callback (GtkAction *action,
gpointer data) gpointer data)
{ {
GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable; GimpDockable *dockable = dockable_get_current (dockbook);
gint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = (GimpDockable *)
gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (dockable) if (dockable)
gimp_dockable_detach (dockable); gimp_dockable_detach (dockable);
} }
void
dockable_lock_tab_cmd_callback (GtkAction *action,
gpointer data)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable = dockable_get_current (dockbook);
if (dockable)
{
gboolean lock = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
gimp_dockable_set_locked (dockable, lock);
}
}
void void
dockable_toggle_view_cmd_callback (GtkAction *action, dockable_toggle_view_cmd_callback (GtkAction *action,
GtkAction *current, GtkAction *current,
@ -219,17 +225,11 @@ dockable_view_size_cmd_callback (GtkAction *action,
gpointer data) gpointer data)
{ {
GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable; GimpDockable *dockable = dockable_get_current (dockbook);
gint view_size; gint view_size;
gint page_num;
view_size = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); view_size = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = (GimpDockable *)
gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (dockable) if (dockable)
{ {
GimpContainerView *view = gimp_container_view_get_by_dockable (dockable); GimpContainerView *view = gimp_container_view_get_by_dockable (dockable);
@ -253,25 +253,19 @@ dockable_tab_style_cmd_callback (GtkAction *action,
gpointer data) gpointer data)
{ {
GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable; GimpDockable *dockable = dockable_get_current (dockbook);
GimpTabStyle tab_style; GimpTabStyle tab_style;
gint page_num;
tab_style = (GimpTabStyle) tab_style = (GimpTabStyle)
gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = (GimpDockable *)
gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (dockable && dockable->tab_style != tab_style) if (dockable && dockable->tab_style != tab_style)
{ {
GtkWidget *tab_widget; GtkWidget *tab_widget;
gimp_dockable_set_tab_style (dockable, tab_style); gimp_dockable_set_tab_style (dockable, tab_style);
tab_widget = gimp_dockbook_get_tab_widget (dockbook, dockable); tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (dockbook), gtk_notebook_set_tab_label (GTK_NOTEBOOK (dockbook),
GTK_WIDGET (dockable), GTK_WIDGET (dockable),
@ -284,13 +278,7 @@ dockable_show_button_bar_cmd_callback (GtkAction *action,
gpointer data) gpointer data)
{ {
GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
GimpDockable *dockable; GimpDockable *dockable = dockable_get_current (dockbook);
gint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = (GimpDockable *)
gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (dockable) if (dockable)
{ {
@ -303,3 +291,12 @@ dockable_show_button_bar_cmd_callback (GtkAction *action,
gimp_docked_set_show_button_bar (docked, show); gimp_docked_set_show_button_bar (docked, show);
} }
} }
static GimpDockable *
dockable_get_current (GimpDockbook *dockbook)
{
gint page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
return (GimpDockable *) gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook),
page_num);
}

View File

@ -27,6 +27,8 @@ void dockable_close_tab_cmd_callback (GtkAction *action,
gpointer data); gpointer data);
void dockable_detach_tab_cmd_callback (GtkAction *action, void dockable_detach_tab_cmd_callback (GtkAction *action,
gpointer data); gpointer data);
void dockable_lock_tab_cmd_callback (GtkAction *action,
gpointer data);
void dockable_toggle_view_cmd_callback (GtkAction *action, void dockable_toggle_view_cmd_callback (GtkAction *action,
GtkAction *current, GtkAction *current,

View File

@ -506,8 +506,10 @@ plug_in_actions_history_changed (GimpPlugInManager *manager,
gimp_action_group_set_action_label (group, "plug-in-repeat", repeat); gimp_action_group_set_action_label (group, "plug-in-repeat", repeat);
gimp_action_group_set_action_label (group, "plug-in-reshow", reshow); gimp_action_group_set_action_label (group, "plug-in-reshow", reshow);
gimp_action_group_set_action_sensitive (group, "plug-in-repeat", sensitive); gimp_action_group_set_action_sensitive (group,
gimp_action_group_set_action_sensitive (group, "plug-in-reshow", sensitive); "plug-in-repeat", sensitive);
gimp_action_group_set_action_sensitive (group,
"plug-in-reshow", sensitive);
g_free (repeat); g_free (repeat);
g_free (reshow); g_free (reshow);

View File

@ -21,6 +21,8 @@
#include "config.h" #include "config.h"
#include <string.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h" #include "libgimpwidgets/gimpwidgets.h"
@ -36,12 +38,27 @@
#include "gimpdockbook.h" #include "gimpdockbook.h"
#include "gimpdocked.h" #include "gimpdocked.h"
#include "gimphelp-ids.h" #include "gimphelp-ids.h"
#include "gimpsessioninfo-aux.h"
#include "gimpuimanager.h" #include "gimpuimanager.h"
#include "gimpwidgets-utils.h" #include "gimpwidgets-utils.h"
#include "gimp-intl.h" #include "gimp-intl.h"
enum
{
PROP_0,
PROP_LOCKED
};
static void gimp_dockable_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_dockable_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_dockable_destroy (GtkObject *object); static void gimp_dockable_destroy (GtkObject *object);
static void gimp_dockable_size_request (GtkWidget *widget, static void gimp_dockable_size_request (GtkWidget *widget,
GtkRequisition *requisition); GtkRequisition *requisition);
@ -76,6 +93,8 @@ static void gimp_dockable_forall (GtkContainer *container,
GtkCallback callback, GtkCallback callback,
gpointer callback_data); gpointer callback_data);
static void gimp_dockable_cursor_setup (GimpDockable *dockable);
static void gimp_dockable_get_title_area (GimpDockable *dockable, static void gimp_dockable_get_title_area (GimpDockable *dockable,
GdkRectangle *area); GdkRectangle *area);
static void gimp_dockable_clear_title_area (GimpDockable *dockable); static void gimp_dockable_clear_title_area (GimpDockable *dockable);
@ -100,11 +119,15 @@ static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
static void static void
gimp_dockable_class_init (GimpDockableClass *klass) gimp_dockable_class_init (GimpDockableClass *klass)
{ {
GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->destroy = gimp_dockable_destroy; object_class->set_property = gimp_dockable_set_property;
object_class->get_property = gimp_dockable_get_property;
gtk_object_class->destroy = gimp_dockable_destroy;
widget_class->size_request = gimp_dockable_size_request; widget_class->size_request = gimp_dockable_size_request;
widget_class->size_allocate = gimp_dockable_size_allocate; widget_class->size_allocate = gimp_dockable_size_allocate;
@ -122,6 +145,11 @@ gimp_dockable_class_init (GimpDockableClass *klass)
container_class->child_type = gimp_dockable_child_type; container_class->child_type = gimp_dockable_child_type;
container_class->forall = gimp_dockable_forall; container_class->forall = gimp_dockable_forall;
g_object_class_install_property (object_class, PROP_LOCKED,
g_param_spec_boolean ("locked", NULL, NULL,
FALSE,
GIMP_PARAM_READWRITE));
gtk_widget_class_install_style_property (widget_class, gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("content-border", g_param_spec_int ("content-border",
NULL, NULL, NULL, NULL,
@ -175,7 +203,7 @@ gimp_dockable_init (GimpDockable *dockable)
dialog_target_table, G_N_ELEMENTS (dialog_target_table), dialog_target_table, G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE); GDK_ACTION_MOVE);
/* Filter out all button_press events not coming from the event window /* Filter out all button-press events not coming from the event window
over the title area. This keeps events that originate from widgets over the title area. This keeps events that originate from widgets
in the dockable to start a drag. in the dockable to start a drag.
*/ */
@ -187,6 +215,44 @@ gimp_dockable_init (GimpDockable *dockable)
NULL); NULL);
} }
static void
gimp_dockable_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpDockable *dockable = GIMP_DOCKABLE (object);
switch (property_id)
{
case PROP_LOCKED:
gimp_dockable_set_locked (dockable, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_dockable_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpDockable *dockable = GIMP_DOCKABLE (object);
switch (property_id)
{
case PROP_LOCKED:
g_value_set_boolean (value, dockable->locked);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void static void
gimp_dockable_destroy (GtkObject *object) gimp_dockable_destroy (GtkObject *object)
{ {
@ -344,7 +410,6 @@ gimp_dockable_realize (GtkWidget *widget)
{ {
GdkWindowAttr attributes; GdkWindowAttr attributes;
GdkRectangle area; GdkRectangle area;
GdkCursor *cursor;
gimp_dockable_get_title_area (dockable, &area); gimp_dockable_get_title_area (dockable, &area);
@ -367,12 +432,9 @@ gimp_dockable_realize (GtkWidget *widget)
GDK_WA_NOREDIR)); GDK_WA_NOREDIR));
gdk_window_set_user_data (dockable->title_window, widget); gdk_window_set_user_data (dockable->title_window, widget);
cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
GDK_HAND2);
gdk_window_set_cursor (dockable->title_window, cursor);
gdk_cursor_unref (cursor);
} }
gimp_dockable_cursor_setup (dockable);
} }
static void static void
@ -742,6 +804,7 @@ gimp_dockable_new (const gchar *name,
return GTK_WIDGET (dockable); return GTK_WIDGET (dockable);
} }
void void
gimp_dockable_set_aux_info (GimpDockable *dockable, gimp_dockable_set_aux_info (GimpDockable *dockable,
GList *aux_info) GList *aux_info)
@ -771,6 +834,32 @@ gimp_dockable_get_aux_info (GimpDockable *dockable)
return NULL; return NULL;
} }
void
gimp_dockable_set_locked (GimpDockable *dockable,
gboolean lock)
{
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
if (dockable->locked != lock)
{
dockable->locked = lock ? TRUE : FALSE;
gimp_dockable_cursor_setup (dockable);
g_object_notify (G_OBJECT (dockable), "locked");
}
}
gboolean
gimp_dockable_is_locked (GimpDockable *dockable)
{
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
return dockable->locked;
}
void void
gimp_dockable_set_tab_style (GimpDockable *dockable, gimp_dockable_set_tab_style (GimpDockable *dockable,
GimpTabStyle tab_style) GimpTabStyle tab_style)
@ -939,8 +1028,35 @@ gimp_dockable_blink_cancel (GimpDockable *dockable)
} }
} }
/* private functions */ /* private functions */
static void
gimp_dockable_cursor_setup (GimpDockable *dockable)
{
if (! GTK_WIDGET_REALIZED (dockable))
return;
if (! dockable->title_window)
return;
/* only show a hand cursor for unlocked dockables */
if (gimp_dockable_is_locked (dockable))
{
gdk_window_set_cursor (dockable->title_window, NULL);
}
else
{
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (dockable));
GdkCursor *cursor;
cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
gdk_window_set_cursor (dockable->title_window, cursor);
gdk_cursor_unref (cursor);
}
}
static void static void
gimp_dockable_get_title_area (GimpDockable *dockable, gimp_dockable_get_title_area (GimpDockable *dockable,
GdkRectangle *area) GdkRectangle *area)

View File

@ -48,6 +48,7 @@ struct _GimpDockable
gchar *stock_id; gchar *stock_id;
gchar *help_id; gchar *help_id;
GimpTabStyle tab_style; GimpTabStyle tab_style;
gboolean locked;
GimpDockbook *dockbook; GimpDockbook *dockbook;
@ -82,6 +83,10 @@ void gimp_dockable_set_aux_info (GimpDockable *dockable,
GList *aux_info); GList *aux_info);
GList * gimp_dockable_get_aux_info (GimpDockable *dockable); GList * gimp_dockable_get_aux_info (GimpDockable *dockable);
void gimp_dockable_set_locked (GimpDockable *dockable,
gboolean lock);
gboolean gimp_dockable_is_locked (GimpDockable *dockable);
void gimp_dockable_set_tab_style (GimpDockable *dockable, void gimp_dockable_set_tab_style (GimpDockable *dockable,
GimpTabStyle tab_style); GimpTabStyle tab_style);
GtkWidget * gimp_dockable_get_tab_widget (GimpDockable *dockable, GtkWidget * gimp_dockable_get_tab_widget (GimpDockable *dockable,

View File

@ -35,6 +35,7 @@
#include "gimpdnd.h" #include "gimpdnd.h"
#include "gimpdockable.h" #include "gimpdockable.h"
#include "gimpdockbook.h" #include "gimpdockbook.h"
#include "gimpdocked.h"
#include "gimphelp-ids.h" #include "gimphelp-ids.h"
#include "gimpimagedock.h" #include "gimpimagedock.h"
#include "gimpmenufactory.h" #include "gimpmenufactory.h"
@ -79,6 +80,8 @@ static void gimp_dockbook_dockable_removed (GimpDockbook *dockbook,
static void gimp_dockbook_update_tabs (GimpDockbook *dockbook, static void gimp_dockbook_update_tabs (GimpDockbook *dockbook,
gboolean added); gboolean added);
static void gimp_dockbook_tab_drag_source_setup (GtkWidget *widget,
GimpDockable *dockable);
static void gimp_dockbook_tab_drag_begin (GtkWidget *widget, static void gimp_dockbook_tab_drag_begin (GtkWidget *widget,
GdkDragContext *context, GdkDragContext *context,
GimpDockable *dockable); GimpDockable *dockable);
@ -106,6 +109,9 @@ static void gimp_dockbook_add_tab_timeout (GimpDockbook *dockbook,
GimpDockable *dockable); GimpDockable *dockable);
static void gimp_dockbook_remove_tab_timeout (GimpDockbook *dockbook); static void gimp_dockbook_remove_tab_timeout (GimpDockbook *dockbook);
static gboolean gimp_dockbook_tab_timeout (GimpDockbook *dockbook); static gboolean gimp_dockbook_tab_timeout (GimpDockbook *dockbook);
static void gimp_dockbook_tab_locked_notify (GimpDockable *dockable,
GParamSpec *pspec,
GimpDockbook *dockbook);
static void gimp_dockbook_help_func (const gchar *help_id, static void gimp_dockbook_help_func (const gchar *help_id,
gpointer help_data); gpointer help_data);
@ -244,8 +250,8 @@ gimp_dockbook_style_set (GtkWidget *widget,
{ {
GtkWidget *tab_widget; GtkWidget *tab_widget;
tab_widget = gimp_dockbook_get_tab_widget (GIMP_DOCKBOOK (widget), tab_widget = gimp_dockbook_create_tab_widget (GIMP_DOCKBOOK (widget),
GIMP_DOCKABLE (list->data)); GIMP_DOCKABLE (list->data));
gtk_notebook_set_tab_label (GTK_NOTEBOOK (widget), gtk_notebook_set_tab_label (GTK_NOTEBOOK (widget),
GTK_WIDGET (list->data), GTK_WIDGET (list->data),
@ -337,7 +343,7 @@ gimp_dockbook_add (GimpDockbook *dockbook,
g_return_if_fail (GIMP_IS_DOCKABLE (dockable)); g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
g_return_if_fail (dockable->dockbook == NULL); g_return_if_fail (dockable->dockbook == NULL);
tab_widget = gimp_dockbook_get_tab_widget (dockbook, dockable); tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
g_return_if_fail (GTK_IS_WIDGET (tab_widget)); g_return_if_fail (GTK_IS_WIDGET (tab_widget));
@ -370,6 +376,10 @@ gimp_dockbook_add (GimpDockbook *dockbook,
gimp_dockable_set_context (dockable, dockbook->dock->context); gimp_dockable_set_context (dockable, dockbook->dock->context);
g_signal_connect (dockable, "notify::locked",
G_CALLBACK (gimp_dockbook_tab_locked_notify),
dockbook);
g_signal_emit (dockbook, dockbook_signals[DOCKABLE_ADDED], 0, dockable); g_signal_emit (dockbook, dockbook_signals[DOCKABLE_ADDED], 0, dockable);
} }
@ -385,6 +395,10 @@ gimp_dockbook_remove (GimpDockbook *dockbook,
g_object_ref (dockable); g_object_ref (dockable);
g_signal_handlers_disconnect_by_func (dockable,
G_CALLBACK (gimp_dockbook_tab_locked_notify),
dockbook);
if (dockbook->tab_hover_dockable == dockable) if (dockbook->tab_hover_dockable == dockable)
gimp_dockbook_remove_tab_timeout (dockbook); gimp_dockbook_remove_tab_timeout (dockbook);
@ -407,8 +421,8 @@ gimp_dockbook_remove (GimpDockbook *dockbook,
} }
GtkWidget * GtkWidget *
gimp_dockbook_get_tab_widget (GimpDockbook *dockbook, gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
GimpDockable *dockable) GimpDockable *dockable)
{ {
GtkWidget *tab_widget; GtkWidget *tab_widget;
GtkIconSize tab_size = DEFAULT_TAB_ICON_SIZE; GtkIconSize tab_size = DEFAULT_TAB_ICON_SIZE;
@ -482,13 +496,8 @@ gimp_dockbook_get_tab_widget (GimpDockbook *dockbook,
g_object_set_data (G_OBJECT (tab_widget), "gimp-dockable", dockable); g_object_set_data (G_OBJECT (tab_widget), "gimp-dockable", dockable);
/* set the drag source *before* connecting button_press because we gimp_dockbook_tab_drag_source_setup (tab_widget, dockable);
* stop button_press emission by returning TRUE from the callback
*/
gtk_drag_source_set (GTK_WIDGET (tab_widget),
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
dialog_target_table, G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE);
g_signal_connect (tab_widget, "drag-begin", g_signal_connect (tab_widget, "drag-begin",
G_CALLBACK (gimp_dockbook_tab_drag_begin), G_CALLBACK (gimp_dockbook_tab_drag_begin),
dockable); dockable);
@ -496,10 +505,6 @@ gimp_dockbook_get_tab_widget (GimpDockbook *dockbook,
G_CALLBACK (gimp_dockbook_tab_drag_end), G_CALLBACK (gimp_dockbook_tab_drag_end),
dockable); dockable);
gtk_drag_source_set (GTK_WIDGET (dockable),
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
dialog_target_table, G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE);
g_signal_connect (dockable, "drag-begin", g_signal_connect (dockable, "drag-begin",
G_CALLBACK (gimp_dockbook_tab_drag_begin), G_CALLBACK (gimp_dockbook_tab_drag_begin),
dockable); dockable);
@ -507,7 +512,7 @@ gimp_dockbook_get_tab_widget (GimpDockbook *dockbook,
G_CALLBACK (gimp_dockbook_tab_drag_end), G_CALLBACK (gimp_dockbook_tab_drag_end),
dockable); dockable);
gtk_drag_dest_set (GTK_WIDGET (tab_widget), gtk_drag_dest_set (tab_widget,
GTK_DEST_DEFAULT_DROP, GTK_DEST_DEFAULT_DROP,
dialog_target_table, G_N_ELEMENTS (dialog_target_table), dialog_target_table, G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE); GDK_ACTION_MOVE);
@ -570,6 +575,34 @@ gimp_dockbook_drop_dockable (GimpDockbook *dockbook,
/* tab DND source side */ /* tab DND source side */
static void
gimp_dockbook_tab_drag_source_setup (GtkWidget *widget,
GimpDockable *dockable)
{
if (gimp_dockable_is_locked (dockable))
{
if (widget)
gtk_drag_source_unset (widget);
gtk_drag_source_unset (GTK_WIDGET (dockable));
}
else
{
if (widget)
gtk_drag_source_set (widget,
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
dialog_target_table,
G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE);
gtk_drag_source_set (GTK_WIDGET (dockable),
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
dialog_target_table,
G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE);
}
}
static void static void
gimp_dockbook_tab_drag_begin (GtkWidget *widget, gimp_dockbook_tab_drag_begin (GtkWidget *widget,
GdkDragContext *context, GdkDragContext *context,
@ -796,16 +829,27 @@ gimp_dockbook_tab_timeout (GimpDockbook *dockbook)
return FALSE; return FALSE;
} }
static void
gimp_dockbook_tab_locked_notify (GimpDockable *dockable,
GParamSpec *pspec,
GimpDockbook *dockbook)
{
GtkWidget *tab_widget;
tab_widget = gtk_notebook_get_tab_label (GTK_NOTEBOOK (dockbook),
GTK_WIDGET (dockable));
gimp_dockbook_tab_drag_source_setup (tab_widget, dockable);
}
static void static void
gimp_dockbook_help_func (const gchar *help_id, gimp_dockbook_help_func (const gchar *help_id,
gpointer help_data) gpointer help_data)
{ {
GimpDockbook *dockbook; GimpDockbook *dockbook = GIMP_DOCKBOOK (help_data);
GtkWidget *dockable; GtkWidget *dockable;
gint page_num; gint page_num;
dockbook = GIMP_DOCKBOOK (help_data);
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook)); page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num); dockable = gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);

View File

@ -60,20 +60,20 @@ struct _GimpDockbookClass
}; };
GType gimp_dockbook_get_type (void) G_GNUC_CONST; GType gimp_dockbook_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_dockbook_new (GimpMenuFactory *menu_factory); GtkWidget * gimp_dockbook_new (GimpMenuFactory *menu_factory);
void gimp_dockbook_add (GimpDockbook *dockbook, void gimp_dockbook_add (GimpDockbook *dockbook,
GimpDockable *dockable, GimpDockable *dockable,
gint position); gint position);
void gimp_dockbook_remove (GimpDockbook *dockbook, void gimp_dockbook_remove (GimpDockbook *dockbook,
GimpDockable *dockable); GimpDockable *dockable);
GtkWidget * gimp_dockbook_get_tab_widget (GimpDockbook *dockbook, GtkWidget * gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
GimpDockable *dockable); GimpDockable *dockable);
gboolean gimp_dockbook_drop_dockable (GimpDockbook *dockbook, gboolean gimp_dockbook_drop_dockable (GimpDockbook *dockbook,
GtkWidget *drag_source); GtkWidget *drag_source);
#endif /* __GIMP_DOCKBOOK_H__ */ #endif /* __GIMP_DOCKBOOK_H__ */

View File

@ -452,6 +452,7 @@
#define GIMP_HELP_DOCK_TAB_ADD "gimp-dock-tab-add" #define GIMP_HELP_DOCK_TAB_ADD "gimp-dock-tab-add"
#define GIMP_HELP_DOCK_TAB_CLOSE "gimp-dock-tab-close" #define GIMP_HELP_DOCK_TAB_CLOSE "gimp-dock-tab-close"
#define GIMP_HELP_DOCK_TAB_LOCK "gimp-dock-tab-lock"
#define GIMP_HELP_DOCK_TAB_MENU "gimp-dock-tab-menu" #define GIMP_HELP_DOCK_TAB_MENU "gimp-dock-tab-menu"
#define GIMP_HELP_DOCK_TAB_DETACH "gimp-dock-tab-detach" #define GIMP_HELP_DOCK_TAB_DETACH "gimp-dock-tab-detach"
#define GIMP_HELP_DOCK_PREVIEW_SIZE "gimp-dock-preview-size" #define GIMP_HELP_DOCK_PREVIEW_SIZE "gimp-dock-preview-size"

View File

@ -38,6 +38,7 @@
enum enum
{ {
SESSION_INFO_DOCKABLE_LOCKED,
SESSION_INFO_DOCKABLE_TAB_STYLE, SESSION_INFO_DOCKABLE_TAB_STYLE,
SESSION_INFO_DOCKABLE_VIEW_SIZE, SESSION_INFO_DOCKABLE_VIEW_SIZE,
SESSION_INFO_DOCKABLE_AUX SESSION_INFO_DOCKABLE_AUX
@ -89,6 +90,12 @@ gimp_session_info_dockable_serialize (GimpConfigWriter *writer,
gimp_config_writer_open (writer, "dockable"); gimp_config_writer_open (writer, "dockable");
gimp_config_writer_string (writer, info->identifier); gimp_config_writer_string (writer, info->identifier);
if (info->locked)
{
gimp_config_writer_open (writer, "locked");
gimp_config_writer_close (writer);
}
enum_value = g_enum_get_value (enum_class, info->tab_style); enum_value = g_enum_get_value (enum_class, info->tab_style);
if (enum_value) if (enum_value)
@ -126,6 +133,8 @@ gimp_session_info_dockable_deserialize (GScanner *scanner,
g_return_val_if_fail (scanner != NULL, G_TOKEN_LEFT_PAREN); g_return_val_if_fail (scanner != NULL, G_TOKEN_LEFT_PAREN);
g_return_val_if_fail (dockable != NULL, G_TOKEN_LEFT_PAREN); g_return_val_if_fail (dockable != NULL, G_TOKEN_LEFT_PAREN);
g_scanner_scope_add_symbol (scanner, scope, "locked",
GINT_TO_POINTER (SESSION_INFO_DOCKABLE_LOCKED));
g_scanner_scope_add_symbol (scanner, scope, "tab-style", g_scanner_scope_add_symbol (scanner, scope, "tab-style",
GINT_TO_POINTER (SESSION_INFO_DOCKABLE_TAB_STYLE)); GINT_TO_POINTER (SESSION_INFO_DOCKABLE_TAB_STYLE));
g_scanner_scope_add_symbol (scanner, scope, "preview-size", g_scanner_scope_add_symbol (scanner, scope, "preview-size",
@ -156,6 +165,10 @@ gimp_session_info_dockable_deserialize (GScanner *scanner,
case G_TOKEN_SYMBOL: case G_TOKEN_SYMBOL:
switch (GPOINTER_TO_INT (scanner->value.v_symbol)) switch (GPOINTER_TO_INT (scanner->value.v_symbol))
{ {
case SESSION_INFO_DOCKABLE_LOCKED:
info->locked = TRUE;
break;
case SESSION_INFO_DOCKABLE_TAB_STYLE: case SESSION_INFO_DOCKABLE_TAB_STYLE:
token = G_TOKEN_IDENTIFIER; token = G_TOKEN_IDENTIFIER;
if (g_scanner_peek_next_token (scanner) != token) if (g_scanner_peek_next_token (scanner) != token)
@ -206,6 +219,7 @@ gimp_session_info_dockable_deserialize (GScanner *scanner,
g_type_class_unref (enum_class); g_type_class_unref (enum_class);
g_scanner_scope_remove_symbol (scanner, scope, "locked");
g_scanner_scope_remove_symbol (scanner, scope, "tab-style"); g_scanner_scope_remove_symbol (scanner, scope, "tab-style");
g_scanner_scope_remove_symbol (scanner, scope, "preview-size"); g_scanner_scope_remove_symbol (scanner, scope, "preview-size");
g_scanner_scope_remove_symbol (scanner, scope, "aux-info"); g_scanner_scope_remove_symbol (scanner, scope, "aux-info");
@ -237,6 +251,7 @@ gimp_session_info_dockable_from_widget (GimpDockable *dockable)
info = gimp_session_info_dockable_new (); info = gimp_session_info_dockable_new ();
info->locked = dockable->locked;
info->identifier = g_strdup (entry->identifier); info->identifier = g_strdup (entry->identifier);
info->tab_style = dockable->tab_style; info->tab_style = dockable->tab_style;
info->view_size = -1; info->view_size = -1;
@ -278,6 +293,7 @@ gimp_session_info_dockable_restore (GimpSessionInfoDockable *info,
if (dockable) if (dockable)
{ {
gimp_dockable_set_locked (GIMP_DOCKABLE (dockable), info->locked);
gimp_dockable_set_tab_style (GIMP_DOCKABLE (dockable), info->tab_style); gimp_dockable_set_tab_style (GIMP_DOCKABLE (dockable), info->tab_style);
if (info->aux_info) if (info->aux_info)

View File

@ -26,6 +26,7 @@
struct _GimpSessionInfoDockable struct _GimpSessionInfoDockable
{ {
gchar *identifier; gchar *identifier;
gboolean locked;
GimpTabStyle tab_style; GimpTabStyle tab_style;
gint view_size; gint view_size;

View File

@ -9,6 +9,7 @@
</menu> </menu>
<menuitem action="dockable-close-tab" /> <menuitem action="dockable-close-tab" />
<menuitem action="dockable-detach-tab" /> <menuitem action="dockable-detach-tab" />
<menuitem action="dockable-lock-tab" />
<separator /> <separator />
<menu action="dockable-preview-size-menu"> <menu action="dockable-preview-size-menu">
<menuitem action="dockable-preview-size-tiny" /> <menuitem action="dockable-preview-size-tiny" />