Commit 9b86acd1 authored by Martin Nordholts's avatar Martin Nordholts

Add 'Automatic' Tab Style support

Add support for a new type of Tab Style called 'Automatic'. This tab
style makes the GimpDockbook use the biggest actual tab style it can
for its auto tab style dockables, based on its widget allocation.

The tab style candidates for auto tab style are "Status + Blurb",
"Status + Text" and "Status". A docked widget can also say that it
wants to use "Icon" instead of "Status" for its auto tab style. The
'Tool Options' dockable does this. This is to be as backwards
compatible with the old tab style setup, we make 'automatic' the
default everywhere.

We have quite a bit of dependency to internal layout code in
GtkNotebook, but the current code should be pixel perfect and rather
complete.

Also add a basic regression test.
parent 501f97b5
......@@ -111,7 +111,9 @@ static const GimpRadioActionEntry dockable_tab_style_actions[] =
TAB_STYLE ("icon-name",
NC_("tab-style", "I_con & Text"), GIMP_TAB_STYLE_ICON_NAME),
TAB_STYLE ("preview-name",
NC_("tab-style", "St_atus & Text"), GIMP_TAB_STYLE_PREVIEW_NAME)
NC_("tab-style", "St_atus & Text"), GIMP_TAB_STYLE_PREVIEW_NAME),
TAB_STYLE ("automatic",
NC_("tab-style", "Automatic"), GIMP_TAB_STYLE_AUTOMATIC)
};
#undef VIEW_SIZE
......@@ -176,7 +178,7 @@ dockable_actions_setup (GimpActionGroup *group)
dockable_tab_style_actions,
G_N_ELEMENTS (dockable_tab_style_actions),
NULL,
GIMP_TAB_STYLE_PREVIEW,
GIMP_TAB_STYLE_AUTOMATIC,
G_CALLBACK (dockable_tab_style_cmd_callback));
gimp_action_group_add_radio_actions (group, "dockable-action",
......@@ -344,6 +346,8 @@ dockable_actions_update (GimpActionGroup *group,
SET_ACTIVE ("dockable-tab-style-icon-name", TRUE);
else if (tab_style == GIMP_TAB_STYLE_PREVIEW_NAME)
SET_ACTIVE ("dockable-tab-style-preview-name", TRUE);
else if (tab_style == GIMP_TAB_STYLE_AUTOMATIC)
SET_ACTIVE ("dockable-tab-style-automatic", TRUE);
SET_SENSITIVE ("dockable-tab-style-preview",
docked_iface->get_preview);
......
......@@ -51,7 +51,8 @@ gimp_log_init (void)
{ "floating-selection", GIMP_LOG_FLOATING_SELECTION },
{ "shm", GIMP_LOG_SHM },
{ "text-editing", GIMP_LOG_TEXT_EDITING },
{ "key-events", GIMP_LOG_KEY_EVENTS }
{ "key-events", GIMP_LOG_KEY_EVENTS },
{ "auto-tab-style", GIMP_LOG_AUTO_TAB_STYLE }
};
/* g_parse_debug_string() has special treatment of the string 'help',
......
......@@ -35,7 +35,8 @@ typedef enum
GIMP_LOG_FLOATING_SELECTION = 1 << 11,
GIMP_LOG_SHM = 1 << 12,
GIMP_LOG_TEXT_EDITING = 1 << 13,
GIMP_LOG_KEY_EVENTS = 1 << 14
GIMP_LOG_KEY_EVENTS = 1 << 14,
GIMP_LOG_AUTO_TAB_STYLE = 1 << 15
} GimpLogFlags;
......@@ -91,6 +92,7 @@ void gimp_logv (const gchar *function,
#define SHM GIMP_LOG_SHM
#define TEXT_EDITING GIMP_LOG_TEXT_EDITING
#define KEY_EVENTS GIMP_LOG_KEY_EVENTS
#define AUTO_TAB_STYLE GIMP_LOG_AUTO_TAB_STYLE
#if 0 /* last resort */
# define GIMP_LOG /* nothing => no varargs, no log */
......
......@@ -67,7 +67,7 @@
(book
(current-page 0)
(dockable "gimp-channel-list"
(tab-style icon)
(tab-style automatic)
(preview-size 32)))
(book
(position 162)
......
......@@ -71,7 +71,7 @@
(book
(current-page 0)
(dockable "gimp-channel-list"
(tab-style icon)
(tab-style automatic)
(preview-size 32)))
(book
(position 162)
......
......@@ -16,6 +16,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
......@@ -31,6 +32,8 @@
#include "display/gimpimagewindow.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockable.h"
#include "widgets/gimpdockbook.h"
#include "widgets/gimpdocked.h"
#include "widgets/gimpdockwindow.h"
#include "widgets/gimphelp-ids.h"
......@@ -66,6 +69,8 @@ typedef struct
static void gimp_ui_tool_options_editor_updates (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_automatic_tab_style (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_create_new_image_via_dialog (GimpTestFixture *fixture,
gconstpointer data);
static void gimp_ui_restore_recently_closed_dock (GimpTestFixture *fixture,
......@@ -112,6 +117,12 @@ int main(int argc, char **argv)
NULL,
gimp_ui_tool_options_editor_updates,
NULL);
g_test_add ("/gimp-ui/automatic-tab-style",
GimpTestFixture,
gimp,
NULL,
gimp_ui_automatic_tab_style,
NULL);
g_test_add ("/gimp-ui/create-new-image-via-dialog",
GimpTestFixture,
gimp,
......@@ -155,6 +166,7 @@ int main(int argc, char **argv)
gimp_ui_switch_back_to_multi_window_mode,
NULL);
/* Run the tests and return status */
result = g_test_run ();
......@@ -217,6 +229,82 @@ gimp_ui_tool_options_editor_updates (GimpTestFixture *fixture,
help_id);
}
static GtkWidget *
gimp_ui_get_dialog (const gchar *identifier)
{
GtkWidget *result = NULL;
GList *iter;
for (iter = gimp_dialog_factory_get_open_dialogs (gimp_dialog_factory_get_singleton ());
iter;
iter = g_list_next (iter))
{
GtkWidget *dialog = GTK_WIDGET (iter->data);
GimpDialogFactoryEntry *entry = NULL;
gimp_dialog_factory_from_widget (dialog, &entry);
if (strcmp (entry->identifier, identifier) == 0)
{
result = dialog;
break;
}
}
return result;
}
static void
gimp_ui_automatic_tab_style (GimpTestFixture *fixture,
gconstpointer data)
{
GtkWidget *channel_dockable = gimp_ui_get_dialog ("gimp-channel-list");
GimpDockable *dockable;
GimpUIManager *ui_manager;
g_assert (channel_dockable != NULL);
dockable = GIMP_DOCKABLE (channel_dockable);
/* The channel dockable is the only dockable, it has enough space
* for the icon-blurb
*/
g_assert_cmpint (GIMP_TAB_STYLE_ICON_BLURB,
==,
gimp_dockable_get_actual_tab_style (dockable));
/* Add some dockables to the channel dockable dockbook */
ui_manager =
gimp_dockbook_get_ui_manager (gimp_dockable_get_dockbook (dockable));
gimp_ui_manager_activate_action (ui_manager,
"dockable",
"dialogs-sample-points");
gimp_ui_manager_activate_action (ui_manager,
"dockable",
"dialogs-vectors");
gimp_test_run_mainloop_until_idle ();
/* Now there is not enough space to have icon-blurb for channel
* dockable, make sure it's just an icon now
*/
g_assert_cmpint (GIMP_TAB_STYLE_ICON,
==,
gimp_dockable_get_actual_tab_style (dockable));
/* Close the two dockables we added */
gimp_ui_manager_activate_action (ui_manager,
"dockable",
"dockable-close-tab");
gimp_ui_manager_activate_action (ui_manager,
"dockable",
"dockable-close-tab");
gimp_test_run_mainloop_until_idle ();
/* We should now be back on icon-blurb */
g_assert_cmpint (GIMP_TAB_STYLE_ICON_BLURB,
==,
gimp_dockable_get_actual_tab_style (dockable));
}
static void
gimp_ui_create_new_image_via_dialog (GimpTestFixture *fixture,
gconstpointer data)
......
......@@ -62,6 +62,7 @@ struct _GimpDockablePrivate
gchar *stock_id;
gchar *help_id;
GimpTabStyle tab_style;
GimpTabStyle actual_tab_style;
gboolean locked;
GimpDockbook *dockbook;
......@@ -215,9 +216,10 @@ gimp_dockable_init (GimpDockable *dockable)
dockable->p = G_TYPE_INSTANCE_GET_PRIVATE (dockable,
GIMP_TYPE_DOCKABLE,
GimpDockablePrivate);
dockable->p->tab_style = GIMP_TAB_STYLE_PREVIEW;
dockable->p->drag_x = GIMP_DOCKABLE_DRAG_OFFSET;
dockable->p->drag_y = GIMP_DOCKABLE_DRAG_OFFSET;
dockable->p->tab_style = GIMP_TAB_STYLE_AUTOMATIC;
dockable->p->actual_tab_style = GIMP_TAB_STYLE_UNDEFINED;
dockable->p->drag_x = GIMP_DOCKABLE_DRAG_OFFSET;
dockable->p->drag_y = GIMP_DOCKABLE_DRAG_OFFSET;
gtk_widget_push_composite_child ();
dockable->p->menu_button = gtk_button_new ();
......@@ -884,6 +886,11 @@ gimp_dockable_new_tab_widget_internal (GimpDockable *dockable,
gtk_box_pack_start (GTK_BOX (tab_widget), label, FALSE, FALSE, 0);
gtk_widget_show (label);
break;
case GIMP_TAB_STYLE_UNDEFINED:
case GIMP_TAB_STYLE_AUTOMATIC:
g_warning ("Tab style error, unexpected code path taken, fix!");
break;
}
return tab_widget;
......@@ -946,6 +953,22 @@ gimp_dockable_get_tab_style (GimpDockable *dockable)
return dockable->p->tab_style;
}
/**
* gimp_dockable_get_actual_tab_style:
* @dockable:
*
* Get actual tab style, i.e. never "automatic". This state should
* actually be hold on a per-dockbook basis, but at this point that
* feels like over-engineering...
**/
GimpTabStyle
gimp_dockable_get_actual_tab_style (GimpDockable *dockable)
{
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), -1);
return dockable->p->actual_tab_style;
}
const gchar *
gimp_dockable_get_name (GimpDockable *dockable)
{
......@@ -1072,6 +1095,39 @@ gimp_dockable_set_tab_style (GimpDockable *dockable,
g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
dockable->p->tab_style = gimp_dockable_convert_tab_style (dockable, tab_style);
if (tab_style == GIMP_TAB_STYLE_AUTOMATIC)
gimp_dockable_set_actual_tab_style (dockable, GIMP_TAB_STYLE_UNDEFINED);
else
gimp_dockable_set_actual_tab_style (dockable, tab_style);
if (dockable->p->dockbook)
gimp_dockbook_update_auto_tab_style (dockable->p->dockbook);
}
/**
* gimp_dockable_set_actual_tab_style:
* @dockable:
* @tab_style:
*
* Sets actual tab style, meant for those that decides what
* "automatic" tab style means.
*
* Returns: %TRUE if changed, %FALSE otherwise.
**/
gboolean
gimp_dockable_set_actual_tab_style (GimpDockable *dockable,
GimpTabStyle tab_style)
{
GimpTabStyle new_tab_style = gimp_dockable_convert_tab_style (dockable, tab_style);
GimpTabStyle old_tab_style = dockable->p->actual_tab_style;
g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
g_return_val_if_fail (tab_style != GIMP_TAB_STYLE_AUTOMATIC, FALSE);
dockable->p->actual_tab_style = new_tab_style;
return new_tab_style != old_tab_style;
}
GtkWidget *
......
......@@ -88,6 +88,9 @@ gboolean gimp_dockable_is_locked (GimpDockable *dockable)
void gimp_dockable_set_tab_style (GimpDockable *dockable,
GimpTabStyle tab_style);
gboolean gimp_dockable_set_actual_tab_style (GimpDockable *dockable,
GimpTabStyle tab_style);
GimpTabStyle gimp_dockable_get_actual_tab_style (GimpDockable *dockable);
GtkWidget * gimp_dockable_create_tab_widget (GimpDockable *dockable,
GimpContext *context,
GimpTabStyle tab_style,
......
......@@ -47,12 +47,13 @@
#include "gimp-log.h"
#define DEFAULT_TAB_BORDER 0
#define DEFAULT_TAB_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define DND_WIDGET_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define MENU_WIDGET_ICON_SIZE GTK_ICON_SIZE_MENU
#define MENU_WIDGET_SPACING 4
#define TAB_HOVER_TIMEOUT 500
#define DEFAULT_TAB_BORDER 0
#define DEFAULT_TAB_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define DND_WIDGET_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define MENU_WIDGET_ICON_SIZE GTK_ICON_SIZE_MENU
#define MENU_WIDGET_SPACING 4
#define TAB_HOVER_TIMEOUT 500
#define GIMP_N_TAB_STYLE_CANDIDATES 3 /* G_N_ELEMENTS (gimp_tab_style_candidates); */
enum
......@@ -65,18 +66,34 @@ enum
struct _GimpDockbookPrivate
{
GimpDock *dock;
GimpUIManager *ui_manager;
GimpDock *dock;
GimpUIManager *ui_manager;
guint tab_hover_timeout;
GimpDockable *tab_hover_dockable;
guint tab_hover_timeout;
GimpDockable *tab_hover_dockable;
GimpPanedBox *drag_handler;
GimpPanedBox *drag_handler;
/* Cache for "what actual tab style for automatic styles can we use
* for a given dockbook width
*/
gint min_width_for_style[GIMP_N_TAB_STYLE_CANDIDATES];
/* We need a list separate from the GtkContainer children list,
* because we need to do calculations for all dockables before we
* can add a dockable as a child, namely automatic tab style
* calculations
*/
GList *dockables;
GtkWidget *menu_button;
};
static void gimp_dockbook_dispose (GObject *object);
static void gimp_dockbook_finalize (GObject *object);
static void gimp_dockbook_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gimp_dockbook_style_set (GtkWidget *widget,
GtkStyle *prev_style);
static void gimp_dockbook_drag_leave (GtkWidget *widget,
......@@ -98,7 +115,8 @@ static void gimp_dockbook_dockable_removed (GimpDockbook *d
GimpDockable *dockable);
static void gimp_dockbook_update_tabs (GimpDockbook *dockbook,
gboolean added);
static void gimp_dockbook_recreate_tab_widgets (GimpDockbook *dockbook);
static void gimp_dockbook_recreate_tab_widgets (GimpDockbook *dockbook,
gboolean only_auto);
static void gimp_dockbook_tab_drag_source_setup (GtkWidget *widget,
GimpDockable *dockable);
static void gimp_dockbook_tab_drag_begin (GtkWidget *widget,
......@@ -122,6 +140,10 @@ static gboolean gimp_dockbook_tab_drag_drop (GtkWidget *w
gint x,
gint y,
guint time);
static GimpTabStyle gimp_dockbook_tab_style_to_prefered (GimpTabStyle tab_style,
GimpDockable *dockable);
static void gimp_dockbook_refresh_tab_layout_lut (GimpDockbook *dockbook);
static void gimp_dockbook_update_automatic_tab_style (GimpDockbook *dockbook);
static GtkWidget * gimp_dockable_create_event_box_tab_widget (GimpDockable *dockable,
GimpContext *context,
GimpTabStyle tab_style,
......@@ -136,6 +158,7 @@ static void gimp_dockbook_tab_locked_notify (GimpDockable *d
GimpDockbook *dockbook);
static void gimp_dockbook_help_func (const gchar *help_id,
gpointer help_data);
static const gchar *gimp_dockbook_get_tab_style_name (GimpTabStyle tab_style);
G_DEFINE_TYPE (GimpDockbook, gimp_dockbook, GTK_TYPE_NOTEBOOK)
......@@ -146,6 +169,15 @@ static guint dockbook_signals[LAST_SIGNAL] = { 0 };
static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
/* List of candidates for the automatic style, starting with the
* biggest first
*/
static GimpTabStyle gimp_tab_style_candidates[] = {
GIMP_TAB_STYLE_PREVIEW_BLURB,
GIMP_TAB_STYLE_PREVIEW_NAME,
GIMP_TAB_STYLE_PREVIEW,
};
static void
gimp_dockbook_class_init (GimpDockbookClass *klass)
......@@ -153,6 +185,9 @@ gimp_dockbook_class_init (GimpDockbookClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
if (G_N_ELEMENTS (gimp_tab_style_candidates) != GIMP_N_TAB_STYLE_CANDIDATES)
g_error ("Update GIMP_N_TAB_STYLE_CANDIDATES");
dockbook_signals[DOCKABLE_ADDED] =
g_signal_new ("dockable-added",
G_TYPE_FROM_CLASS (klass),
......@@ -186,10 +221,11 @@ gimp_dockbook_class_init (GimpDockbookClass *klass)
object_class->dispose = gimp_dockbook_dispose;
object_class->finalize = gimp_dockbook_finalize;
widget_class->style_set = gimp_dockbook_style_set;
widget_class->drag_leave = gimp_dockbook_drag_leave;
widget_class->drag_motion = gimp_dockbook_drag_motion;
widget_class->drag_drop = gimp_dockbook_drag_drop;
widget_class->size_allocate = gimp_dockbook_size_allocate;
widget_class->style_set = gimp_dockbook_style_set;
widget_class->drag_leave = gimp_dockbook_drag_leave;
widget_class->drag_motion = gimp_dockbook_drag_motion;
widget_class->drag_drop = gimp_dockbook_drag_drop;
klass->dockable_added = gimp_dockbook_dockable_added;
klass->dockable_removed = gimp_dockbook_dockable_removed;
......@@ -254,6 +290,18 @@ gimp_dockbook_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_dockbook_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (widget);
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
/* Update tab styles, also recreates if changed */
gimp_dockbook_update_automatic_tab_style (dockbook);
}
static void
gimp_dockbook_style_set (GtkWidget *widget,
GtkStyle *prev_style)
......@@ -279,7 +327,8 @@ gimp_dockbook_style_set (GtkWidget *widget,
"tab-border", tab_border,
NULL);
gimp_dockbook_recreate_tab_widgets (GIMP_DOCKBOOK (widget));
gimp_dockbook_recreate_tab_widgets (GIMP_DOCKBOOK (widget),
FALSE /*only_auto*/);
}
static void
......@@ -382,6 +431,241 @@ gimp_dockbook_update_tabs (GimpDockbook *dockbook,
}
}
/**
* gimp_dockbook_get_dockable_tab_width:
* @dockable:
* @tab_style:
*
* Returns: Width of tab when the dockable is using the specified tab
* style.
**/
static gint
gimp_dockbook_get_dockable_tab_width (GimpDockbook *dockbook,
GimpDockable *dockable,
GimpTabStyle tab_style)
{
GtkRequisition dockable_request;
GtkWidget *tab_widget;
tab_widget =
gimp_dockable_create_event_box_tab_widget (dockable,
gimp_dock_get_context (dockbook->p->dock),
tab_style,
gimp_dockbook_get_tab_icon_size (dockbook));
/* So font-scale is applied. We can't apply styles without having a
* GdkScreen :(
*/
gimp_dock_temp_add (dockbook->p->dock, tab_widget);
gtk_widget_size_request (tab_widget, &dockable_request);
/* Also destroys the widget */
gimp_dock_temp_remove (dockbook->p->dock, tab_widget);
return dockable_request.width;
}
/**
* gimp_dockbook_tab_style_to_prefered:
* @tab_style:
* @dockable:
*
* The list of tab styles to try in automatic mode only consists of
* preview styles. For some dockables, like the tool options dockable,
* we rather want to use the icon tab styles for the automatic
* mode. This function is used to convert tab styles for such
* dockables.
*
* Returns: An icon tab style if the dockable prefers icon tab styles
* in automatic mode.
**/
static GimpTabStyle
gimp_dockbook_tab_style_to_prefered (GimpTabStyle tab_style,
GimpDockable *dockable)
{
GimpDocked *docked = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (dockable)));
if (gimp_docked_get_prefer_icon (docked))
tab_style = gimp_preview_tab_style_to_icon (tab_style);
return tab_style;
}
/**
* gimp_dockbook_refresh_tab_layout_lut:
* @dockbook:
*
* For each given set of tab widgets, there is a fixed mapping between
* the width of the dockbook and the actual tab style to use for auto
* tab widgets. This function refreshes that look-up table.
**/
static void
gimp_dockbook_refresh_tab_layout_lut (GimpDockbook *dockbook)
{
GList *auto_dockables = NULL;
GList *iter = NULL;
gint fixed_tab_style_space = 0;
int i = 0;
/* Calculate space taken by dockables with fixed tab styles */
fixed_tab_style_space = 0;
for (iter = dockbook->p->dockables; iter; iter = g_list_next (iter))
{
GimpDockable *dockable = GIMP_DOCKABLE (iter->data);
GimpTabStyle tab_style = gimp_dockable_get_tab_style (dockable);
if (tab_style == GIMP_TAB_STYLE_AUTOMATIC)
auto_dockables = g_list_prepend (auto_dockables, dockable);
else
fixed_tab_style_space +=
gimp_dockbook_get_dockable_tab_width (dockbook,
dockable,
tab_style);
}
/* Calculate space taken with auto tab style for all candidates */
for (i = 0; i < GIMP_N_TAB_STYLE_CANDIDATES; i++)
{
gint size_with_candidate = 0;
GimpTabStyle candidate = gimp_tab_style_candidates[i];
for (iter = auto_dockables; iter; iter = g_list_next (iter))
{
GimpDockable *dockable = GIMP_DOCKABLE (iter->data);
GimpTabStyle style_to_use;
style_to_use = gimp_dockbook_tab_style_to_prefered (candidate,
dockable);
size_with_candidate +=
gimp_dockbook_get_dockable_tab_width (dockbook,
dockable,
style_to_use);
}
dockbook->p->min_width_for_style[i] =
fixed_tab_style_space + size_with_candidate;
GIMP_LOG (AUTO_TAB_STYLE, "Total tab space taken for auto tab style %s = %d",
gimp_dockbook_get_tab_style_name (candidate),
dockbook->p->min_width_for_style[i]);
}
g_list_free (auto_dockables);
}
/**
* gimp_dockbook_update_automatic_tab_style:
* @dockbook:
*
* Based on widget allocation, sets actual tab style for dockables
* with automatic tab styles. Takes care of recreating tab widgets if
* necessary.
**/
static void
gimp_dockbook_update_automatic_tab_style (GimpDockbook *dockbook)
{
GtkWidget *widget = GTK_WIDGET (dockbook);
gboolean changed = FALSE;
GList *iter = NULL;
GtkAllocation dockbook_allocation = { 0, };
GtkAllocation button_allocation = { 0, };
GimpTabStyle tab_style = 0;
int i = 0;
gint available_space = 0;
guint tab_hborder = 0;
gint xthickness = 0;
gint tab_curvature = 0;
gint focus_width = 0;
gint tab_overlap = 0;
gint tab_padding = 0;
gint border_loss = 0;
gint action_widget_size = 0;
xthickness = gtk_widget_get_style (widget)->xthickness;
g_object_get (widget,
"tab-hborder", &tab_hborder,
NULL);
gtk_widget_style_get (widget,
"tab-curvature", &tab_curvature,
"focus-line-width", &focus_width,
"tab-overlap", &tab_overlap,
NULL);
gtk_widget_get_allocation (dockbook->p->menu_button,
&button_allocation);
/* Calculate available space. Based on code in GTK+ internal
* functions gtk_notebook_size_request() and
* gtk_notebook_pages_allocate()
*/
gtk_widget_get_allocation (widget, &dockbook_allocation);
/* Border on both sides */
border_loss = gtk_container_get_border_width (GTK_CONTAINER (dockbook)) * 2;
/* Space taken by action widget */
action_widget_size = button_allocation.width + xthickness;
/* Space taken by the tabs but not the tab widgets themselves */
tab_padding = gtk_notebook_get_n_pages (GTK_NOTEBOOK (dockbook)) *
(2 * (xthickness + tab_curvature + focus_width + tab_hborder) -
tab_overlap);
available_space = dockbook_allocation.width
- border_loss
- action_widget_size
- tab_padding
- tab_overlap;
GIMP_LOG (AUTO_TAB_STYLE, "\n"
" available_space = %d where\n"
" dockbook_allocation.width = %d\n"
" border_loss = %d\n"
" action_widget_size = %d\n"
" tab_padding = %d\n"
" tab_overlap = %d\n",
available_space,
dockbook_allocation.width,
border_loss,
action_widget_size,
tab_padding,
tab_overlap);
/* Try all candidates, if we don't get any hit we still end up on
* the smallest style (which we always fall back to if we don't get
* a better match)
*/
for (i = 0; i < GIMP_N_TAB_STYLE_CANDIDATES; i++)
{
tab_style = gimp_tab_style_candidates[i];
if (available_space > dockbook->p->min_width_for_style[i])
{
GIMP_LOG (AUTO_TAB_STYLE, "Choosing tab style %s",
gimp_dockbook_get_tab_style_name (tab_style));
break;
}
}
for (iter = dockbook->p->dockables; iter; iter = g_list_next (iter))
{
GimpDockable *dockable = GIMP_DOCKABLE (iter->data);
GimpTabStyle actual_tab_style = tab_style;
if (gimp_dockable_get_tab_style (dockable) != GIMP_TAB_STYLE_AUTOMATIC)
continue;
actual_tab_style = gimp_dockbook_tab_style_to_prefered (tab_style,
dockable);
if (gimp_dockable_set_actual_tab_style (dockable, actual_tab_style))
changed = TRUE;
}
if (changed)
gimp_dockbook_recreate_tab_widgets (dockbook,
TRUE /*only_auto*/);
}
GtkWidget *
gimp_dockbook_new (GimpMenuFactory *menu_factory)
{
......@@ -443,6 +727,16 @@ gimp_dockbook_add (GimpDockbook *dockbook,
GIMP_LOG (DND, "Adding GimpDockable %p to GimpDockbook %p", dockable, dockbook);
/* Add to internal list before doing automatic tab style
* calculations
*/
dockbook->p->dockables = g_list_insert (dockbook->p->dockables,
dockable,
position);
gimp_dockbook_update_auto_tab_style (dockbook);
/* Create the new tab widget, it will get the correct tab style now */
tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
g_return_if_fail (GTK_IS_WIDGET (tab_widget));
......@@ -515,11 +809,15 @@ gimp_dockbook_remove (GimpDockbook *dockbook,
gimp_dockable_set_context (dockable, NULL);
gtk_container_remove (GTK_CONTAINER (dockbook), GTK_WIDGET (dockable));
dockbook->p->dockables = g_list_remove (dockbook->p->dockables,
dockable);
g_signal_emit (dockbook, dockbook_signals[DOCKABLE_REMOVED], 0, dockable);
g_object_unref (dockable);
gimp_dockbook_update_auto_tab_style (dockbook);
children = gtk_container_get_children (GTK_CONTAINER (dockbook));
if (! g_list_length (children))
......@@ -565,7 +863,7 @@ gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
tab_widget =
gimp_dockable_create_event_box_tab_widget (dockable,
gimp_dock_get_context (dockbook->p->dock),
gimp_dockable_get_tab_style (dockable),
gimp_dockable_get_actual_tab_style (dockable),
gimp_dockbook_get_tab_icon_size (dockbook));