* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "gtkdnd.h"
#include "gtkbuildable.h"
#include "gtktypebuiltins.h"
+#include "gtkwidgetpath.h"
+#include "gtkwidgetprivate.h"
#include "a11y/gtknotebookaccessible.h"
guint dnd_timer;
guint switch_tab_timer;
-
- guint16 tab_hborder;
- guint16 tab_vborder;
+ GList *switch_tab;
guint32 timer;
guint32 timestamp;
/*** GtkNotebook Private Functions ***/
static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
+static void gtk_notebook_redraw_tabs_junction (GtkNotebook *notebook);
static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
static void gtk_notebook_real_remove (GtkNotebook *notebook,
GList *list);
static void gtk_notebook_draw_tab (GtkNotebook *notebook,
GtkNotebookPage *page,
cairo_t *cr,
- GtkRegionFlags flags);
+ gboolean use_flags);
static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
cairo_t *cr,
GtkNotebookArrow arrow);
* a notebook where the tab will be attached. It is also
* responsible for moving/resizing the window and adding the
* necessary properties to the notebook (e.g. the
- * #GtkNotebook:group ).
+ * #GtkNotebook:group-name ).
*
* Returns: (transfer none): a #GtkNotebook that @page should be
* added to, or %NULL.
priv->event_window = NULL;
priv->menu = NULL;
- priv->tab_hborder = 2;
- priv->tab_vborder = 2;
-
priv->show_tabs = TRUE;
priv->show_border = TRUE;
priv->tab_pos = GTK_POS_TOP;
* gtk_notebook_drag_data_get
* gtk_notebook_drag_data_received
*/
+static void
+remove_switch_tab_timer (GtkNotebook *notebook)
+{
+ GtkNotebookPrivate *priv = notebook->priv;
+
+ if (priv->switch_tab_timer)
+ {
+ g_source_remove (priv->switch_tab_timer);
+ priv->switch_tab_timer = 0;
+ }
+}
+
static void
gtk_notebook_destroy (GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
+ if (priv->action_widget[GTK_PACK_START])
+ {
+ gtk_widget_unparent (priv->action_widget[GTK_PACK_START]);
+ priv->action_widget[GTK_PACK_START] = NULL;
+ }
+
+ if (priv->action_widget[GTK_PACK_END])
+ {
+ gtk_widget_unparent (priv->action_widget[GTK_PACK_END]);
+ priv->action_widget[GTK_PACK_END] = NULL;
+ }
+
if (priv->menu)
gtk_notebook_popup_disable (notebook);
priv->source_targets = NULL;
}
- if (priv->switch_tab_timer)
- {
- g_source_remove (priv->switch_tab_timer);
- priv->switch_tab_timer = 0;
- }
+ remove_switch_tab_timer (notebook);
GTK_WIDGET_CLASS (gtk_notebook_parent_class)->destroy (widget);
}
priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
&attributes, attributes_mask);
- gdk_window_set_user_data (priv->event_window, notebook);
+ gtk_widget_register_window (widget, priv->event_window);
}
static void
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
- gdk_window_set_user_data (priv->event_window, NULL);
+ gtk_widget_unregister_window (widget, priv->event_window);
gdk_window_destroy (priv->event_window);
priv->event_window = NULL;
if (priv->drag_window)
{
- gdk_window_set_user_data (priv->drag_window, NULL);
+ gtk_widget_unregister_window (widget, priv->drag_window);
gdk_window_destroy (priv->drag_window);
priv->drag_window = NULL;
}
return flags;
}
+static GtkStateFlags
+notebook_tab_prepare_style_context (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ GtkStyleContext *context,
+ gboolean use_flags)
+{
+ gint tab_pos = get_effective_tab_pos (notebook);
+ GtkRegionFlags flags = 0;
+ GtkStateFlags state = gtk_style_context_get_state (context);
+
+ if (page != NULL &&
+ page == notebook->priv->cur_page)
+ state |= GTK_STATE_FLAG_ACTIVE;
+
+ gtk_style_context_set_state (context, state);
+
+ if (use_flags && (page != NULL))
+ flags = _gtk_notebook_get_tab_flags (notebook, page);
+
+ gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, flags);
+
+ switch (tab_pos)
+ {
+ case GTK_POS_TOP:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
+ break;
+ case GTK_POS_BOTTOM:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
+ break;
+ case GTK_POS_LEFT:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
+ break;
+ case GTK_POS_RIGHT:
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
+ break;
+ default:
+ break;
+ }
+
+ return state;
+}
+
static void
gtk_notebook_get_preferred_tabs_size (GtkNotebook *notebook,
GtkRequisition *requisition)
gint tab_overlap;
gint tab_curvature;
gint arrow_spacing;
+ gint initial_gap;
gint scroll_arrow_hlength;
gint scroll_arrow_vlength;
gtk_widget_style_get (widget,
"focus-line-width", &focus_width,
"focus-padding", &focus_pad,
+ "initial-gap", &initial_gap,
"tab-overlap", &tab_overlap,
"tab-curvature", &tab_curvature,
"arrow-spacing", &arrow_spacing,
if (gtk_widget_get_visible (page->child))
{
GtkBorder tab_padding;
+ GtkStateFlags state;
vis_pages++;
/* Get border/padding for tab */
gtk_style_context_save (context);
- gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
- _gtk_notebook_get_tab_flags (notebook, page));
- gtk_style_context_get_padding (context, 0, &tab_padding);
+ state = notebook_tab_prepare_style_context (notebook, page, context, TRUE);
+ gtk_style_context_get_padding (context, state, &tab_padding);
gtk_style_context_restore (context);
page->requisition.width = child_requisition.width +
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- page->requisition.height += 2 * priv->tab_vborder;
tab_height = MAX (tab_height, page->requisition.height);
tab_max = MAX (tab_max, page->requisition.width);
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
- page->requisition.width += 2 * priv->tab_hborder;
tab_width = MAX (tab_width, page->requisition.width);
tab_max = MAX (tab_max, page->requisition.height);
break;
tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_START].height);
tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_END].height);
- padding = 2 * (tab_curvature + priv->tab_hborder) - tab_overlap;
+ padding = 2 * tab_curvature - tab_overlap;
tab_max += padding;
while (children)
{
action_width += action_widget_requisition[ACTION_WIDGET_START].width;
action_width += action_widget_requisition[ACTION_WIDGET_END].width;
- requisition->width = tab_width + tab_overlap + action_width;
+ requisition->width = tab_width + tab_overlap + action_width + initial_gap;
requisition->height = tab_height;
break;
tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_START].width);
tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_END].width);
- padding = 2 * (tab_curvature + priv->tab_vborder) - tab_overlap;
+ padding = 2 * tab_curvature - tab_overlap;
tab_max += padding;
while (children)
action_height += action_widget_requisition[ACTION_WIDGET_START].height;
action_height += action_widget_requisition[ACTION_WIDGET_END].height;
- requisition->height = tab_height + tab_overlap + action_height;
+ requisition->height = tab_height + tab_overlap + action_height + initial_gap;
requisition->height = MAX (requisition->height, tab_max + tab_overlap);
gtk_widget_get_preferred_height_for_width (widget, size, minimum, natural);
}
+static void
+get_padding_and_border (GtkNotebook *notebook,
+ GtkBorder *border)
+{
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (notebook));
+ gtk_style_context_get_padding (context, 0, border);
+
+ if (notebook->priv->show_border || notebook->priv->show_tabs)
+ {
+ GtkBorder tmp;
+
+ gtk_style_context_get_border (context, 0, &tmp);
+ border->top += tmp.top;
+ border->right += tmp.right;
+ border->bottom += tmp.bottom;
+ border->left += tmp.left;
+ }
+}
+
static void
gtk_notebook_size_request (GtkWidget *widget,
GtkOrientation orientation,
if (priv->show_border || priv->show_tabs)
{
- GtkStyleContext *context;
GtkBorder notebook_padding;
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_padding (context, 0, ¬ebook_padding);
+ get_padding_and_border (notebook, ¬ebook_padding);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (priv->show_tabs || priv->show_border)
{
- GtkStyleContext *context;
GtkBorder padding;
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_padding (context, 0, &padding);
+ get_padding_and_border (notebook, &padding);
child_allocation.x += padding.left;
child_allocation.y += padding.top;
{
case GTK_POS_TOP:
child_allocation.y += priv->cur_page->requisition.height;
+ /* fall thru */
case GTK_POS_BOTTOM:
child_allocation.height =
MAX (1, child_allocation.height -
break;
case GTK_POS_LEFT:
child_allocation.x += priv->cur_page->requisition.width;
+ /* fall thru */
case GTK_POS_RIGHT:
child_allocation.width =
MAX (1, child_allocation.width -
if (priv->operation == DRAG_OPERATION_REORDER &&
gtk_cairo_should_draw_window (cr, priv->drag_window))
{
- GtkStyleContext *context;
- GdkRGBA bg_color;
-
cairo_save (cr);
gtk_cairo_transform_to_window (cr, widget, priv->drag_window);
- context = gtk_widget_get_style_context (widget);
-
- /* FIXME: This is a workaround to make tabs reordering work better
- * with engines with rounded tabs. If the drag window background
- * isn't set, the rounded corners would be black.
- *
- * Ideally, these corners should be made transparent, Either by using
- * ARGB visuals or shape windows.
- */
- gtk_style_context_get_background_color (context, 0, &bg_color);
- gdk_cairo_set_source_rgba (cr, &bg_color);
- cairo_paint (cr);
gtk_notebook_draw_tab (notebook,
priv->cur_page,
- cr, 0);
+ cr, FALSE);
cairo_restore (cr);
priv->button = button;
priv->click_child = arrow;
- if (button == 1)
+ if (button == GDK_BUTTON_PRIMARY)
{
gtk_notebook_do_arrow (notebook, arrow);
gtk_notebook_set_scroll_timer (notebook);
}
- else if (button == 2)
+ else if (button == GDK_BUTTON_MIDDLE)
gtk_notebook_page_select (notebook, TRUE);
- else if (button == 3)
+ else if (button == GDK_BUTTON_SECONDARY)
gtk_notebook_switch_focus_tab (notebook,
gtk_notebook_search_page (notebook,
NULL,
return TRUE;
}
- if (event->button != 1)
+ if (event->button != GDK_BUTTON_PRIMARY)
return FALSE;
priv->button = event->button;
{
GdkWindowAttr attributes;
guint attributes_mask;
+ GdkRGBA transparent = {0, 0, 0, 0};
attributes.x = page->allocation.x;
attributes.y = page->allocation.y;
priv->drag_window = gdk_window_new (gtk_widget_get_parent_window (widget),
&attributes,
attributes_mask);
- gdk_window_set_user_data (priv->drag_window, widget);
+ gtk_widget_register_window (widget, priv->drag_window);
+ gdk_window_set_background_rgba (priv->drag_window, &transparent);
}
g_object_ref (page->tab_label);
{
g_object_ref (page->tab_label);
- if (GTK_IS_WINDOW (parent))
- {
- /* parent widget is the drag window */
- gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
- }
+ if (GTK_IS_WINDOW (parent)) /* parent widget is the drag window */
+ gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
else
gtk_widget_unparent (page->tab_label);
{
if (priv->during_reorder)
{
- gint old_page_num, page_num;
+ gint old_page_num, page_num, i;
GList *element;
element = get_drop_position (notebook);
gtk_notebook_child_reordered (notebook, page);
if (priv->has_scrolled || old_page_num != page_num)
- g_signal_emit (notebook,
- notebook_signals[PAGE_REORDERED], 0,
- page->child, page_num);
+ {
+ for (element = priv->children, i = 0; element; element = element->next, i++)
+ {
+ if (MIN (old_page_num, page_num) <= i && i <= MAX (old_page_num, page_num))
+ gtk_widget_child_notify (((GtkNotebookPage *) element->data)->child, "position");
+ }
+ g_signal_emit (notebook,
+ notebook_signals[PAGE_REORDERED], 0,
+ page->child, page_num);
+ }
priv->has_scrolled = FALSE;
priv->during_reorder = FALSE;
priv->drag_window_y,
page->allocation.width,
page->allocation.height);
+
+ gtk_notebook_redraw_tabs_junction (notebook);
}
}
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
- gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, 0);
+ notebook_tab_prepare_style_context (GTK_NOTEBOOK (notebook), NULL, context, FALSE);
gtk_widget_get_preferred_size (widget,
&requisition, NULL);
{
GtkNotebook *notebook = GTK_NOTEBOOK (data);
GtkNotebookPrivate *priv = notebook->priv;
- GList *tab;
- gint x, y;
+ GList *switch_tab;
priv->switch_tab_timer = 0;
- x = priv->mouse_x;
- y = priv->mouse_y;
- if ((tab = get_tab_at_pos (notebook, x, y)) != NULL)
+ switch_tab = priv->switch_tab;
+ priv->switch_tab = NULL;
+
+ if (switch_tab)
{
/* FIXME: hack, we don't want the
* focus to move fom the source widget
*/
priv->child_has_focus = FALSE;
- gtk_notebook_switch_focus_tab (notebook, tab);
+ gtk_notebook_switch_focus_tab (notebook, switch_tab);
}
return FALSE;
GtkNotebookArrow arrow;
guint timeout;
GdkAtom target, tab_target;
+ GList *tab;
+ gboolean retval = FALSE;
gtk_widget_get_allocation (widget, &allocation);
priv->click_child = arrow;
gtk_notebook_set_scroll_timer (notebook);
gdk_drag_status (context, 0, time);
- return TRUE;
+
+ retval = TRUE;
+ goto out;
}
stop_scrolling (notebook);
GtkNotebook *source;
GtkWidget *source_child;
+ retval = TRUE;
+
source = GTK_NOTEBOOK (gtk_drag_get_source_widget (context));
source_child = source->priv->cur_page->child;
gtk_widget_is_ancestor (widget, source_child)))
{
gdk_drag_status (context, GDK_ACTION_MOVE, time);
- return TRUE;
+ goto out;
}
else
{
if (gtk_notebook_get_event_window_position (notebook, &position) &&
x >= position.x && x <= position.x + position.width &&
- y >= position.y && y <= position.y + position.height)
+ y >= position.y && y <= position.y + position.height &&
+ (tab = get_tab_at_pos (notebook, x, y)))
{
priv->mouse_x = x;
priv->mouse_y = y;
+ retval = TRUE;
+
+ if (tab != priv->switch_tab)
+ remove_switch_tab_timer (notebook);
+
+ priv->switch_tab = tab;
+
if (!priv->switch_tab_timer)
{
settings = gtk_widget_get_settings (widget);
}
else
{
- if (priv->switch_tab_timer)
- {
- g_source_remove (priv->switch_tab_timer);
- priv->switch_tab_timer = 0;
- }
+ remove_switch_tab_timer (notebook);
}
- return (target == tab_target) ? TRUE : FALSE;
+ out:
+ return retval;
}
static void
guint time)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkNotebookPrivate *priv = notebook->priv;
- if (priv->switch_tab_timer)
- {
- g_source_remove (priv->switch_tab_timer);
- priv->switch_tab_timer = 0;
- }
-
- stop_scrolling (GTK_NOTEBOOK (widget));
+ remove_switch_tab_timer (notebook);
+ stop_scrolling (notebook);
}
static gboolean
GtkNotebook *notebook = GTK_NOTEBOOK (container);
GtkNotebookPrivate *priv = notebook->priv;
GtkNotebookPage *page;
- GList *children;
+ GList *children, *list;
gint page_num = 0;
children = priv->children;
g_object_ref (widget);
+ list = children->next;
gtk_notebook_real_remove (notebook, children);
+ while (list)
+ {
+ gtk_widget_child_notify (((GtkNotebookPage *)list->data)->child, "position");
+ list = list->next;
+ }
+
g_signal_emit (notebook,
notebook_signals[PAGE_REMOVED],
0,
if (priv->show_tabs && priv->cur_page)
{
gtk_widget_grab_focus (GTK_WIDGET (notebook));
-
+ gtk_notebook_set_focus_child (GTK_CONTAINER (notebook), NULL);
gtk_notebook_switch_focus_tab (notebook,
g_list_find (priv->children,
priv->cur_page));
GtkNotebookPrivate *priv = notebook->priv;
GtkNotebookPage *page;
gint nchildren;
+ GList *list;
gtk_widget_freeze_child_notify (child);
gtk_widget_child_notify (child, "tab-fill");
gtk_widget_child_notify (child, "tab-label");
gtk_widget_child_notify (child, "menu-label");
- gtk_widget_child_notify (child, "position");
+
+ list = g_list_nth (priv->children, position);
+ while (list)
+ {
+ gtk_widget_child_notify (((GtkNotebookPage *)list->data)->child, "position");
+ list = list->next;
+ }
+
gtk_widget_thaw_child_notify (child);
/* The page-added handler might have reordered the pages, re-get the position */
GtkAllocation allocation;
GtkWidget *widget;
GtkNotebookPage *page;
- GtkStyleContext *context;
GdkRectangle redraw_rect;
gint border;
gint tab_pos = get_effective_tab_pos (notebook);
widget = GTK_WIDGET (notebook);
border = gtk_container_get_border_width (GTK_CONTAINER (notebook));
- if (!gtk_widget_get_mapped (widget) || !priv->first_tab)
+ if (!gtk_widget_get_mapped (widget) || !priv->cur_page)
return;
- page = priv->first_tab->data;
+ page = priv->cur_page;
redraw_rect.x = border;
redraw_rect.y = border;
gtk_widget_get_allocation (widget, &allocation);
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_padding (context, 0, &padding);
+ get_padding_and_border (notebook, &padding);
switch (tab_pos)
{
case GTK_POS_BOTTOM:
redraw_rect.y = allocation.height - border -
page->allocation.height - padding.bottom;
-
- if (page != priv->cur_page)
- redraw_rect.y -= padding.bottom;
/* fall through */
case GTK_POS_TOP:
redraw_rect.width = allocation.width - 2 * border;
redraw_rect.height = page->allocation.height + padding.top;
- if (page != priv->cur_page)
- redraw_rect.height += padding.top;
break;
case GTK_POS_RIGHT:
redraw_rect.x = allocation.width - border -
page->allocation.width - padding.right;
- if (page != priv->cur_page)
- redraw_rect.x -= padding.right;
/* fall through */
case GTK_POS_LEFT:
redraw_rect.width = page->allocation.width + padding.left;
redraw_rect.height = allocation.height - 2 * border;
- if (page != priv->cur_page)
- redraw_rect.width += padding.left;
+ break;
+ }
+
+ redraw_rect.x += allocation.x;
+ redraw_rect.y += allocation.y;
+
+ gdk_window_invalidate_rect (gtk_widget_get_window (widget),
+ &redraw_rect, TRUE);
+}
+
+static void
+gtk_notebook_redraw_tabs_junction (GtkNotebook *notebook)
+{
+ GtkNotebookPrivate *priv = notebook->priv;
+ GtkAllocation allocation;
+ GtkWidget *widget;
+ GtkNotebookPage *page;
+ GdkRectangle redraw_rect;
+ gint border;
+ gint tab_pos = get_effective_tab_pos (notebook);
+ GtkBorder padding;
+
+ widget = GTK_WIDGET (notebook);
+ border = gtk_container_get_border_width (GTK_CONTAINER (notebook));
+
+ if (!gtk_widget_get_mapped (widget) || !priv->cur_page)
+ return;
+
+ page = priv->cur_page;
+
+ redraw_rect.x = border;
+ redraw_rect.y = border;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ get_padding_and_border (notebook, &padding);
+
+ switch (tab_pos)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ redraw_rect.width = allocation.width - 2 * border;
+ if (tab_pos == GTK_POS_TOP)
+ {
+ redraw_rect.y = border + page->allocation.y +
+ page->allocation.height;
+ redraw_rect.height = padding.top;
+ }
+ else
+ {
+ redraw_rect.y = allocation.height - border -
+ page->allocation.height - padding.bottom;
+ redraw_rect.height = padding.bottom;
+ }
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ redraw_rect.height = allocation.height - 2 * border;
+
+ if (tab_pos == GTK_POS_LEFT)
+ {
+ redraw_rect.x = border + page->allocation.x + page->allocation.width;
+ redraw_rect.width = padding.left;
+ }
+ else
+ {
+ redraw_rect.x = allocation.width - border -
+ page->allocation.width - padding.right;
+ redraw_rect.width = padding.right;
+ }
break;
}
page->mnemonic_activate_signal = 0;
gtk_widget_set_state_flags (page->tab_label, 0, TRUE);
- gtk_widget_unparent (page->tab_label);
+ if (gtk_widget_get_window (page->tab_label) != gtk_widget_get_window (GTK_WIDGET (notebook)) ||
+ !NOTEBOOK_IS_TAB_LABEL_PARENT (notebook, page))
+ {
+ GtkWidget *parent;
+
+ /* we hit this condition during dnd of a detached tab */
+ parent = gtk_widget_get_parent (page->tab_label);
+ if (GTK_IS_WINDOW (parent))
+ gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
+ else
+ gtk_widget_unparent (page->tab_label);
+ }
+ else
+ {
+ gtk_widget_unparent (page->tab_label);
+ }
+
page->tab_label = NULL;
}
}
if (priv->detached_tab == list->data)
priv->detached_tab = NULL;
+ if (priv->switch_tab == list)
+ priv->switch_tab = NULL;
if (list == priv->first_tab)
priv->first_tab = next_list;
gboolean is_rtl;
gint tab_pos;
GtkStyleContext *context;
- GtkRegionFlags tab_flags;
notebook = GTK_NOTEBOOK (widget);
priv = notebook->priv;
!gtk_widget_get_mapped (page->tab_label))
continue;
- tab_flags = _gtk_notebook_get_tab_flags (notebook, page);
- gtk_notebook_draw_tab (notebook, page, cr, tab_flags);
+ gtk_notebook_draw_tab (notebook, page, cr, TRUE);
}
if (children != NULL)
for (children = other_order; children; children = children->next)
{
page = children->data;
-
- tab_flags = _gtk_notebook_get_tab_flags (notebook, page);
- gtk_notebook_draw_tab (notebook, page, cr, tab_flags);
+ gtk_notebook_draw_tab (notebook, page, cr, TRUE);
}
g_list_free (other_order);
}
if (priv->operation != DRAG_OPERATION_REORDER)
- {
- tab_flags = _gtk_notebook_get_tab_flags (notebook, priv->cur_page);
- gtk_notebook_draw_tab (notebook, priv->cur_page, cr, tab_flags);
- }
+ gtk_notebook_draw_tab (notebook, priv->cur_page, cr, TRUE);
}
static void
gtk_notebook_draw_tab (GtkNotebook *notebook,
GtkNotebookPage *page,
cairo_t *cr,
- GtkRegionFlags flags)
+ gboolean use_flags)
{
GtkNotebookPrivate *priv;
- GtkStateFlags state = 0;
GtkWidget *widget;
GtkStyleContext *context;
widget = GTK_WIDGET (notebook);
priv = notebook->priv;
- if (priv->cur_page == page)
- state = GTK_STATE_FLAG_ACTIVE;
-
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
- gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, flags);
- gtk_style_context_set_state (context, state);
+ notebook_tab_prepare_style_context (notebook, page, context, use_flags);
gtk_render_extension (context, cr,
page->allocation.x,
widget = GTK_WIDGET (notebook);
context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
"scroll-arrow-vlength", &scroll_arrow_vlength,
NULL);
- if (priv->in_child == nbarrow)
+ if (priv->focus_tab &&
+ !gtk_notebook_search_page (notebook, priv->focus_tab,
+ left ? STEP_PREV : STEP_NEXT, TRUE))
+ {
+ state |= GTK_STATE_FLAG_INSENSITIVE;
+ }
+ else if (priv->in_child == nbarrow)
{
state |= GTK_STATE_FLAG_PRELIGHT;
if (priv->click_child == nbarrow)
state |= GTK_STATE_FLAG_ACTIVE;
}
- else
- state = gtk_widget_get_state_flags (widget);
-
- if (priv->focus_tab &&
- !gtk_notebook_search_page (notebook, priv->focus_tab,
- left ? STEP_PREV : STEP_NEXT, TRUE))
- state = GTK_STATE_FLAG_INSENSITIVE;
if (priv->tab_pos == GTK_POS_LEFT ||
priv->tab_pos == GTK_POS_RIGHT)
GtkNotebookPrivate *priv = notebook->priv;
GtkAllocation allocation, action_allocation;
GtkWidget *widget;
- GtkStyleContext *context;
GList *children;
gint tab_pos = get_effective_tab_pos (notebook);
gint tab_overlap;
children = priv->children;
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
- context = gtk_widget_get_style_context (widget);
-
gtk_widget_style_get (GTK_WIDGET (notebook),
"arrow-spacing", &arrow_spacing,
"scroll-arrow-hlength", &scroll_arrow_hlength,
NULL);
border_width = gtk_container_get_border_width (GTK_CONTAINER (notebook));
- gtk_style_context_get_padding (context, 0, &padding);
+ get_padding_and_border (notebook, &padding);
gtk_widget_get_allocation (widget, &allocation);
- allocation.x += initial_gap;
- allocation.width -= 2 * initial_gap;
-
switch (tab_pos)
{
case GTK_POS_TOP:
break;
}
+ *min += initial_gap;
+ *max -= (2 * initial_gap);
+
if (!priv->scrollable)
*show_arrows = FALSE;
else
gboolean gap_left, packing_changed;
GtkAllocation child_allocation = { 0, };
GtkOrientation tab_expand_orientation;
- GtkBorder padding;
widget = GTK_WIDGET (notebook);
container = GTK_CONTAINER (notebook);
else
tab_expand_orientation = GTK_ORIENTATION_VERTICAL;
- gtk_style_context_save (context);
-
while (*children && *children != last_child)
{
page = (*children)->data;
- gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
- _gtk_notebook_get_tab_flags (notebook, page));
- gtk_style_context_get_padding (context, 0, &padding);
-
if (direction == STEP_NEXT)
*children = gtk_notebook_search_page (notebook, *children, direction, TRUE);
else
if (page != priv->cur_page)
{
+ GtkBorder active_padding, normal_padding, padding;
+
+ /* The active tab is by definition at least the same height as the inactive one.
+ * The padding we're building is the offset between the two tab states,
+ * so in case the style specifies normal_padding > active_padding we
+ * remove the offset and draw them with the same height.
+ * Note that the padding will still be applied to the tab content though,
+ * see gtk_notebook_page_allocate().
+ */
+ gtk_style_context_save (context);
+ notebook_tab_prepare_style_context (notebook, page, context, TRUE);
+
+ gtk_style_context_get_padding (context, GTK_STATE_FLAG_ACTIVE, &active_padding);
+ gtk_style_context_get_padding (context, GTK_STATE_FLAG_NORMAL, &normal_padding);
+
+ gtk_style_context_restore (context);
+
+ padding.top = MAX (0, active_padding.top - normal_padding.top);
+ padding.right = MAX (0, active_padding.right - normal_padding.right);
+ padding.bottom = MAX (0, active_padding.bottom - normal_padding.bottom);
+ padding.left = MAX (0, active_padding.left - normal_padding.left);
+
switch (tab_pos)
{
case GTK_POS_TOP:
- page->allocation.y += padding.top;
- page->allocation.height = MAX (1, page->allocation.height - padding.top);
+ page->allocation.y += padding.top + padding.bottom;
+ page->allocation.height = MAX (1, page->allocation.height - padding.top - padding.bottom);
break;
case GTK_POS_BOTTOM:
- page->allocation.height = MAX (1, page->allocation.height - padding.bottom);
+ page->allocation.height = MAX (1, page->allocation.height - padding.top - padding.bottom);
break;
case GTK_POS_LEFT:
- page->allocation.x += padding.left;
- page->allocation.width = MAX (1, page->allocation.width - padding.left);
+ page->allocation.x += padding.left + padding.right;
+ page->allocation.width = MAX (1, page->allocation.width - padding.left - padding.right);
break;
case GTK_POS_RIGHT:
- page->allocation.width = MAX (1, page->allocation.width - padding.right);
+ page->allocation.width = MAX (1, page->allocation.width - padding.left - padding.right);
break;
}
}
gtk_widget_set_child_visible (page->tab_label, TRUE);
}
- gtk_style_context_restore (context);
-
/* Don't move the current tab past the last position during tabs reordering */
if (children &&
priv->operation == DRAG_OPERATION_REORDER &&
gboolean tab_allocation_changed;
gboolean was_visible = page->tab_allocated_visible;
GtkBorder tab_padding;
+ GtkStateFlags state;
if (!page->tab_label ||
!gtk_widget_get_visible (page->tab_label) ||
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
- gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
- _gtk_notebook_get_tab_flags (notebook, page));
+ state = notebook_tab_prepare_style_context (notebook, page, context, TRUE);
- gtk_style_context_get_padding (context, 0, &tab_padding);
+ gtk_style_context_get_padding (context, state, &tab_padding);
gtk_widget_get_preferred_size (page->tab_label, &tab_requisition, NULL);
gtk_widget_style_get (widget,
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- padding = tab_curvature + priv->tab_hborder + focus_width + focus_padding;
+ padding = tab_curvature + focus_width + focus_padding;
if (page->fill)
{
child_allocation.x = tab_padding.left + padding;
child_allocation.width = tab_requisition.width;
}
- child_allocation.y = priv->tab_vborder + page->allocation.y;
-
- if (tab_pos == GTK_POS_TOP)
- child_allocation.y += tab_padding.top + focus_width + focus_padding;
+ child_allocation.y =
+ page->allocation.y + tab_padding.top + focus_width + focus_padding;
child_allocation.height = MAX (1, (page->allocation.height -
tab_padding.top - tab_padding.bottom -
- 2 * (priv->tab_vborder + focus_width + focus_padding)));
+ 2 * (focus_width + focus_padding)));
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
- padding = tab_curvature + priv->tab_vborder + focus_width + focus_padding;
+ padding = tab_curvature + focus_width + focus_padding;
if (page->fill)
{
child_allocation.y = tab_padding.top + padding;
child_allocation.height = tab_requisition.height;
}
- child_allocation.x = priv->tab_hborder + page->allocation.x;
-
- if (tab_pos == GTK_POS_LEFT)
- child_allocation.x += tab_padding.left + focus_width + focus_padding;
+ child_allocation.x =
+ page->allocation.x + tab_padding.left + focus_width + focus_padding;
child_allocation.width = MAX (1, (page->allocation.width -
tab_padding.left - tab_padding.right -
- 2 * (priv->tab_hborder + focus_width + focus_padding)));
+ 2 * (focus_width + focus_padding)));
break;
}
- if (page != priv->cur_page)
- {
- switch (tab_pos)
- {
- case GTK_POS_TOP:
- child_allocation.y -= tab_padding.top;
- child_allocation.height += tab_padding.top;
- break;
- case GTK_POS_BOTTOM:
- child_allocation.height += tab_padding.bottom;
- break;
- case GTK_POS_LEFT:
- child_allocation.x -= tab_padding.left;
- child_allocation.width += tab_padding.left;
- break;
- case GTK_POS_RIGHT:
- child_allocation.width += tab_padding.right;
- break;
- }
- }
-
gtk_widget_get_allocation (page->tab_label, &label_allocation);
tab_allocation_changed = (child_allocation.x != label_allocation.x ||
child_allocation.y != label_allocation.y ||
{
GtkRegionFlags current_flags;
- if (page == priv->cur_page)
- gtk_widget_set_state_flags (page->tab_label, GTK_STATE_FLAG_ACTIVE, FALSE);
- else
- gtk_widget_unset_state_flags (page->tab_label, GTK_STATE_FLAG_ACTIVE);
-
/* FIXME: We should store these flags somewhere instead of poking
* the widget's path */
if (!gtk_widget_path_iter_has_region (gtk_widget_get_path (page->tab_label),
GTK_STYLE_REGION_TAB,
¤t_flags)
|| current_flags != _gtk_notebook_get_tab_flags (notebook, page))
- gtk_widget_reset_style (page->tab_label);
+ _gtk_widget_invalidate_style_context (page->tab_label, GTK_CSS_CHANGE_PARENT_STATE);
}
}
}
}
gtk_notebook_update_tab_states (notebook);
+ gtk_notebook_pages_allocate (notebook);
+
gtk_widget_queue_resize (GTK_WIDGET (notebook));
g_object_notify (G_OBJECT (notebook), "page");
}
return;
page = priv->focus_tab->data;
- if (gtk_widget_get_mapped (page->tab_label))
- gtk_notebook_redraw_tabs (notebook);
- else
- gtk_notebook_pages_allocate (notebook);
-
gtk_notebook_switch_page (notebook, page);
}
* Return value: horizontal width of a tab border
*
* Since: 2.22
+ *
+ * Deprecated: 3.4: this function returns zero
*/
guint16
gtk_notebook_get_tab_hborder (GtkNotebook *notebook)
{
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
- return notebook->priv->tab_hborder;
+ return 0;
}
/**
* Return value: vertical width of a tab border
*
* Since: 2.22
+ *
+ * Deprecated: 3.4: this function returns zero
*/
guint16
gtk_notebook_get_tab_vborder (GtkNotebook *notebook)
{
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
- return notebook->priv->tab_vborder;
+ return 0;
}
GtkNotebookPage *page;
gint old_pos;
gint max_pos;
+ gint i;
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
g_return_if_fail (GTK_IS_WIDGET (child));
/* Move around the menu items if necessary */
gtk_notebook_child_reordered (notebook, page);
- gtk_widget_child_notify (child, "position");
+
+ for (list = priv->children, i = 0; list; list = list->next, i++)
+ {
+ if (MIN (old_pos, position) <= i && i <= MAX (old_pos, position))
+ gtk_widget_child_notify (((GtkNotebookPage *) list->data)->child, "position");
+ }
if (priv->show_tabs)
gtk_notebook_pages_allocate (notebook);