* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include <config.h>
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#undef GTK_DISABLE_DEPRECATED
+
#include "gtknotebook.h"
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtklabel.h"
-#include <gdk/gdkkeysyms.h>
-#include <stdio.h>
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkbindings.h"
#include "gtkprivate.h"
#include "gtkdnd.h"
+#include "gtkbuildable.h"
+
#include "gtkalias.h"
#define SCROLL_DELAY_FACTOR 5
PAGE_REORDERED,
PAGE_REMOVED,
PAGE_ADDED,
+ CREATE_WINDOW,
LAST_SIGNAL
};
CHILD_PROP_DETACHABLE
};
+enum {
+ ACTION_WIDGET_START,
+ ACTION_WIDGET_END,
+ N_ACTION_WIDGETS
+};
+
#define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
/* some useful defines for calculating coords */
guint reorderable : 1;
guint detachable : 1;
+ /* if true, the tab label was visible on last allocation; we track this so
+ * that we know to redraw the tab area if a tab label was hidden then shown
+ * without changing position */
+ guint tab_allocated_visible : 1;
+
GtkRequisition requisition;
GtkAllocation allocation;
guint32 timestamp;
+ GtkWidget *action_widget[N_ACTION_WIDGETS];
+
guint during_reorder : 1;
guint during_detach : 1;
guint has_scrolled : 1;
static gboolean gtk_notebook_reorder_tab (GtkNotebook *notebook,
GtkDirectionType direction_type,
gboolean move_to_last);
+static void gtk_notebook_remove_tab_label (GtkNotebook *notebook,
+ GtkNotebookPage *page);
/*** GtkObject Methods ***/
static void gtk_notebook_destroy (GtkObject *object);
GtkWidget *menu_label,
gint position);
+static GtkNotebook *gtk_notebook_create_window (GtkNotebook *notebook,
+ GtkWidget *page,
+ gint x,
+ gint y);
+
/*** GtkNotebook Private Functions ***/
static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
GList *list,
gint direction,
gboolean find_visible);
+static void gtk_notebook_child_reordered (GtkNotebook *notebook,
+ GtkNotebookPage *page);
/*** GtkNotebook Drawing Functions ***/
static void gtk_notebook_paint (GtkWidget *widget,
/*** GtkNotebook Size Allocate Functions ***/
static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
-static void gtk_notebook_page_allocate (GtkNotebook *notebook,
+static gboolean gtk_notebook_page_allocate (GtkNotebook *notebook,
GtkNotebookPage *page);
static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
GList *start,
/*** GtkNotebook Page Switch Functions ***/
static void gtk_notebook_switch_page (GtkNotebook *notebook,
- GtkNotebookPage *page,
- gint page_num);
+ GtkNotebookPage *page);
static gint gtk_notebook_page_select (GtkNotebook *notebook,
gboolean move_focus);
static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
gint x,
gint y);
+/* GtkBuildable */
+static void gtk_notebook_buildable_init (GtkBuildableIface *iface);
+static void gtk_notebook_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type);
static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
static gpointer window_creation_hook_data;
static guint notebook_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_notebook_buildable_init))
static void
add_tab_bindings (GtkBindingSet *binding_set,
G_TYPE_BOOLEAN, move_to_last);
}
+static gboolean
+gtk_object_handled_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy)
+{
+ gboolean continue_emission;
+ GObject *object;
+
+ object = g_value_get_object (handler_return);
+ g_value_set_object (return_accu, object);
+ continue_emission = !object;
+
+ return continue_emission;
+}
+
static void
gtk_notebook_class_init (GtkNotebookClass *class)
{
class->change_current_page = gtk_notebook_change_current_page;
class->move_focus_out = gtk_notebook_move_focus_out;
class->reorder_tab = gtk_notebook_reorder_tab;
+ class->create_window = gtk_notebook_create_window;
g_object_class_install_property (gobject_class,
PROP_PAGE,
g_param_spec_int ("page",
P_("Page"),
P_("The index of the current page"),
- 0,
+ -1,
G_MAXINT,
- 0,
+ -1,
GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TAB_POS,
G_MAXINT,
-1,
GTK_PARAM_READWRITE));
+
+ /**
+ * GtkNotebook:group:
+ *
+ * Group for tabs drag and drop.
+ *
+ * Since: 2.12
+ */
g_object_class_install_property (gobject_class,
PROP_GROUP,
g_param_spec_pointer ("group",
g_param_spec_boolean ("tab-expand",
P_("Tab expand"),
P_("Whether to expand the child's tab or not"),
- TRUE,
+ FALSE,
GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_TAB_FILL,
*/
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("arrow-spacing",
- _("Arrow spacing"),
- _("Scroll arrow spacing"),
+ P_("Arrow spacing"),
+ P_("Scroll arrow spacing"),
0,
G_MAXINT,
0,
GTK_PARAM_READABLE));
notebook_signals[SWITCH_PAGE] =
- g_signal_new (I_("switch_page"),
+ g_signal_new (I_("switch-page"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
G_TYPE_POINTER,
G_TYPE_UINT);
notebook_signals[FOCUS_TAB] =
- g_signal_new (I_("focus_tab"),
+ g_signal_new (I_("focus-tab"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
G_TYPE_BOOLEAN, 1,
GTK_TYPE_NOTEBOOK_TAB);
notebook_signals[SELECT_PAGE] =
- g_signal_new (I_("select_page"),
+ g_signal_new (I_("select-page"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, select_page),
G_TYPE_BOOLEAN, 1,
G_TYPE_BOOLEAN);
notebook_signals[CHANGE_CURRENT_PAGE] =
- g_signal_new (I_("change_current_page"),
+ g_signal_new (I_("change-current-page"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
G_TYPE_BOOLEAN, 1,
G_TYPE_INT);
notebook_signals[MOVE_FOCUS_OUT] =
- g_signal_new (I_("move_focus_out"),
+ g_signal_new (I_("move-focus-out"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
G_TYPE_NONE, 1,
GTK_TYPE_DIRECTION_TYPE);
notebook_signals[REORDER_TAB] =
- g_signal_new (I_("reorder_tab"),
+ g_signal_new (I_("reorder-tab"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
* Since: 2.10
**/
notebook_signals[PAGE_REORDERED] =
- g_signal_new (I_("page_reordered"),
+ g_signal_new (I_("page-reordered"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
* Since: 2.10
**/
notebook_signals[PAGE_REMOVED] =
- g_signal_new (I_("page_removed"),
+ g_signal_new (I_("page-removed"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
* Since: 2.10
**/
notebook_signals[PAGE_ADDED] =
- g_signal_new (I_("page_added"),
+ g_signal_new (I_("page-added"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
GTK_TYPE_WIDGET,
G_TYPE_UINT);
+ /**
+ * GtkNotebook::create-window:
+ * @notebook: the #GtkNotebook emitting the signal
+ * @page: the tab of @notebook that is being detached
+ * @x: the X coordinate where the drop happens
+ * @y: the Y coordinate where the drop happens
+ *
+ * The ::create-window signal is emitted when a detachable
+ * tab is dropped on the root window.
+ *
+ * A handler for this signal can create a window containing
+ * 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-id ).
+ *
+ * The default handler uses the global window creation hook,
+ * if one has been set with gtk_notebook_set_window_creation_hook().
+ *
+ * Returns: a #GtkNotebook that @page should be added to, or %NULL.
+ *
+ * Since: 2.12
+ */
+ notebook_signals[CREATE_WINDOW] =
+ g_signal_new (I_("create-window"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkNotebookClass, create_window),
+ gtk_object_handled_accumulator, NULL,
+ _gtk_marshal_OBJECT__OBJECT_INT_INT,
+ GTK_TYPE_NOTEBOOK, 3,
+ GTK_TYPE_WIDGET, G_TYPE_INT, G_TYPE_INT);
+
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
GDK_space, 0,
- "select_page", 1,
+ "select-page", 1,
G_TYPE_BOOLEAN, FALSE);
gtk_binding_entry_add_signal (binding_set,
GDK_KP_Space, 0,
- "select_page", 1,
+ "select-page", 1,
G_TYPE_BOOLEAN, FALSE);
gtk_binding_entry_add_signal (binding_set,
GDK_Home, 0,
- "focus_tab", 1,
+ "focus-tab", 1,
GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
gtk_binding_entry_add_signal (binding_set,
GDK_KP_Home, 0,
- "focus_tab", 1,
+ "focus-tab", 1,
GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
gtk_binding_entry_add_signal (binding_set,
GDK_End, 0,
- "focus_tab", 1,
+ "focus-tab", 1,
GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
gtk_binding_entry_add_signal (binding_set,
GDK_KP_End, 0,
- "focus_tab", 1,
+ "focus-tab", 1,
GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
gtk_binding_entry_add_signal (binding_set,
GDK_Page_Up, GDK_CONTROL_MASK,
- "change_current_page", 1,
+ "change-current-page", 1,
G_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set,
GDK_Page_Down, GDK_CONTROL_MASK,
- "change_current_page", 1,
+ "change-current-page", 1,
G_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set,
GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
- "change_current_page", 1,
+ "change-current-page", 1,
G_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set,
GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
- "change_current_page", 1,
+ "change-current-page", 1,
G_TYPE_INT, 1);
add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
}
+static void
+gtk_notebook_buildable_init (GtkBuildableIface *iface)
+{
+ iface->add_child = gtk_notebook_buildable_add_child;
+}
+
+static void
+gtk_notebook_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (buildable);
+
+ if (type && strcmp (type, "tab") == 0)
+ {
+ GtkWidget * page;
+
+ page = gtk_notebook_get_nth_page (notebook, -1);
+ /* To set the tab label widget, we must have already a child
+ * inside the tab container. */
+ g_assert (page != NULL);
+ gtk_notebook_set_tab_label (notebook, page, GTK_WIDGET (child));
+ }
+ else if (type && strcmp (type, "action-start") == 0)
+ {
+ gtk_notebook_set_action_widget (notebook, GTK_WIDGET (child), GTK_PACK_START);
+ }
+ else if (type && strcmp (type, "action-end") == 0)
+ {
+ gtk_notebook_set_action_widget (notebook, GTK_WIDGET (child), GTK_PACK_END);
+ }
+ else if (!type)
+ gtk_notebook_append_page (notebook, GTK_WIDGET (child), NULL);
+ else
+ GTK_BUILDER_WARN_INVALID_CHILD_TYPE (notebook, type);
+}
+
static gboolean
gtk_notebook_select_page (GtkNotebook *notebook,
gboolean move_focus)
}
if (current)
- gtk_notebook_switch_page (notebook, current->data, -1);
+ gtk_notebook_switch_page (notebook, current->data);
else
gtk_widget_error_bell (GTK_WIDGET (notebook));
* do this by setting a flag, then propagating the focus motion to the notebook.
*/
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
- if (!GTK_WIDGET_TOPLEVEL (toplevel))
+ if (!gtk_widget_is_toplevel (toplevel))
return;
g_object_ref (notebook);
notebook->focus_out = TRUE;
- g_signal_emit_by_name (toplevel, "move_focus", direction_type);
+ g_signal_emit_by_name (toplevel, "move-focus", direction_type);
notebook->focus_out = FALSE;
g_object_unref (notebook);
{
GtkNotebook *notebook = GTK_NOTEBOOK (object);
GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
-
+
if (notebook->menu)
gtk_notebook_popup_disable (notebook);
gtk_notebook_set_group (notebook, g_value_get_pointer (value));
break;
default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
gtk_notebook_get_event_window_position (GtkNotebook *notebook,
GdkRectangle *rectangle)
{
+ GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
GtkWidget *widget = GTK_WIDGET (notebook);
gint border_width = GTK_CONTAINER (notebook)->border_width;
GtkNotebookPage *visible_page = NULL;
GList *tmp_list;
gint tab_pos = get_effective_tab_pos (notebook);
+ gboolean is_rtl;
+ gint i;
for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
{
{
if (rectangle)
{
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
rectangle->x = widget->allocation.x + border_width;
rectangle->y = widget->allocation.y + border_width;
-
+
switch (tab_pos)
{
case GTK_POS_TOP:
rectangle->height = visible_page->requisition.height;
if (tab_pos == GTK_POS_BOTTOM)
rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
+
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i] &&
+ GTK_WIDGET_VISIBLE (priv->action_widget[i]))
+ {
+ rectangle->width -= priv->action_widget[i]->allocation.width;
+ if ((!is_rtl && i == ACTION_WIDGET_START) ||
+ (is_rtl && i == ACTION_WIDGET_END))
+ rectangle->x += priv->action_widget[i]->allocation.width;
+ }
+ }
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
rectangle->height = widget->allocation.height - 2 * border_width;
if (tab_pos == GTK_POS_RIGHT)
rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
- break;
+
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i] &&
+ GTK_WIDGET_VISIBLE (priv->action_widget[i]))
+ {
+ rectangle->height -= priv->action_widget[i]->allocation.height;
+
+ if (i == ACTION_WIDGET_START)
+ rectangle->y += priv->action_widget[i]->allocation.height;
+ }
+ }
+ break;
}
}
static void
gtk_notebook_map (GtkWidget *widget)
{
+ GtkNotebookPrivate *priv;
GtkNotebook *notebook;
GtkNotebookPage *page;
GList *children;
-
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ gint i;
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
notebook = GTK_NOTEBOOK (widget);
+ priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
if (notebook->cur_page &&
GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
!GTK_WIDGET_MAPPED (notebook->cur_page->child))
gtk_widget_map (notebook->cur_page->child);
+ if (notebook->show_tabs)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ if (priv->action_widget[i] &&
+ GTK_WIDGET_VISIBLE (priv->action_widget[i]) &&
+ !GTK_WIDGET_MAPPED (priv->action_widget[i]))
+ gtk_widget_map (priv->action_widget[i]);
+ }
+ }
+
if (notebook->scrollable)
gtk_notebook_pages_allocate (notebook);
else
static void
gtk_notebook_unmap (GtkWidget *widget)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
-
stop_scrolling (GTK_NOTEBOOK (widget));
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
gint attributes_mask;
GdkRectangle event_window_pos;
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
-
notebook = GTK_NOTEBOOK (widget);
GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
GtkNotebook *notebook;
GtkNotebookPrivate *priv;
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
-
notebook = GTK_NOTEBOOK (widget);
priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
priv->drag_window = NULL;
}
- if (GTK_WIDGET_CLASS (gtk_notebook_parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (gtk_notebook_parent_class)->unrealize) (widget);
+ GTK_WIDGET_CLASS (gtk_notebook_parent_class)->unrealize (widget);
}
static void
gtk_notebook_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
+ GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPage *page;
GList *children;
GtkRequisition child_requisition;
+ GtkRequisition action_widget_requisition[2] = { { 0 }, { 0 } };
gboolean switch_page = FALSE;
gint vis_pages;
gint focus_width;
gint tab_height = 0;
gint tab_max = 0;
gint padding;
+ gint i;
for (children = notebook->children; children;
children = children->next)
if (vis_pages)
{
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i])
+ {
+ gtk_widget_size_request (priv->action_widget[i], &action_widget_requisition[i]);
+ action_widget_requisition[i].width += widget->style->xthickness;
+ action_widget_requisition[i].height += widget->style->ythickness;
+ }
+ }
+
switch (notebook->tab_pos)
{
case GTK_POS_TOP:
widget->requisition.width < tab_width)
tab_height = MAX (tab_height, scroll_arrow_hlength);
+ 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 + focus_width +
notebook->tab_hborder) - tab_overlap;
tab_max += padding;
widget->requisition.width = MAX (widget->requisition.width,
tab_width + tab_overlap);
+ widget->requisition.width += action_widget_requisition[ACTION_WIDGET_START].width;
+ widget->requisition.width += action_widget_requisition[ACTION_WIDGET_END].width;
widget->requisition.height += tab_height;
break;
case GTK_POS_LEFT:
tab_width = MAX (tab_width,
arrow_spacing + 2 * scroll_arrow_vlength);
+ 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 + focus_width +
notebook->tab_vborder) - tab_overlap;
tab_max += padding;
if (!GTK_WIDGET_VISIBLE (page->child))
continue;
- page->requisition.width = tab_width;
+ page->requisition.width = tab_width;
if (notebook->homogeneous)
page->requisition.height = tab_max;
widget->requisition.height < tab_height)
tab_height = tab_max + (2 * scroll_arrow_vlength + arrow_spacing);
- widget->requisition.width += tab_width;
-
if (notebook->homogeneous && !notebook->scrollable)
widget->requisition.height =
MAX (widget->requisition.height,
widget->requisition.height = MAX (widget->requisition.height,
vis_pages * tab_max +
tab_overlap);
+
+ widget->requisition.height += action_widget_requisition[ACTION_WIDGET_START].height;
+ widget->requisition.height += action_widget_requisition[ACTION_WIDGET_END].height;
+ widget->requisition.width += tab_width;
break;
}
}
page = children->data;
if (GTK_WIDGET_VISIBLE (page->child))
{
- gtk_notebook_switch_page (notebook, page, -1);
+ gtk_notebook_switch_page (notebook, page);
break;
}
}
if (children)
{
notebook->first_tab = children;
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children));
}
}
}
gtk_notebook_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
+ GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
gint tab_pos = get_effective_tab_pos (notebook);
+ gboolean is_rtl;
+ gint focus_width;
+ gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
+
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
{
GtkNotebookPage *page;
GtkAllocation child_allocation;
GList *children;
+ gint i;
child_allocation.x = widget->allocation.x + border_width;
child_allocation.y = widget->allocation.y + border_width;
notebook->cur_page->requisition.width);
break;
}
+
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ GtkAllocation widget_allocation;
+
+ if (!priv->action_widget[i])
+ continue;
+
+ widget_allocation.x = widget->allocation.x + border_width;
+ widget_allocation.y = widget->allocation.y + border_width;
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+
+ switch (tab_pos)
+ {
+ case GTK_POS_BOTTOM:
+ widget_allocation.y +=
+ widget->allocation.height - 2 * border_width - notebook->cur_page->requisition.height;
+ /* fall through */
+ case GTK_POS_TOP:
+ widget_allocation.width = priv->action_widget[i]->requisition.width;
+ widget_allocation.height = notebook->cur_page->requisition.height - widget->style->ythickness;
+
+ if ((i == ACTION_WIDGET_START && is_rtl) ||
+ (i == ACTION_WIDGET_END && !is_rtl))
+ widget_allocation.x +=
+ widget->allocation.width - 2 * border_width -
+ priv->action_widget[i]->requisition.width;
+ if (tab_pos == GTK_POS_TOP) /* no fall through */
+ widget_allocation.y += 2 * focus_width;
+ break;
+ case GTK_POS_RIGHT:
+ widget_allocation.x +=
+ widget->allocation.width - 2 * border_width - notebook->cur_page->requisition.width;
+ /* fall through */
+ case GTK_POS_LEFT:
+ widget_allocation.height = priv->action_widget[i]->requisition.height;
+ widget_allocation.width = notebook->cur_page->requisition.width - widget->style->xthickness;
+
+ if (i == ACTION_WIDGET_END)
+ widget_allocation.y +=
+ widget->allocation.height - 2 * border_width -
+ priv->action_widget[i]->requisition.height;
+ if (tab_pos == GTK_POS_LEFT) /* no fall through */
+ widget_allocation.x += 2 * focus_width;
+ break;
+ }
+
+ gtk_widget_size_allocate (priv->action_widget[i], &widget_allocation);
+ }
}
}
{
GtkNotebook *notebook;
GtkNotebookPrivate *priv;
-
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ gint i;
notebook = GTK_NOTEBOOK (widget);
priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
if (event->window == priv->drag_window)
{
GdkRectangle area = { 0, };
+ cairo_t *cr;
+
+ /* 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.
+ */
+ cr = gdk_cairo_create (priv->drag_window);
+ gdk_cairo_set_source_color (cr, &widget->style->bg [GTK_STATE_NORMAL]);
+ cairo_paint (cr);
+ cairo_destroy (cr);
gdk_drawable_get_size (priv->drag_window,
&area.width, &area.height);
gtk_container_propagate_expose (GTK_CONTAINER (notebook),
notebook->cur_page->child,
event);
+ if (notebook->show_tabs)
+ {
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i] &&
+ GTK_WIDGET_DRAWABLE (priv->action_widget[i]))
+ gtk_container_propagate_expose (GTK_CONTAINER (notebook),
+ priv->action_widget[i], event);
+ }
+ }
}
return FALSE;
GtkNotebookArrow arrow)
{
GtkWidget *widget = GTK_WIDGET (notebook);
- GtkDirectionType dir;
gboolean is_rtl, left;
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
left ? STEP_PREV : STEP_NEXT,
TRUE))
{
- if (notebook->tab_pos == GTK_POS_LEFT ||
- notebook->tab_pos == GTK_POS_RIGHT)
- dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
- else
- dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
-
+ gtk_notebook_change_current_page (notebook, left ? -1 : 1);
gtk_widget_grab_focus (widget);
- gtk_widget_child_focus (widget, dir);
}
}
gtk_notebook_scroll (GtkWidget *widget,
GdkEventScroll *event)
{
+ GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-
- GtkWidget* child;
- GtkWidget* originator;
+ GtkWidget *child, *event_widget;
+ gint i;
if (!notebook->cur_page)
return FALSE;
child = notebook->cur_page->child;
- originator = gtk_get_event_widget ((GdkEvent *)event);
+ event_widget = gtk_get_event_widget ((GdkEvent *)event);
/* ignore scroll events from the content of the page */
- if (!originator || gtk_widget_is_ancestor (originator, child) || originator == child)
+ if (!event_widget || gtk_widget_is_ancestor (event_widget, child) || event_widget == child)
return FALSE;
-
+
+ /* nor from the action area */
+ for (i = 0; i < 2; i++)
+ {
+ if (event_widget == priv->action_widget[i] ||
+ gtk_widget_is_ancestor (event_widget, priv->action_widget[i]))
+ return FALSE;
+ }
+
switch (event->direction)
{
case GDK_SCROLL_RIGHT:
priv->during_reorder = FALSE;
priv->pressed_button = event->button;
- gdk_window_get_pointer (widget->window,
- &priv->mouse_x,
- &priv->mouse_y,
- NULL);
+ priv->mouse_x = x;
+ priv->mouse_y = y;
priv->drag_begin_x = priv->mouse_x;
priv->drag_begin_y = priv->mouse_y;
else
gtk_widget_unparent (page->tab_label);
- gtk_widget_set_parent_window (page->tab_label, widget->window);
gtk_widget_set_parent (page->tab_label, widget);
g_object_unref (page->tab_label);
}
else
page = notebook->cur_page;
- if (!page)
+ if (!page || !page->tab_label)
return;
priv->pressed_button = -1;
element = get_drop_position (notebook, page->pack);
old_page_num = g_list_position (notebook->children, notebook->focus_tab);
page_num = reorder_tab (notebook, element, notebook->focus_tab);
-
+ gtk_notebook_child_reordered (notebook, page);
+
if (priv->has_scrolled || old_page_num != page_num)
g_signal_emit (notebook,
notebook_signals[PAGE_REORDERED], 0,
GtkNotebookPrivate *priv;
GtkNotebookPage *page;
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
if (event->type != GDK_BUTTON_RELEASE)
return FALSE;
get_pointer_position (GtkNotebook *notebook)
{
GtkWidget *widget = (GtkWidget *) notebook;
- GtkContainer *container = (GtkContainer *) notebook;
GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
+ gint wx, wy, width, height;
gboolean is_rtl;
if (!notebook->scrollable)
return POINTER_BETWEEN;
+ gdk_window_get_position (notebook->event_window, &wx, &wy);
+ gdk_drawable_get_size (GDK_DRAWABLE (notebook->event_window), &width, &height);
+
if (notebook->tab_pos == GTK_POS_TOP ||
notebook->tab_pos == GTK_POS_BOTTOM)
{
gint x;
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
- x = priv->mouse_x - widget->allocation.x;
+ x = priv->mouse_x - wx;
- if (x > widget->allocation.width - 2 * container->border_width - SCROLL_THRESHOLD)
+ if (x > width - SCROLL_THRESHOLD)
return (is_rtl) ? POINTER_BEFORE : POINTER_AFTER;
- else if (x < SCROLL_THRESHOLD + container->border_width)
+ else if (x < SCROLL_THRESHOLD)
return (is_rtl) ? POINTER_AFTER : POINTER_BEFORE;
else
return POINTER_BETWEEN;
{
gint y;
- y = priv->mouse_y - widget->allocation.y;
- if (y > widget->allocation.height - 2 * container->border_width - SCROLL_THRESHOLD)
+ y = priv->mouse_y - wy;
+ if (y > height - SCROLL_THRESHOLD)
return POINTER_AFTER;
- else if (y < SCROLL_THRESHOLD + container->border_width)
+ else if (y < SCROLL_THRESHOLD)
return POINTER_BEFORE;
else
return POINTER_BETWEEN;
GtkNotebookPointerPosition pointer_position;
GtkSettings *settings;
guint timeout;
+ gint x_win, y_win;
page = notebook->cur_page;
return FALSE;
priv->timestamp = event->time;
- gdk_window_get_pointer (widget->window,
- &priv->mouse_x,
- &priv->mouse_y,
- NULL);
+
+ /* While animating the move, event->x is relative to the flying tab
+ * (priv->drag_window has a pointer grab), but we need coordinates relative to
+ * the notebook widget.
+ */
+ gdk_window_get_origin (widget->window, &x_win, &y_win);
+ priv->mouse_x = event->x_root - x_win;
+ priv->mouse_y = event->y_root - y_win;
arrow = gtk_notebook_get_arrow (notebook, priv->mouse_x, priv->mouse_y);
if (arrow != notebook->in_child)
gtk_notebook_focus_in (GtkWidget *widget,
GdkEventFocus *event)
{
- GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
-
gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
return FALSE;
notebook->has_before_next = has_before_next;
notebook->has_after_previous = has_after_previous;
notebook->has_after_next = has_after_next;
-
- (* GTK_WIDGET_CLASS (gtk_notebook_parent_class)->style_set) (widget, previous);
+
+ GTK_WIDGET_CLASS (gtk_notebook_parent_class)->style_set (widget, previous);
}
static gboolean
gtk_widget_unparent (tab_label);
priv->dnd_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_screen (GTK_WINDOW (priv->dnd_window),
+ gtk_widget_get_screen (widget));
gtk_container_add (GTK_CONTAINER (priv->dnd_window), tab_label);
gtk_widget_set_size_request (priv->dnd_window,
priv->detached_tab->allocation.width,
gtk_notebook_stop_reorder (GTK_NOTEBOOK (widget));
if (priv->detached_tab)
- gtk_notebook_switch_page (GTK_NOTEBOOK (widget), priv->detached_tab, -1);
+ gtk_notebook_switch_page (GTK_NOTEBOOK (widget), priv->detached_tab);
GTK_BIN (priv->dnd_window)->child = NULL;
gtk_widget_destroy (priv->dnd_window);
priv->operation = DRAG_OPERATION_NONE;
}
+static GtkNotebook *
+gtk_notebook_create_window (GtkNotebook *notebook,
+ GtkWidget *page,
+ gint x,
+ gint y)
+{
+ if (window_creation_hook)
+ return (* window_creation_hook) (notebook, page, x, y, window_creation_hook_data);
+
+ return NULL;
+}
+
static gboolean
gtk_notebook_drag_failed (GtkWidget *widget,
GdkDragContext *context,
if (result == GTK_DRAG_RESULT_NO_TARGET)
{
GtkNotebookPrivate *priv;
- GtkNotebook *notebook, *dest_notebook;
+ GtkNotebook *notebook, *dest_notebook = NULL;
GdkDisplay *display;
gint x, y;
display = gtk_widget_get_display (widget);
gdk_display_get_pointer (display, NULL, &x, &y, NULL);
- dest_notebook = (* window_creation_hook) (notebook,
- priv->detached_tab->child,
- x, y,
- window_creation_hook_data);
+ g_signal_emit (notebook, notebook_signals[CREATE_WINDOW], 0,
+ priv->detached_tab->child, x, y, &dest_notebook);
if (dest_notebook)
do_detach_tab (notebook, dest_notebook, priv->detached_tab->child, 0, 0);
case CHILD_PROP_TAB_LABEL:
label = gtk_notebook_get_tab_label (notebook, child);
- if (label && GTK_IS_LABEL (label))
+ if (GTK_IS_LABEL (label))
g_value_set_string (value, GTK_LABEL (label)->label);
else
g_value_set_string (value, NULL);
case CHILD_PROP_MENU_LABEL:
label = gtk_notebook_get_menu_label (notebook, child);
- if (label && GTK_IS_LABEL (label))
+ if (GTK_IS_LABEL (label))
g_value_set_string (value, GTK_LABEL (label)->label);
else
g_value_set_string (value, NULL);
gtk_notebook_add (GtkContainer *container,
GtkWidget *widget)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (container));
-
gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
NULL, NULL, -1);
}
GList *children;
gint page_num = 0;
- g_return_if_fail (GTK_IS_NOTEBOOK (container));
- g_return_if_fail (widget != NULL);
-
notebook = GTK_NOTEBOOK (container);
children = notebook->children;
}
static gboolean
-focus_child_in (GtkNotebook *notebook,
- GtkDirectionType direction)
+focus_child_in (GtkNotebook *notebook,
+ GtkDirectionType direction)
{
if (notebook->cur_page)
return gtk_widget_child_focus (notebook->cur_page->child, direction);
return FALSE;
}
+static gboolean
+focus_action_in (GtkNotebook *notebook,
+ gint action,
+ GtkDirectionType direction)
+{
+ GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
+
+ if (priv->action_widget[action] &&
+ GTK_WIDGET_VISIBLE (priv->action_widget[action]))
+ return gtk_widget_child_focus (priv->action_widget[action], direction);
+ else
+ return FALSE;
+}
+
/* Focus in the notebook can either be on the pages, or on
- * the tabs.
+ * the tabs or on the action_widgets.
*/
static gint
gtk_notebook_focus (GtkWidget *widget,
GtkDirectionType direction)
{
+ GtkNotebookPrivate *priv;
GtkWidget *old_focus_child;
GtkNotebook *notebook;
GtkDirectionType effective_direction;
+ gint first_action;
+ gint last_action;
gboolean widget_is_focus;
GtkContainer *container;
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
-
container = GTK_CONTAINER (widget);
notebook = GTK_NOTEBOOK (container);
+ priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
+
+ if (notebook->tab_pos == GTK_POS_TOP ||
+ notebook->tab_pos == GTK_POS_LEFT)
+ {
+ first_action = ACTION_WIDGET_START;
+ last_action = ACTION_WIDGET_END;
+ }
+ else
+ {
+ first_action = ACTION_WIDGET_END;
+ last_action = ACTION_WIDGET_START;
+ }
if (notebook->focus_out)
{
}
widget_is_focus = gtk_widget_is_focus (widget);
- old_focus_child = container->focus_child;
+ old_focus_child = container->focus_child;
effective_direction = get_effective_direction (notebook, direction);
- if (old_focus_child) /* Focus on page child */
+ if (old_focus_child) /* Focus on page child or action widget */
{
if (gtk_widget_child_focus (old_focus_child, direction))
return TRUE;
-
- switch (effective_direction)
+
+ if (old_focus_child == priv->action_widget[ACTION_WIDGET_START])
{
- case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_UP:
- /* Focus onto the tabs */
- return focus_tabs_in (notebook);
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- case GTK_DIR_LEFT:
- case GTK_DIR_RIGHT:
- return FALSE;
+ switch (effective_direction)
+ {
+ case GTK_DIR_DOWN:
+ return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
+ case GTK_DIR_RIGHT:
+ return focus_tabs_in (notebook);
+ case GTK_DIR_LEFT:
+ return FALSE;
+ case GTK_DIR_UP:
+ return FALSE;
+ default:
+ switch (direction)
+ {
+ case GTK_DIR_TAB_FORWARD:
+ if ((notebook->tab_pos == GTK_POS_RIGHT || notebook->tab_pos == GTK_POS_BOTTOM) &&
+ focus_child_in (notebook, direction))
+ return TRUE;
+ return focus_tabs_in (notebook);
+ case GTK_DIR_TAB_BACKWARD:
+ return FALSE;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ }
+ else if (old_focus_child == priv->action_widget[ACTION_WIDGET_END])
+ {
+ switch (effective_direction)
+ {
+ case GTK_DIR_DOWN:
+ return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
+ case GTK_DIR_RIGHT:
+ return FALSE;
+ case GTK_DIR_LEFT:
+ return focus_tabs_in (notebook);
+ case GTK_DIR_UP:
+ return FALSE;
+ default:
+ switch (direction)
+ {
+ case GTK_DIR_TAB_FORWARD:
+ return FALSE;
+ case GTK_DIR_TAB_BACKWARD:
+ if ((notebook->tab_pos == GTK_POS_TOP || notebook->tab_pos == GTK_POS_LEFT) &&
+ focus_child_in (notebook, direction))
+ return TRUE;
+ return focus_tabs_in (notebook);
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ }
+ else
+ {
+ switch (effective_direction)
+ {
+ case GTK_DIR_TAB_BACKWARD:
+ case GTK_DIR_UP:
+ /* Focus onto the tabs */
+ return focus_tabs_in (notebook);
+ case GTK_DIR_DOWN:
+ case GTK_DIR_LEFT:
+ case GTK_DIR_RIGHT:
+ return FALSE;
+ case GTK_DIR_TAB_FORWARD:
+ return focus_action_in (notebook, last_action, direction);
+ }
}
}
else if (widget_is_focus) /* Focus was on tabs */
{
switch (effective_direction)
{
- case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_UP:
+ case GTK_DIR_TAB_BACKWARD:
+ return focus_action_in (notebook, first_action, direction);
+ case GTK_DIR_UP:
return FALSE;
- case GTK_DIR_TAB_FORWARD:
+ case GTK_DIR_TAB_FORWARD:
+ if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
+ return TRUE;
+ return focus_action_in (notebook, last_action, direction);
case GTK_DIR_DOWN:
/* We use TAB_FORWARD rather than direction so that we focus a more
* predictable widget for the user; users may be using arrow focusing
* in this situation even if they don't usually use arrow focusing.
*/
- return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
+ return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
case GTK_DIR_LEFT:
return focus_tabs_move (notebook, direction, STEP_PREV);
case GTK_DIR_RIGHT:
{
case GTK_DIR_TAB_FORWARD:
case GTK_DIR_DOWN:
+ if (focus_action_in (notebook, first_action, direction))
+ return TRUE;
if (focus_tabs_in (notebook))
return TRUE;
+ if (focus_action_in (notebook, last_action, direction))
+ return TRUE;
if (focus_child_in (notebook, direction))
return TRUE;
return FALSE;
case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_UP:
+ if (focus_action_in (notebook, last_action, direction))
+ return TRUE;
if (focus_child_in (notebook, direction))
return TRUE;
if (focus_tabs_in (notebook))
return TRUE;
- return FALSE;
+ if (focus_action_in (notebook, first_action, direction))
+ return TRUE;
+ case GTK_DIR_UP:
case GTK_DIR_LEFT:
case GTK_DIR_RIGHT:
return focus_child_in (notebook, direction);
g_assert_not_reached ();
return FALSE;
-}
+}
static void
gtk_notebook_set_focus_child (GtkContainer *container,
*/
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
- if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+ if (toplevel && gtk_widget_is_toplevel (toplevel))
{
page_child = GTK_WINDOW (toplevel)->focus_widget;
while (page_child)
}
}
}
+ else
+ notebook->child_has_focus = FALSE;
GTK_CONTAINER_CLASS (gtk_notebook_parent_class)->set_focus_child (container, child);
}
GtkCallback callback,
gpointer callback_data)
{
+ GtkNotebookPrivate *priv;
GtkNotebook *notebook;
GList *children;
-
- g_return_if_fail (GTK_IS_NOTEBOOK (container));
- g_return_if_fail (callback != NULL);
+ gint i;
notebook = GTK_NOTEBOOK (container);
+ priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
children = notebook->children;
while (children)
(* callback) (page->tab_label, callback_data);
}
}
+
+ if (include_internals) {
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i])
+ (* callback) (priv->action_widget[i], callback_data);
+ }
+ }
}
static GType
}
if (next)
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next), -1);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next));
}
}
GtkNotebookPage *page;
gint nchildren;
- g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
- g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
- g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
- g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
-
gtk_widget_freeze_child_notify (child);
- page = g_new0 (GtkNotebookPage, 1);
+ page = g_slice_new0 (GtkNotebookPage);
page->child = child;
nchildren = g_list_length (notebook->children);
page->mnemonic_activate_signal =
g_signal_connect (tab_label,
- "mnemonic_activate",
+ "mnemonic-activate",
G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
notebook);
}
if (!notebook->cur_page)
{
- gtk_notebook_switch_page (notebook, page, 0);
+ gtk_notebook_switch_page (notebook, page);
/* focus_tab is set in the switch_page method */
gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab);
}
gtk_notebook_update_tab_states (notebook);
+ if (notebook->scrollable)
+ gtk_notebook_redraw_arrows (notebook);
+
gtk_widget_child_notify (child, "tab-expand");
gtk_widget_child_notify (child, "tab-fill");
gtk_widget_child_notify (child, "tab-pack");
GtkNotebookPage *page;
GList * next_list;
gint need_resize = FALSE;
+ GtkWidget *tab_label;
gboolean destroying;
priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
destroying = GTK_OBJECT_FLAGS (notebook) & GTK_IN_DESTRUCTION;
- next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
+ next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
if (!next_list)
- next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
+ next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
+
+ notebook->children = g_list_remove_link (notebook->children, list);
if (notebook->cur_page == list->data)
{
notebook->cur_page = NULL;
if (next_list && !destroying)
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list));
}
if (priv->detached_tab == list->data)
gtk_widget_unparent (page->child);
- gtk_notebook_remove_tab_label (notebook, page);
-
+ tab_label = page->tab_label;
+ if (tab_label)
+ {
+ g_object_ref (tab_label);
+ gtk_notebook_remove_tab_label (notebook, page);
+ if (destroying)
+ gtk_widget_destroy (tab_label);
+ g_object_unref (tab_label);
+ }
+
if (notebook->menu)
{
gtk_container_remove (GTK_CONTAINER (notebook->menu),
if (!page->default_menu)
g_object_unref (page->menu_label);
- notebook->children = g_list_remove_link (notebook->children, list);
g_list_free (list);
if (page->last_focus_child)
page->last_focus_child = NULL;
}
- g_free (page);
+ g_slice_free (GtkNotebookPage, page);
gtk_notebook_update_labels (notebook);
if (need_resize)
gchar string[32];
gint page_num = 1;
+ if (!notebook->show_tabs && !notebook->menu)
+ return;
+
for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
list;
list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
}
if (notebook->menu && page->default_menu)
{
- if (page->tab_label && GTK_IS_LABEL (page->tab_label))
+ if (GTK_IS_LABEL (page->tab_label))
gtk_label_set_text (GTK_LABEL (page->menu_label),
- GTK_LABEL (page->tab_label)->label);
+ GTK_LABEL (page->tab_label)->label);
else
gtk_label_set_text (GTK_LABEL (page->menu_label), string);
}
GList *work;
gint count_start;
- g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
- g_return_val_if_fail (list != NULL, -1);
-
for (work = notebook->children, count_start = 0;
work && work != list; work = work->next)
if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
GList *old_list = NULL;
gint flag = 0;
- g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
-
switch (direction)
{
case STEP_PREV:
gboolean is_rtl;
gint tab_pos;
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
- g_return_if_fail (area != NULL);
-
if (!GTK_WIDGET_DRAWABLE (widget))
return;
GdkWindow *window;
GtkWidget *widget;
- g_return_if_fail (notebook != NULL);
- g_return_if_fail (page != NULL);
- g_return_if_fail (area != NULL);
-
if (!NOTEBOOK_IS_TAB_LABEL_PARENT (notebook, page) ||
!GTK_WIDGET_MAPPED (page->tab_label) ||
(page->allocation.width == 0) || (page->allocation.height == 0))
gint arrow_spacing;
gint scroll_arrow_hlength;
gint scroll_arrow_vlength;
+ gboolean is_rtl;
+ gint i;
widget = GTK_WIDGET (notebook);
priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
children = notebook->children;
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
gtk_widget_style_get (GTK_WIDGET (notebook),
"arrow-spacing", &arrow_spacing,
*min = widget->allocation.x + GTK_CONTAINER (notebook)->border_width;
*max = widget->allocation.x + widget->allocation.width - GTK_CONTAINER (notebook)->border_width;
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i])
+ {
+ if ((i == ACTION_WIDGET_START && !is_rtl) ||
+ (i == ACTION_WIDGET_END && is_rtl))
+ *min += priv->action_widget[i]->allocation.width + widget->style->xthickness;
+ else
+ *max -= priv->action_widget[i]->allocation.width + widget->style->xthickness;
+ }
+ }
+
while (children)
{
GtkNotebookPage *page;
*min = widget->allocation.y + GTK_CONTAINER (notebook)->border_width;
*max = widget->allocation.y + widget->allocation.height - GTK_CONTAINER (notebook)->border_width;
+ for (i = 0; i < N_ACTION_WIDGETS; i++)
+ {
+ if (priv->action_widget[i])
+ {
+ if (i == ACTION_WIDGET_START)
+ *min += priv->action_widget[i]->allocation.height + widget->style->ythickness;
+ else
+ *max -= priv->action_widget[i]->allocation.height + widget->style->ythickness;
+ }
+ }
+
while (children)
{
GtkNotebookPage *page;
*show_arrows = TRUE;
/* take arrows into account */
- *tab_space = widget->allocation.width - tab_overlap -
- 2 * GTK_CONTAINER (notebook)->border_width;
+ *tab_space = *max - *min - tab_overlap;
if (notebook->has_after_previous)
{
*show_arrows = TRUE;
/* take arrows into account */
- *tab_space = widget->allocation.height -
- tab_overlap - 2 * GTK_CONTAINER (notebook)->border_width;
+ *tab_space = *max - *min - tab_overlap;
if (notebook->has_after_previous || notebook->has_after_next)
{
remaining_space, STEP_NEXT);
}
- if (*remaining_space <= 0)
+ if (tab_space <= 0 || *remaining_space < 0)
{
/* show 1 tab */
notebook->first_tab = notebook->focus_tab;
*last_child = gtk_notebook_search_page (notebook, notebook->focus_tab,
STEP_NEXT, TRUE);
+ page = notebook->first_tab->data;
+ *remaining_space = tab_space - page->requisition.width;
+ *n = 1;
}
else
{
TRUE);
}
}
- }
- if (*remaining_space < 0)
- {
- /* calculate number of tabs */
- *remaining_space = - (*remaining_space);
- *n = 0;
-
- for (children = notebook->first_tab;
- children && children != *last_child;
- children = gtk_notebook_search_page (notebook, children,
- STEP_NEXT, TRUE))
- (*n)++;
- }
- else
- *remaining_space = 0;
+ if (*remaining_space < 0)
+ {
+ /* calculate number of tabs */
+ *remaining_space = - (*remaining_space);
+ *n = 0;
+
+ for (children = notebook->first_tab;
+ children && children != *last_child;
+ children = gtk_notebook_search_page (notebook, children,
+ STEP_NEXT, TRUE))
+ (*n)++;
+ }
+ else
+ *remaining_space = 0;
+ }
/* unmap all non-visible tabs */
for (children = gtk_notebook_search_page (notebook, NULL,
return FALSE;
}
-static gboolean
+static void
gtk_notebook_calculate_tabs_allocation (GtkNotebook *notebook,
GList **children,
GList *last_child,
gint xthickness, ythickness;
gboolean gap_left, packing_changed;
GtkAllocation child_allocation = { 0, };
- gboolean allocation_changed = FALSE;
widget = GTK_WIDGET (notebook);
container = GTK_CONTAINER (notebook);
break;
}
- if ((priv->operation != DRAG_OPERATION_REORDER || page != notebook->cur_page) &&
- (page->allocation.x != child_allocation.x ||
- page->allocation.y != child_allocation.y ||
- page->allocation.width != child_allocation.width ||
- page->allocation.height != child_allocation.height))
- allocation_changed = TRUE;
-
page->allocation = child_allocation;
if ((page == priv->detached_tab && priv->operation == DRAG_OPERATION_DETACH) ||
break;
}
}
-
- return allocation_changed;
}
static void
gboolean showarrow = FALSE;
gint tab_space, min, max, remaining_space;
gint expanded_tabs, operation;
+ gboolean tab_allocations_changed = FALSE;
if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
return;
while (children)
{
- gtk_notebook_page_allocate (notebook, GTK_NOTEBOOK_PAGE (children));
+ if (gtk_notebook_page_allocate (notebook, GTK_NOTEBOOK_PAGE (children)))
+ tab_allocations_changed = TRUE;
children = children->next;
}
if (!notebook->first_tab)
notebook->first_tab = notebook->children;
- gtk_notebook_redraw_tabs (notebook);
+ if (tab_allocations_changed)
+ gtk_notebook_redraw_tabs (notebook);
}
-static void
+static gboolean
gtk_notebook_page_allocate (GtkNotebook *notebook,
GtkNotebookPage *page)
{
gint focus_width;
gint tab_curvature;
gint tab_pos = get_effective_tab_pos (notebook);
+ gboolean tab_allocation_changed;
+ gboolean was_visible = page->tab_allocated_visible;
- if (!page->tab_label)
- return;
+ if (!page->tab_label ||
+ !GTK_WIDGET_VISIBLE (page->tab_label) ||
+ !gtk_widget_get_child_visible (page->tab_label))
+ {
+ page->tab_allocated_visible = FALSE;
+ return was_visible;
+ }
xthickness = widget->style->xthickness;
ythickness = widget->style->ythickness;
break;
}
+ tab_allocation_changed = (child_allocation.x != page->tab_label->allocation.x ||
+ child_allocation.y != page->tab_label->allocation.y ||
+ child_allocation.width != page->tab_label->allocation.width ||
+ child_allocation.height != page->tab_label->allocation.height);
+
gtk_widget_size_allocate (page->tab_label, &child_allocation);
+
+ if (!was_visible)
+ {
+ page->tab_allocated_visible = TRUE;
+ tab_allocation_changed = TRUE;
+ }
+
+ return tab_allocation_changed;
}
static void
GtkNotebookPage *page,
guint page_num)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (page != NULL);
+ gboolean child_has_focus;
if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
return;
+ /* save the value here, changing visibility changes focus */
+ child_has_focus = notebook->child_has_focus;
+
if (notebook->cur_page)
gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
* element on the new page, if possible, or if not, to the
* notebook itself.
*/
- if (notebook->child_has_focus)
+ if (child_has_focus)
{
if (notebook->cur_page->last_focus_child &&
gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
*/
static void
gtk_notebook_switch_page (GtkNotebook *notebook,
- GtkNotebookPage *page,
- gint page_num)
+ GtkNotebookPage *page)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (page != NULL);
-
+ guint page_num;
+
if (notebook->cur_page == page)
return;
- if (page_num < 0)
- page_num = g_list_index (notebook->children, page);
+ page_num = g_list_index (notebook->children, page);
g_signal_emit (notebook,
notebook_signals[SWITCH_PAGE],
GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
gint tab_pos = get_effective_tab_pos (notebook);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
-
if (!notebook->focus_tab)
return FALSE;
page = notebook->focus_tab->data;
- gtk_notebook_switch_page (notebook, page, -1);
+ gtk_notebook_switch_page (notebook, page);
if (move_focus)
{
GList *old_child;
GtkNotebookPage *page;
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
if (notebook->focus_tab == new_child)
return;
else
gtk_notebook_pages_allocate (notebook);
- gtk_notebook_switch_page (notebook, page,
- g_list_index (notebook->children, page));
+ gtk_notebook_switch_page (notebook, page);
}
static void
GList *children;
guint page_num;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (page != NULL);
-
notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
(GTK_MENU (widget->parent)));
page = list->data;
if (page->default_menu)
{
- if (page->tab_label && GTK_IS_LABEL (page->tab_label))
+ if (GTK_IS_LABEL (page->tab_label))
page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
else
page->menu_label = gtk_label_new ("");
{
GtkNotebook *notebook;
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
-
notebook = GTK_NOTEBOOK (widget);
g_return_if_fail (notebook->menu == (GtkWidget*) menu);
gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
gboolean homogeneous)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
if (homogeneous == notebook->homogeneous)
return;
gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
guint border_width)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
notebook->tab_hborder = border_width;
notebook->tab_vborder = border_width;
gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
guint tab_hborder)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
if (notebook->tab_hborder == tab_hborder)
return;
gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
guint tab_vborder)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
if (notebook->tab_vborder == tab_vborder)
return;
* gtk_notebook_append_page:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
- *
+ *
* Appends a page to @notebook.
*
* Return value: the index (starting from 0) of the appended
* gtk_notebook_append_page_menu:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
- * @menu_label: the widget to use as a label for the page-switch
+ * @menu_label: (allow-none): the widget to use as a label for the page-switch
* menu, if that is enabled. If %NULL, and @tab_label
* is a #GtkLabel or %NULL, then the menu label will be
* a newly created label with the same text as @tab_label;
* gtk_notebook_prepend_page:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
*
* Prepends a page to @notebook.
* gtk_notebook_prepend_page_menu:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
- * @menu_label: the widget to use as a label for the page-switch
+ * @menu_label: (allow-none): the widget to use as a label for the page-switch
* menu, if that is enabled. If %NULL, and @tab_label
* is a #GtkLabel or %NULL, then the menu label will be
* a newly created label with the same text as @tab_label;
* gtk_notebook_insert_page:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
* @position: the index (starting at 0) at which to insert the page,
* or -1 to append the page after all other pages.
- *
+ *
* Insert a page into @notebook at the given position.
*
* Return value: the index (starting from 0) of the inserted
GtkNotebookPage *page = list->data;
gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
- gtk_notebook_switch_page (notebook, page, -1);
+ gtk_notebook_switch_page (notebook, page);
focus_tabs_in (notebook);
}
* gtk_notebook_insert_page_menu:
* @notebook: a #GtkNotebook
* @child: the #GtkWidget to use as the contents of the page.
- * @tab_label: the #GtkWidget to be used as the label for the page,
+ * @tab_label: (allow-none): the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
- * @menu_label: the widget to use as a label for the page-switch
+ * @menu_label: (allow-none): the widget to use as a label for the page-switch
* menu, if that is enabled. If %NULL, and @tab_label
* is a #GtkLabel or %NULL, then the menu label will be
* a newly created label with the same text as @tab_label;
/**
* gtk_notebook_get_nth_page:
* @notebook: a #GtkNotebook
- * @page_num: the index of a page in the noteobok, or -1
+ * @page_num: the index of a page in the notebook, or -1
* to get the last page.
*
* Returns the child widget contained in page number @page_num.
- *
- * Return value: the child widget, or %NULL if @page_num is
+ *
+ * Return value: (transfer none): the child widget, or %NULL if @page_num is
* out of bounds.
**/
GtkWidget*
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- if (page_num >= 0)
- list = g_list_nth (notebook->children, page_num);
- else
- list = g_list_last (notebook->children);
-
- page_num = g_list_index (notebook->children, list);
+ if (page_num < 0)
+ page_num = g_list_length (notebook->children) - 1;
+ list = g_list_nth (notebook->children, page_num);
if (list)
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list));
}
/**
if (!list)
return;
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list));
}
/**
if (!list)
return;
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list));
}
/* Public GtkNotebook/Tab Style Functions
* Returns the tab label widget for the page @child. %NULL is returned
* if @child is not in @notebook or if no tab label has specifically
* been set for @child.
- *
- * Return value: the tab label
+ *
+ * Return value: (transfer none): the tab label
**/
GtkWidget *
gtk_notebook_get_tab_label (GtkNotebook *notebook,
* gtk_notebook_set_tab_label:
* @notebook: a #GtkNotebook
* @child: the page
- * @tab_label: the tab label widget to use, or %NULL for default tab
+ * @tab_label: (allow-none): the tab label widget to use, or %NULL for default tab
* label.
- *
+ *
* Changes the tab label for @child. If %NULL is specified
* for @tab_label, then the page will have the label 'page N'.
**/
if (page->tab_label)
page->mnemonic_activate_signal =
g_signal_connect (page->tab_label,
- "mnemonic_activate",
+ "mnemonic-activate",
G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
notebook);
* Retrieves the text of the tab label for the page containing
* @child.
*
- * Returns value: the text of the tab label, or %NULL if the
- * tab label widget is not a #GtkLabel. The
- * string is owned by the widget and must not
- * be freed.
+ * Return value: the text of the tab label, or %NULL if the
+ * tab label widget is not a #GtkLabel. The
+ * string is owned by the widget and must not
+ * be freed.
**/
G_CONST_RETURN gchar *
gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
tab_label = gtk_notebook_get_tab_label (notebook, child);
- if (tab_label && GTK_IS_LABEL (tab_label))
+ if (GTK_IS_LABEL (tab_label))
return gtk_label_get_text (GTK_LABEL (tab_label));
else
return NULL;
* gtk_notebook_set_menu_label:
* @notebook: a #GtkNotebook
* @child: the child widget
- * @menu_label: the menu label, or NULL for default
- *
- * Changes the menu label for the page containing @child.
+ * @menu_label: (allow-none): the menu label, or NULL for default
+ *
+ * Changes the menu label for the page containing @child.
**/
void
gtk_notebook_set_menu_label (GtkNotebook *notebook,
* Retrieves the text of the menu label for the page containing
* @child.
*
- * Returns value: the text of the tab label, or %NULL if the
- * widget does not have a menu label other than
- * the default menu label, or the menu label widget
- * is not a #GtkLabel. The string is owned by
- * the widget and must not be freed.
+ * Return value: the text of the tab label, or %NULL if the
+ * widget does not have a menu label other than
+ * the default menu label, or the menu label widget
+ * is not a #GtkLabel. The string is owned by
+ * the widget and must not be freed.
**/
G_CONST_RETURN gchar *
gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
menu_label = gtk_notebook_get_menu_label (notebook, child);
- if (menu_label && GTK_IS_LABEL (menu_label))
+ if (GTK_IS_LABEL (menu_label))
return gtk_label_get_text (GTK_LABEL (menu_label));
else
return NULL;
* @expand: whether to expand the bookmark or not
* @fill: whether the bookmark should fill the allocated area or not
* @pack_type: the position of the bookmark
- *
+ *
* Sets the packing parameters for the tab label of the page
* containing @child. See gtk_box_pack_start() for the exact meaning
* of the parameters.
+ *
+ * Deprecated: 2.20: Modify the "tab-expand" and "tab-fill" child
+ * properties instead.
**/
void
gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
*
* Query the packing attributes for the tab label of the page
* containing @child.
+ *
+ * Deprecated: 2.20: Modify the "tab-expand" and "tab-fill" child
+ * properties instead.
**/
void
gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
* not be able to exchange tabs with any other notebook.
*
* Since: 2.10
- * Deprecated:2.12: use gtk_notebook_set_group() instead.
+ * Deprecated: 2.12: use gtk_notebook_set_group() instead.
*/
void
gtk_notebook_set_group_id (GtkNotebook *notebook,
gint group_id)
{
- GtkNotebookPrivate *priv;
gpointer group;
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
/**
* gtk_notebook_set_group:
* @notebook: a #GtkNotebook
- * @group_id: a pointer to identify the notebook group, or %NULL to unset it
+ * @group: a pointer to identify the notebook group, or %NULL to unset it
*
* Sets a group identificator pointer for @notebook, notebooks sharing
* the same group identificator pointer will be able to exchange tabs
* Return Value: the group identificator, or -1 if none is set.
*
* Since: 2.10
- * Deprecated:2.12: use gtk_notebook_get_group() instead.
+ * Deprecated: 2.12: use gtk_notebook_get_group() instead.
*/
gint
gtk_notebook_get_group_id (GtkNotebook *notebook)
priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
/* substract 1 to get rid of the -1/NULL difference */
- return GPOINTER_TO_INT (priv->group - 1);
+ return GPOINTER_TO_INT (priv->group) - 1;
}
/**
* destination and accept the target "GTK_NOTEBOOK_TAB". The notebook
* will fill the selection with a GtkWidget** pointing to the child
* widget that corresponds to the dropped tab.
- *
- * <informalexample><programlisting>
+ * |[
* static void
* on_drop_zone_drag_data_received (GtkWidget *widget,
* GdkDragContext *context,
* process_widget (*child);
* gtk_container_remove (GTK_CONTAINER (notebook), *child);
* }
- * </programlisting></informalexample>
+ * ]|
*
* If you want a notebook to accept drags from other widgets,
* you will have to set your own DnD code to do it.
}
}
+/**
+ * gtk_notebook_get_action_widget:
+ * @notebook: a #GtkNotebook
+ * @pack_type: pack type of the action widget to receive
+ *
+ * Gets one of the action widgets. See gtk_notebook_set_action_widget().
+ *
+ * Returns: The action widget with the given @pack_type or
+ * %NULL when this action widget has not been set
+ *
+ * Since: 2.20
+ */
+GtkWidget*
+gtk_notebook_get_action_widget (GtkNotebook *notebook,
+ GtkPackType pack_type)
+{
+ GtkNotebookPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
+
+ priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
+ return priv->action_widget[pack_type];
+}
+
+/**
+ * gtk_notebook_set_action_widget:
+ * @notebook: a #GtkNotebook
+ * @widget: a #GtkWidget
+ * @pack_type: pack type of the action widget
+ *
+ * Sets @widget as one of the action widgets. Depending on the pack type
+ * the widget will be placed before or after the tabs. You can use
+ * a #GtkBox if you need to pack more than one widget on the same side.
+ *
+ * Note that action widgets are "internal" children of the notebook and thus
+ * not included in the list returned from gtk_container_foreach().
+ *
+ * Since: 2.20
+ */
+void
+gtk_notebook_set_action_widget (GtkNotebook *notebook,
+ GtkWidget *widget,
+ GtkPackType pack_type)
+{
+ GtkNotebookPrivate *priv;
+
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ g_return_if_fail (!widget || GTK_IS_WIDGET (widget));
+ g_return_if_fail (!widget || widget->parent == NULL);
+
+ priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
+
+ if (priv->action_widget[pack_type])
+ gtk_widget_unparent (priv->action_widget[pack_type]);
+
+ priv->action_widget[pack_type] = widget;
+
+ if (widget)
+ {
+ gtk_widget_set_parent (widget, GTK_WIDGET (notebook));
+
+ if (GTK_WIDGET_REALIZED (GTK_WIDGET (notebook)))
+ gtk_widget_realize (widget);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+}
+
#define __GTK_NOTEBOOK_C__
#include "gtkaliasdef.c"