Bug 602223 - Can't hide docks with Tab in single-window mode

Add a "hide-docks" config and connect the Windows->Hide docks menu
item to it. Also connect the image window to the config property so it
can hide/show its docks when it needs to.

Also add and use a utility function
gimp_image_window_keep_canvas_pos() to ensure that the image in the
window remains fixed when toggling visiblity of docks. One problem:
When GimpDrawTool is active on the canvas, there is flicker. The end
position is correct though.

Also add regression testing for this fix to test-ui.c
This commit is contained in:
Martin Nordholts 2010-02-23 20:21:08 +01:00
parent 82a0b95147
commit 18f3be6bd3
7 changed files with 207 additions and 10 deletions

View File

@ -201,8 +201,7 @@ windows_actions_update (GimpActionGroup *group,
gimp_action_group_set_action_active (group, action, (condition) != 0)
SET_ACTIVE ("windows-use-single-window-mode", config->single_window_mode);
SET_ACTIVE ("windows-hide-docks", (gimp_dialog_factories_get_state () !=
GIMP_DIALOGS_SHOWN));
SET_ACTIVE ("windows-hide-docks", config->hide_docks);
#undef SET_ACTIVE
}

View File

@ -56,6 +56,11 @@ windows_hide_docks_cmd_callback (GtkAction *action,
gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
GimpDialogsState state = gimp_dialog_factories_get_state ();
GimpDialogsState new_state = state;
Gimp *gimp = NULL;
return_if_no_gimp (gimp, data);
if (GIMP_GUI_CONFIG (gimp->config)->hide_docks == active)
return;
/* Make sure the state and toggle action are in sync */
if (active && state == GIMP_DIALOGS_SHOWN)
@ -65,6 +70,10 @@ windows_hide_docks_cmd_callback (GtkAction *action,
if (state != new_state)
gimp_dialog_factories_set_state (new_state);
g_object_set (gimp->config,
"hide-docks", active,
NULL);
}
void

View File

@ -52,6 +52,7 @@ enum
PROP_RESTORE_SESSION,
PROP_SAVE_TOOL_OPTIONS,
PROP_SHOW_TOOLTIPS,
PROP_HIDE_DOCKS,
PROP_SINGLE_WINDOW_MODE,
PROP_TEAROFF_MENUS,
PROP_CAN_CHANGE_ACCELS,
@ -154,6 +155,11 @@ gimp_gui_config_class_init (GimpGuiConfigClass *klass)
TRUE,
GIMP_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_RESTART);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_HIDE_DOCKS,
"hide-docks", HIDE_DOCKS_BLURB,
FALSE,
GIMP_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_RESTART);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SINGLE_WINDOW_MODE,
"single-window-mode", SINGLE_WINDOW_MODE_BLURB,
FALSE,
@ -353,6 +359,9 @@ gimp_gui_config_set_property (GObject *object,
case PROP_SHOW_TOOLTIPS:
gui_config->show_tooltips = g_value_get_boolean (value);
break;
case PROP_HIDE_DOCKS:
gui_config->hide_docks = g_value_get_boolean (value);
break;
case PROP_SINGLE_WINDOW_MODE:
gui_config->single_window_mode = g_value_get_boolean (value);
break;
@ -474,6 +483,9 @@ gimp_gui_config_get_property (GObject *object,
case PROP_SHOW_TOOLTIPS:
g_value_set_boolean (value, gui_config->show_tooltips);
break;
case PROP_HIDE_DOCKS:
g_value_set_boolean (value, gui_config->hide_docks);
break;
case PROP_SINGLE_WINDOW_MODE:
g_value_set_boolean (value, gui_config->single_window_mode);
break;

View File

@ -46,6 +46,7 @@ struct _GimpGuiConfig
gboolean restore_session;
gboolean save_tool_options;
gboolean show_tooltips;
gboolean hide_docks;
gboolean single_window_mode;
gboolean tearoff_menus;
gboolean can_change_accels;

View File

@ -361,6 +361,9 @@ N_("Show a tooltip when the pointer hovers over an item.")
#define SINGLE_WINDOW_MODE_BLURB \
N_("Use GIMP in a single-window mode.")
#define HIDE_DOCKS_BLURB \
N_("Hide docks and other windows, leaving only image windows.")
#define SPACE_BAR_ACTION_BLURB \
N_("What to do when the space bar is pressed in the image window.")

View File

@ -50,6 +50,7 @@
#include "gimpdisplayshell-callbacks.h"
#include "gimpdisplayshell-close.h"
#include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-transform.h"
#include "gimpimagewindow.h"
#include "gimpstatusbar.h"
@ -90,6 +91,14 @@ struct _GimpImageWindowPrivate
gboolean is_empty;
};
typedef struct
{
GimpImageWindow *window;
gint x;
gint y;
} PosCorrectionData;
#define GIMP_IMAGE_WINDOW_GET_PRIVATE(window) \
G_TYPE_INSTANCE_GET_PRIVATE (window, \
GIMP_TYPE_IMAGE_WINDOW, \
@ -131,6 +140,10 @@ static void gimp_image_window_show_tooltip (GimpUIManager *man
static void gimp_image_window_hide_tooltip (GimpUIManager *manager,
GimpImageWindow *window);
static void gimp_image_window_keep_canvas_pos (GimpImageWindow *window);
static void gimp_image_window_shell_size_allocate (GimpDisplayShell *shell,
GtkAllocation *allocation,
PosCorrectionData *data);
static gboolean gimp_image_window_shell_events (GtkWidget *widget,
GdkEvent *event,
GimpImageWindow *window);
@ -344,6 +357,9 @@ gimp_image_window_constructor (GType type,
g_signal_connect_object (config, "notify::single-window-mode",
G_CALLBACK (gimp_image_window_config_notify),
window, G_CONNECT_SWAPPED);
g_signal_connect_object (config, "notify::hide-docks",
G_CALLBACK (gimp_image_window_config_notify),
window, G_CONNECT_SWAPPED);
return object;
}
@ -1045,10 +1061,15 @@ gimp_image_window_config_notify (GimpImageWindow *window,
{
GimpImageWindowPrivate *private = GIMP_IMAGE_WINDOW_GET_PRIVATE (window);
if (strcmp (pspec->name, "single-window-mode") == 0)
if (strcmp (pspec->name, "single-window-mode") == 0 ||
strcmp (pspec->name, "hide-docks") == 0)
{
gtk_widget_set_visible (private->left_docks, config->single_window_mode);
gtk_widget_set_visible (private->right_docks, config->single_window_mode);
gboolean show_docks = (config->single_window_mode &&
! config->hide_docks);
gimp_image_window_keep_canvas_pos (window);
gtk_widget_set_visible (private->left_docks, show_docks);
gtk_widget_set_visible (private->right_docks, show_docks);
}
}
@ -1067,6 +1088,74 @@ gimp_image_window_hide_tooltip (GimpUIManager *manager,
gimp_statusbar_pop (statusbar, "menu-tooltip");
}
/**
* gimp_image_window_keep_canvas_pos:
* @window:
*
* Stores the coordinate of the current shell image origin in
* GtkWindow coordinates and on the first size-allocate sets the
* offsets in the shell so the image origin remains the same in
* GtkWindow coordinates.
*
* Exampe use case: The user hides docks attached to the side of image
* windows. You want the image to remain fixed on the screen though,
* so you use this function to keep the image fixed after the docks
* have been hidden.
**/
static void
gimp_image_window_keep_canvas_pos (GimpImageWindow *window)
{
GimpDisplayShell *shell = gimp_image_window_get_active_shell (window);
gint image_origin_shell_x = -1;
gint image_origin_shell_y = -1;
gint image_origin_window_x = -1;
gint image_origin_window_y = -1;
PosCorrectionData *data = NULL;
gimp_display_shell_transform_xy (shell,
0.0, 0.0,
&image_origin_shell_x, &image_origin_shell_y,
FALSE /*use_offsets*/);
gtk_widget_translate_coordinates (GTK_WIDGET (shell),
GTK_WIDGET (window),
image_origin_shell_x, image_origin_shell_y,
&image_origin_window_x, &image_origin_window_y);
data = g_new0 (PosCorrectionData, 1);
data->window = window;
data->x = image_origin_window_x;
data->y = image_origin_window_y;
g_signal_connect_data (shell, "size-allocate",
G_CALLBACK (gimp_image_window_shell_size_allocate),
data, (GClosureNotify) g_free,
G_CONNECT_AFTER);
}
static void
gimp_image_window_shell_size_allocate (GimpDisplayShell *shell,
GtkAllocation *allocation,
PosCorrectionData *data)
{
GimpImageWindow *window = data->window;
gint image_origin_shell_x = -1;
gint image_origin_shell_y = -1;
gtk_widget_translate_coordinates (GTK_WIDGET (window),
GTK_WIDGET (shell),
data->x, data->y,
&image_origin_shell_x, &image_origin_shell_y);
/* Note that the shell offset isn't the offset of the image into the
* shell, but the offset of the shell relative to the image,
* therefor we need to negate
*/
gimp_display_shell_scroll_set_offset (shell, -image_origin_shell_x, -image_origin_shell_y);
g_signal_handlers_disconnect_by_func (shell,
gimp_image_window_shell_size_allocate,
data);
}
static gboolean
gimp_image_window_shell_events (GtkWidget *widget,
GdkEvent *event,

View File

@ -28,6 +28,8 @@
#include "dialogs/dialogs.h"
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
#include "display/gimpdisplayshell-transform.h"
#include "display/gimpimagewindow.h"
#include "widgets/gimpdialogfactory.h"
@ -48,7 +50,10 @@
#include "gimp-app-test-utils.h"
#define GIMP_UI_POSITION_EPSILON 10
#define GIMP_UI_WINDOW_POSITION_EPSILON 10
#define GIMP_UI_WINDOW_POSITION_EPSILON 10
#define GIMP_UI_POSITION_EPSILON 1
#define GIMP_UI_POSITION_EPSILON 1
typedef struct
@ -67,6 +72,10 @@ static void gimp_ui_tab_toggle_dont_change_position (GimpTestFixture
gconstpointer data);
static void gimp_ui_switch_to_single_window_mode (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_hide_docks_in_single_window_mode (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_show_docks_in_single_window_mode (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_switch_back_to_multi_window_mode (GimpTestFixture *fixture,
gconstpointer data);
static GimpUIManager * gimp_ui_get_ui_manager (Gimp *gimp);
@ -122,6 +131,18 @@ int main(int argc, char **argv)
NULL,
gimp_ui_switch_to_single_window_mode,
NULL);
g_test_add ("/gimp-ui/hide-docks-in-single-window-mode",
GimpTestFixture,
gimp,
NULL,
gimp_ui_hide_docks_in_single_window_mode,
NULL);
g_test_add ("/gimp-ui/show-docks-in-single-window-mode",
GimpTestFixture,
gimp,
NULL,
gimp_ui_show_docks_in_single_window_mode,
NULL);
g_test_add ("/gimp-ui/switch-back-to-multi-window-mode",
GimpTestFixture,
gimp,
@ -345,10 +366,10 @@ gimp_ui_tab_toggle_dont_change_position (GimpTestFixture *fixture,
gtk_window_get_size (GTK_WINDOW (dock_window),
&w_after_show,
&h_after_show);
g_assert_cmpint ((int)abs (x_before_hide - x_after_show), <, GIMP_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <, GIMP_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <, GIMP_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <, GIMP_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (x_before_hide - x_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <=, GIMP_UI_WINDOW_POSITION_EPSILON);
}
static void
@ -366,6 +387,69 @@ gimp_ui_switch_to_single_window_mode (GimpTestFixture *fixture,
gimp_test_run_mainloop_until_idle ();
}
static void
gimp_ui_toggle_docks_in_single_window_mode (Gimp *gimp)
{
GimpDisplay *display = GIMP_DISPLAY (gimp_get_display_iter (gimp)->data);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GtkWidget *toplevel = GTK_WIDGET (gimp_display_shell_get_window (shell));
gint x_temp = -1;
gint y_temp = -1;
gint x_before_hide = -1;
gint y_before_hide = -1;
gint x_after_hide = -1;
gint y_after_hide = -1;
g_assert (shell);
g_assert (toplevel);
/* Get toplevel coordinate of image origin */
gimp_test_run_mainloop_until_idle ();
gimp_display_shell_transform_xy (shell,
0.0, 0.0,
&x_temp, &y_temp,
FALSE /*use_offsets*/);
gtk_widget_translate_coordinates (GTK_WIDGET (shell),
toplevel,
x_temp, y_temp,
&x_before_hide, &y_before_hide);
/* Hide all dock windows */
gimp_ui_manager_activate_action (gimp_ui_get_ui_manager (gimp),
"windows",
"windows-hide-docks");
gimp_test_run_mainloop_until_idle ();
/* Get toplevel coordinate of image origin */
gimp_test_run_mainloop_until_idle ();
gimp_display_shell_transform_xy (shell,
0.0, 0.0,
&x_temp, &y_temp,
FALSE /*use_offsets*/);
gtk_widget_translate_coordinates (GTK_WIDGET (shell),
toplevel,
x_temp, y_temp,
&x_after_hide, &y_after_hide);
g_assert_cmpint ((int)abs (x_after_hide - x_before_hide), <=, GIMP_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (y_after_hide - y_before_hide), <=, GIMP_UI_POSITION_EPSILON);
}
static void
gimp_ui_hide_docks_in_single_window_mode (GimpTestFixture *fixture,
gconstpointer data)
{
Gimp *gimp = GIMP (data);
gimp_ui_toggle_docks_in_single_window_mode (gimp);
}
static void
gimp_ui_show_docks_in_single_window_mode (GimpTestFixture *fixture,
gconstpointer data)
{
Gimp *gimp = GIMP (data);
gimp_ui_toggle_docks_in_single_window_mode (gimp);
}
static void
gimp_ui_switch_back_to_multi_window_mode (GimpTestFixture *fixture,
gconstpointer data)