* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
#include "gtknotebook.h"
-#include "gtksignal.h"
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkbindings.h"
+#include "gtkprivate.h"
+#include "gtkalias.h"
#define TAB_OVERLAP 2
FOCUS_TAB,
SELECT_PAGE,
CHANGE_CURRENT_PAGE,
+ MOVE_FOCUS_OUT,
LAST_SIGNAL
};
STEP_NEXT
};
+typedef enum
+{
+ ARROW_NONE,
+ ARROW_LEFT_BEFORE,
+ ARROW_RIGHT_BEFORE,
+ ARROW_LEFT_AFTER,
+ ARROW_RIGHT_AFTER
+} GtkNotebookArrow;
+
+#define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
+#define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
+
enum {
PROP_0,
PROP_TAB_POS,
static void gtk_notebook_class_init (GtkNotebookClass *klass);
static void gtk_notebook_init (GtkNotebook *notebook);
-static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
- gboolean move_focus);
-static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
- GtkNotebookTab type);
-static void gtk_notebook_change_current_page (GtkNotebook *notebook,
- gint offset);
-
+static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
+ gboolean move_focus);
+static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
+ GtkNotebookTab type);
+static void gtk_notebook_change_current_page (GtkNotebook *notebook,
+ gint offset);
+static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
+ GtkDirectionType direction_type);
/*** GtkObject Methods ***/
static void gtk_notebook_destroy (GtkObject *object);
GtkAllocation *allocation);
static gint gtk_notebook_expose (GtkWidget *widget,
GdkEventExpose *event);
+static gboolean gtk_notebook_scroll (GtkWidget *widget,
+ GdkEventScroll *event);
static gint gtk_notebook_button_press (GtkWidget *widget,
GdkEventButton *event);
static gint gtk_notebook_button_release (GtkWidget *widget,
GdkEventMotion *event);
static gint gtk_notebook_focus_in (GtkWidget *widget,
GdkEventFocus *event);
+static gint gtk_notebook_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static void gtk_notebook_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed);
+static void gtk_notebook_state_changed (GtkWidget *widget,
+ GtkStateType previous_state);
static void gtk_notebook_draw_focus (GtkWidget *widget);
static gint gtk_notebook_focus (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_notebook_style_set (GtkWidget *widget,
+ GtkStyle *previous);
/*** GtkContainer Methods ***/
static void gtk_notebook_set_child_property (GtkContainer *container,
GtkWidget *widget);
static void gtk_notebook_set_focus_child (GtkContainer *container,
GtkWidget *child);
-static GtkType gtk_notebook_child_type (GtkContainer *container);
+static GType gtk_notebook_child_type (GtkContainer *container);
static void gtk_notebook_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
/*** GtkNotebook Private Functions ***/
static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
-static void gtk_notebook_focus_changed (GtkNotebook *notebook,
- GtkNotebookPage *old_page);
static void gtk_notebook_real_remove (GtkNotebook *notebook,
- GList *list);
+ GList *list,
+ gboolean destroying);
static void gtk_notebook_update_labels (GtkNotebook *notebook);
static gint gtk_notebook_timer (GtkNotebook *notebook);
static gint gtk_notebook_page_compare (gconstpointer a,
GtkNotebookPage *page,
GdkRectangle *area);
static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
- guint arrow);
+ GtkNotebookArrow arrow);
/*** GtkNotebook Size Allocate Functions ***/
static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
static void gtk_notebook_menu_detacher (GtkWidget *widget,
GtkMenu *menu);
+/*** GtkNotebook Private Setters ***/
+static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
+ gboolean homogeneous);
+static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
+ guint border_width);
+static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
+ guint tab_hborder);
+static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
+ guint tab_vborder);
+
+static gboolean focus_tabs_in (GtkNotebook *notebook);
+static gboolean focus_child_in (GtkNotebook *notebook,
+ GtkDirectionType direction);
+
+static void stop_scrolling (GtkNotebook *notebook);
+
static GtkContainerClass *parent_class = NULL;
static guint notebook_signals[LAST_SIGNAL] = { 0 };
-GtkType
+GType
gtk_notebook_get_type (void)
{
- static GtkType notebook_type = 0;
+ static GType notebook_type = 0;
if (!notebook_type)
{
- static const GtkTypeInfo notebook_info =
+ static const GTypeInfo notebook_info =
{
- "GtkNotebook",
- sizeof (GtkNotebook),
sizeof (GtkNotebookClass),
- (GtkClassInitFunc) gtk_notebook_class_init,
- (GtkObjectInitFunc) gtk_notebook_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gtk_notebook_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkNotebook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_notebook_init,
};
- notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
+ notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
+ ¬ebook_info, 0);
}
return notebook_type;
}
+static void
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ GtkDirectionType direction)
+{
+ gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
+static void
+add_arrow_bindings (GtkBindingSet *binding_set,
+ guint keysym,
+ GtkDirectionType direction)
+{
+ guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
+
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
static void
gtk_notebook_class_init (GtkNotebookClass *class)
{
widget_class->size_request = gtk_notebook_size_request;
widget_class->size_allocate = gtk_notebook_size_allocate;
widget_class->expose_event = gtk_notebook_expose;
+ widget_class->scroll_event = gtk_notebook_scroll;
widget_class->button_press_event = gtk_notebook_button_press;
widget_class->button_release_event = gtk_notebook_button_release;
widget_class->enter_notify_event = gtk_notebook_enter_notify;
widget_class->leave_notify_event = gtk_notebook_leave_notify;
widget_class->motion_notify_event = gtk_notebook_motion_notify;
+ widget_class->grab_notify = gtk_notebook_grab_notify;
+ widget_class->state_changed = gtk_notebook_state_changed;
widget_class->focus_in_event = gtk_notebook_focus_in;
+ widget_class->focus_out_event = gtk_notebook_focus_out;
widget_class->focus = gtk_notebook_focus;
+ widget_class->style_set = gtk_notebook_style_set;
container_class->add = gtk_notebook_add;
container_class->remove = gtk_notebook_remove;
class->focus_tab = gtk_notebook_focus_tab;
class->select_page = gtk_notebook_select_page;
class->change_current_page = gtk_notebook_change_current_page;
+ class->move_focus_out = gtk_notebook_move_focus_out;
g_object_class_install_property (gobject_class,
PROP_PAGE,
g_param_spec_int ("page",
- _("Page"),
- _("The index of the current page"),
+ P_("Page"),
+ P_("The index of the current page"),
0,
G_MAXINT,
0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TAB_POS,
- g_param_spec_enum ("tab_pos",
- _("Tab Position"),
- _("Which side of the notebook holds the tabs"),
+ g_param_spec_enum ("tab-pos",
+ P_("Tab Position"),
+ P_("Which side of the notebook holds the tabs"),
GTK_TYPE_POSITION_TYPE,
GTK_POS_TOP,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TAB_BORDER,
- g_param_spec_uint ("tab_border",
- _("Tab Border"),
- _("Width of the border around the tab labels"),
+ g_param_spec_uint ("tab-border",
+ P_("Tab Border"),
+ P_("Width of the border around the tab labels"),
0,
G_MAXUINT,
2,
- G_PARAM_WRITABLE));
+ GTK_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
PROP_TAB_HBORDER,
- g_param_spec_uint ("tab_hborder",
- _("Horizontal Tab Border"),
- _("Width of the horizontal border of tab labels"),
+ g_param_spec_uint ("tab-hborder",
+ P_("Horizontal Tab Border"),
+ P_("Width of the horizontal border of tab labels"),
0,
G_MAXUINT,
2,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TAB_VBORDER,
- g_param_spec_uint ("tab_vborder",
- _("Vertical Tab Border"),
- _("Width of the vertical border of tab labels"),
+ g_param_spec_uint ("tab-vborder",
+ P_("Vertical Tab Border"),
+ P_("Width of the vertical border of tab labels"),
0,
G_MAXUINT,
2,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SHOW_TABS,
- g_param_spec_boolean ("show_tabs",
- _("Show Tabs"),
- _("Whether tabs should be shown or not"),
+ g_param_spec_boolean ("show-tabs",
+ P_("Show Tabs"),
+ P_("Whether tabs should be shown or not"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SHOW_BORDER,
- g_param_spec_boolean ("show_border",
- _("Show Border"),
- _("Whether the border should be shown or not"),
+ g_param_spec_boolean ("show-border",
+ P_("Show Border"),
+ P_("Whether the border should be shown or not"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SCROLLABLE,
g_param_spec_boolean ("scrollable",
- _("Scrollable"),
- _("If TRUE, scroll arrows are added if there are to many tabs to fit"),
+ P_("Scrollable"),
+ P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
FALSE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_ENABLE_POPUP,
- g_param_spec_boolean ("enable_popup",
- _("Enable Popup"),
- _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
+ g_param_spec_boolean ("enable-popup",
+ P_("Enable Popup"),
+ P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
FALSE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_HOMOGENEOUS,
g_param_spec_boolean ("homogeneous",
- _("Homogeneous"),
- _("Whether tabs should have homogeneous sizes"),
+ P_("Homogeneous"),
+ P_("Whether tabs should have homogeneous sizes"),
FALSE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_TAB_LABEL,
- g_param_spec_string ("tab_label", NULL, NULL,
+ g_param_spec_string ("tab-label",
+ P_("Tab label"),
+ P_("The string displayed on the child's tab label"),
NULL,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_MENU_LABEL,
- g_param_spec_string ("menu_label", NULL, NULL,
+ g_param_spec_string ("menu-label",
+ P_("Menu label"),
+ P_("The string displayed in the child's menu entry"),
NULL,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_POSITION,
- g_param_spec_int ("position", NULL, NULL,
+ g_param_spec_int ("position",
+ P_("Position"),
+ P_("The index of the child in the parent"),
-1, G_MAXINT, 0,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_TAB_EXPAND,
- g_param_spec_boolean ("tab_expand", NULL, NULL,
+ g_param_spec_boolean ("tab-expand",
+ P_("Tab expand"),
+ P_("Whether to expand the child's tab or not"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_TAB_FILL,
- g_param_spec_boolean ("tab_fill", NULL, NULL,
+ g_param_spec_boolean ("tab-fill",
+ P_("Tab fill"),
+ P_("Whether the child's tab should fill the allocated area or not"),
TRUE,
- G_PARAM_READWRITE));
+ GTK_PARAM_READWRITE));
gtk_container_class_install_child_property (container_class,
CHILD_PROP_TAB_PACK,
- g_param_spec_enum ("tab_pack", NULL, NULL,
+ g_param_spec_enum ("tab-pack",
+ P_("Tab pack type"),
+ P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
GTK_TYPE_PACK_TYPE, GTK_PACK_START,
- G_PARAM_READWRITE));
-
+ GTK_PARAM_READWRITE));
+
+/**
+ * GtkNotebook:has-secondary-backward-stepper:
+ *
+ * The "has-secondary-backward-stepper" property determines whether
+ * a second backward arrow button is displayed on the opposite end
+ * of the tab area.
+ *
+ * Since: 2.4
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("has-secondary-backward-stepper",
+ P_("Secondary backward stepper"),
+ P_("Display a second backward arrow button on the opposite end of the tab area"),
+ FALSE,
+
+ GTK_PARAM_READABLE));
+
+/**
+ * GtkNotebook:has-secondary-forward-stepper:
+ *
+ * The "has-secondary-forward-stepper" property determines whether
+ * a second forward arrow button is displayed on the opposite end
+ * of the tab area.
+ *
+ * Since: 2.4
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("has-secondary-forward-stepper",
+ P_("Secondary forward stepper"),
+ P_("Display a second forward arrow button on the opposite end of the tab area"),
+ FALSE,
+
+ GTK_PARAM_READABLE));
+
+/**
+ * GtkNotebook:has-backward-stepper:
+ *
+ * The "has-backward-stepper" property determines whether
+ * the standard backward arrow button is displayed.
+ *
+ * Since: 2.4
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("has-backward-stepper",
+ P_("Backward stepper"),
+ P_("Display the standard backward arrow button"),
+ TRUE,
+
+ GTK_PARAM_READABLE));
+
+/**
+ * GtkNotebook:has-forward-stepper:
+ *
+ * The "has-forward-stepper" property determines whether
+ * the standard forward arrow button is displayed.
+ *
+ * Since: 2.4
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boolean ("has-forward-stepper",
+ P_("Forward stepper"),
+ P_("Display the standard forward arrow button"),
+ TRUE,
+
+ GTK_PARAM_READABLE));
+
notebook_signals[SWITCH_PAGE] =
- gtk_signal_new ("switch_page",
- GTK_RUN_LAST,
- GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
- _gtk_marshal_VOID__POINTER_UINT,
- GTK_TYPE_NONE, 2,
- GTK_TYPE_POINTER,
- GTK_TYPE_UINT);
+ g_signal_new ("switch_page",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
+ NULL, NULL,
+ _gtk_marshal_VOID__POINTER_UINT,
+ G_TYPE_NONE, 2,
+ G_TYPE_POINTER,
+ G_TYPE_UINT);
notebook_signals[FOCUS_TAB] =
g_signal_new ("focus_tab",
- G_TYPE_FROM_CLASS (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
NULL, NULL,
_gtk_marshal_BOOLEAN__ENUM,
- G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN, 1,
GTK_TYPE_NOTEBOOK_TAB);
notebook_signals[SELECT_PAGE] =
g_signal_new ("select_page",
- G_TYPE_FROM_CLASS (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, select_page),
NULL, NULL,
G_TYPE_BOOLEAN);
notebook_signals[CHANGE_CURRENT_PAGE] =
g_signal_new ("change_current_page",
- G_TYPE_FROM_CLASS (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
NULL, NULL,
- gtk_marshal_VOID__INT,
- G_TYPE_BOOLEAN, 1,
+ _gtk_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
G_TYPE_INT);
+ notebook_signals[MOVE_FOCUS_OUT] =
+ g_signal_new ("move_focus_out",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_DIRECTION_TYPE);
- binding_set = gtk_binding_set_by_class (object_class);
- gtk_binding_entry_add_signal (binding_set,
- GDK_Return, 0,
- "select_page", 1,
- G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set,
- GDK_KP_Enter, 0,
- "select_page", 1,
- G_TYPE_BOOLEAN, TRUE);
+
+ binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
GDK_space, 0,
"select_page", 1,
GDK_Page_Down, GDK_CONTROL_MASK,
"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,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
+ "change_current_page", 1,
+ G_TYPE_INT, 1);
+
+ add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
+
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
}
static void
gtk_notebook_init (GtkNotebook *notebook)
{
- GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
+ GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
notebook->cur_page = NULL;
notebook->need_timer = 0;
notebook->child_has_focus = FALSE;
notebook->have_visible_child = FALSE;
+ notebook->focus_out = FALSE;
+
+ notebook->has_before_previous = 1;
+ notebook->has_before_next = 0;
+ notebook->has_after_previous = 0;
+ notebook->has_after_next = 1;
}
static gboolean
if (current)
gtk_notebook_switch_page (notebook, current->data, -1);
+ else
+ gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
+}
+
+static GtkDirectionType
+get_effective_direction (GtkNotebook *notebook,
+ GtkDirectionType direction)
+{
+ /* Remap the directions into the effective direction it would be for a
+ * GTK_POS_TOP notebook
+ */
+
+#define D(rest) GTK_DIR_##rest
+
+ static const GtkDirectionType translate_direction[2][4][6] = {
+ /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
+ /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
+ /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
+ /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
+ /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
+ /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
+ /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
+ /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
+ };
+
+#undef D
+
+ int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
+
+ return translate_direction[text_dir][notebook->tab_pos][direction];
+}
+
+static gint
+get_effective_tab_pos (GtkNotebook *notebook)
+{
+ if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_LEFT:
+ return GTK_POS_RIGHT;
+ case GTK_POS_RIGHT:
+ return GTK_POS_LEFT;
+ default: ;
+ }
+ }
+
+ return notebook->tab_pos;
+}
+
+static void
+gtk_notebook_move_focus_out (GtkNotebook *notebook,
+ GtkDirectionType direction_type)
+{
+ GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
+ GtkWidget *toplevel;
+
+ if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
+ if (focus_tabs_in (notebook))
+ return;
+ if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
+ if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
+ return;
+
+ /* At this point, we know we should be focusing out of the notebook entirely. We
+ * 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))
+ return;
+
+ g_object_ref (notebook);
+
+ notebook->focus_out = TRUE;
+ g_signal_emit_by_name (toplevel, "move_focus", direction_type);
+ notebook->focus_out = FALSE;
+
+ g_object_unref (notebook);
+
}
/**
GtkWidget*
gtk_notebook_new (void)
{
- return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
+ return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
}
/* Private GtkObject Methods :
static void
gtk_notebook_destroy (GtkObject *object)
{
+ GList *children;
GtkNotebook *notebook = GTK_NOTEBOOK (object);
if (notebook->menu)
gtk_notebook_popup_disable (notebook);
+ children = notebook->children;
+ while (children)
+ {
+ GList *child = children;
+ children = child->next;
+
+ gtk_notebook_real_remove (notebook, child, TRUE);
+ }
+
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
gtk_notebook_popup_disable (notebook);
break;
case PROP_HOMOGENEOUS:
- gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
+ gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
break;
case PROP_PAGE:
gtk_notebook_set_current_page (notebook, g_value_get_int (value));
gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
break;
case PROP_TAB_BORDER:
- gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
+ gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
break;
case PROP_TAB_HBORDER:
- gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
+ gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
break;
case PROP_TAB_VBORDER:
- gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
+ gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
break;
default:
break;
* gtk_notebook_size_request
* gtk_notebook_size_allocate
* gtk_notebook_expose
+ * gtk_notebook_scroll
* gtk_notebook_button_press
* gtk_notebook_button_release
* gtk_notebook_enter_notify
{
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);
- if (notebook->show_tabs && notebook->children)
+ for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
{
- if (rectangle)
+ GtkNotebookPage *page = tmp_list->data;
+ if (GTK_WIDGET_VISIBLE (page->child))
{
- GtkNotebookPage *page = notebook->children->data;
+ visible_page = page;
+ break;
+ }
+ }
+ if (notebook->show_tabs && visible_page)
+ {
+ if (rectangle)
+ {
rectangle->x = widget->allocation.x + border_width;
rectangle->y = widget->allocation.y + border_width;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
rectangle->width = widget->allocation.width - 2 * border_width;
- rectangle->height = page->requisition.height;
- if (notebook->tab_pos == GTK_POS_BOTTOM)
+ rectangle->height = visible_page->requisition.height;
+ if (tab_pos == GTK_POS_BOTTOM)
rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
- rectangle->width = page->requisition.width;
+ rectangle->width = visible_page->requisition.width;
rectangle->height = widget->allocation.height - 2 * border_width;
- if (notebook->tab_pos == GTK_POS_RIGHT)
+ if (tab_pos == GTK_POS_RIGHT)
rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
break;
}
{
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ stop_scrolling (GTK_NOTEBOOK (widget));
+
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
gtk_notebook_get_event_window_position (notebook, &event_window_pos);
widget->window = gtk_widget_get_parent_window (widget);
- gdk_window_ref (widget->window);
+ g_object_ref (widget->window);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = event_window_pos.x;
attributes.height = event_window_pos.height;
attributes.wclass = GDK_INPUT_ONLY;
attributes.event_mask = gtk_widget_get_events (widget);
- attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
-
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
+ GDK_SCROLL_MASK);
attributes_mask = GDK_WA_X | GDK_WA_Y;
notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
if (notebook->scrollable && vis_pages > 1 &&
widget->requisition.height < tab_height)
- tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
+ tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
padding = 2 * (TAB_CURVATURE + focus_width +
notebook->tab_vborder) - TAB_OVERLAP;
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
gint vis_pages = 0;
+ gint tab_pos = get_effective_tab_pos (notebook);
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
GdkRectangle position;
if (gtk_notebook_get_event_window_position (notebook, &position))
- gdk_window_move_resize (notebook->event_window,
- position.x, position.y,
- position.width, position.height);
+ {
+ gdk_window_move_resize (notebook->event_window,
+ position.x, position.y,
+ position.width, position.height);
+ if (GTK_WIDGET_MAPPED (notebook))
+ gdk_window_show_unraised (notebook->event_window);
+ }
+ else
+ gdk_window_hide (notebook->event_window);
}
if (notebook->children)
if (notebook->show_tabs && notebook->children && notebook->cur_page)
{
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
child_allocation.y += notebook->cur_page->requisition.height;
gtk_notebook_pages_allocate (notebook);
}
-
- if ((vis_pages != 0) != notebook->have_visible_child)
- {
- notebook->have_visible_child = (vis_pages != 0);
- if (notebook->show_tabs)
- gtk_widget_queue_draw (widget);
- }
}
static gint
}
static void
-gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
- GdkRectangle *rectangle)
+gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
+ GdkRectangle *rectangle,
+ GtkNotebookArrow arrow)
{
GdkRectangle event_window_pos;
+ gboolean before = ARROW_IS_BEFORE (arrow);
+ gboolean left = ARROW_IS_LEFT (arrow);
if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
{
- rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
+ rectangle->width = ARROW_SIZE;
rectangle->height = ARROW_SIZE;
switch (notebook->tab_pos)
{
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
+ if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
+ (!before && (notebook->has_after_previous != notebook->has_after_next)))
rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
- rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
+ else if (left)
+ rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
+ else
+ rectangle->x = event_window_pos.x + event_window_pos.width / 2;
+ rectangle->y = event_window_pos.y;
+ if (!before)
+ rectangle->y += event_window_pos.height - rectangle->height;
break;
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
+ if (before)
+ {
+ if (left || !notebook->has_before_previous)
+ rectangle->x = event_window_pos.x;
+ else
+ rectangle->x = event_window_pos.x + rectangle->width;
+ }
+ else
+ {
+ if (!left || !notebook->has_after_next)
+ rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
+ else
+ rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
+ }
rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
break;
}
}
}
-static GtkArrowType
+static GtkNotebookArrow
gtk_notebook_get_arrow (GtkNotebook *notebook,
gint x,
gint y)
{
GdkRectangle arrow_rect;
GdkRectangle event_window_pos;
+ gint i;
+ gint x0, y0;
+ GtkNotebookArrow arrow[4];
+
+ arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
+ arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
+ arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
+ arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
if (gtk_notebook_show_arrows (notebook))
{
gtk_notebook_get_event_window_position (notebook, &event_window_pos);
- gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
+ for (i = 0; i < 4; i++)
+ {
+ if (arrow[i] == ARROW_NONE)
+ continue;
- x -= arrow_rect.x;
- y -= arrow_rect.y;
+ gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
- if (y >= 0 && y < arrow_rect.height)
- {
- if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
- return GTK_ARROW_LEFT;
- else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
- return GTK_ARROW_RIGHT;
+ x0 = x - arrow_rect.x;
+ y0 = y - arrow_rect.y;
+
+ if (y0 >= 0 && y0 < arrow_rect.height &&
+ x0 >= 0 && x0 < arrow_rect.width)
+ return arrow[i];
}
}
-
- return 0;
+
+ return ARROW_NONE;
}
-static gboolean
-gtk_notebook_arrow_button_press (GtkNotebook *notebook,
- GtkArrowType arrow,
- GdkEventButton *event)
+static void
+gtk_notebook_do_arrow (GtkNotebook *notebook,
+ 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 = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
+ (!ARROW_IS_LEFT (arrow) && is_rtl);
+ if (!notebook->focus_tab ||
+ gtk_notebook_search_page (notebook, notebook->focus_tab,
+ 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_widget_child_focus (widget, dir);
+ }
+}
+
+static gboolean
+gtk_notebook_arrow_button_press (GtkNotebook *notebook,
+ GtkNotebookArrow arrow,
+ GdkEventButton *event)
+{
+ GtkWidget *widget = GTK_WIDGET (notebook);
+ gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+ gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
+ (!ARROW_IS_LEFT (arrow) && is_rtl);
+
if (!GTK_WIDGET_HAS_FOCUS (widget))
gtk_widget_grab_focus (widget);
if (event->button == 1)
{
- GtkDirectionType dir;
- if (!notebook->focus_tab ||
- gtk_notebook_search_page (notebook, notebook->focus_tab,
- arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
- TRUE))
- {
- if (notebook->tab_pos == GTK_POS_LEFT ||
- notebook->tab_pos == GTK_POS_RIGHT)
- dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
- else
- dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
- gtk_widget_child_focus (widget, dir);
- }
+ gtk_notebook_do_arrow (notebook, arrow);
if (!notebook->timer)
{
- notebook->timer = gtk_timeout_add
- (NOTEBOOK_INIT_SCROLL_DELAY,
- (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
+ notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
+ (GSourceFunc) gtk_notebook_timer,
+ (gpointer) notebook);
notebook->need_timer = TRUE;
}
}
gtk_notebook_switch_focus_tab (notebook,
gtk_notebook_search_page (notebook,
NULL,
- arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
+ left ? STEP_NEXT : STEP_PREV,
TRUE));
gtk_notebook_redraw_arrows (notebook);
return FALSE;
}
+static gboolean
+gtk_notebook_scroll (GtkWidget *widget,
+ GdkEventScroll *event)
+{
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+
+ GtkWidget* child;
+ GtkWidget* originator;
+
+ if (!notebook->cur_page)
+ return FALSE;
+
+ child = notebook->cur_page->child;
+ originator = gtk_get_event_widget ((GdkEvent *)event);
+
+ /* ignore scroll events from the content of the page */
+ if (!originator || gtk_widget_is_ancestor (originator, child))
+ return FALSE;
+
+ switch (event->direction)
+ {
+ case GDK_SCROLL_RIGHT:
+ case GDK_SCROLL_DOWN:
+ gtk_notebook_next_page (notebook);
+ break;
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_UP:
+ gtk_notebook_prev_page (notebook);
+ break;
+ }
+
+ return TRUE;
+}
+
static gboolean
gtk_notebook_button_press (GtkWidget *widget,
GdkEventButton *event)
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPage *page;
GList *children;
- GtkArrowType arrow;
+ GtkNotebookArrow arrow;
gint num;
gint x, y;
return TRUE;
}
+ if (event->button != 1)
+ return FALSE;
+
num = 0;
children = notebook->children;
while (children)
(x <= (page->allocation.x + page->allocation.width)) &&
(y <= (page->allocation.y + page->allocation.height)))
{
- if (page == notebook->cur_page && notebook->focus_tab &&
- notebook->focus_tab != children &&
- GTK_WIDGET_HAS_FOCUS (notebook))
- {
- GtkNotebookPage *old_page;
-
- notebook->child_has_focus = FALSE;
- old_page = (GtkNotebookPage *)
- (notebook->focus_tab->data);
- gtk_notebook_switch_focus_tab (notebook, children);
- gtk_notebook_focus_changed (notebook, old_page);
- }
- else
- {
- gtk_notebook_switch_focus_tab (notebook, children);
- gtk_widget_grab_focus (widget);
- gtk_notebook_switch_page (notebook, page, num);
- }
+ gboolean page_changed = page != notebook->cur_page;
+ gboolean was_focus = gtk_widget_is_focus (widget);
+
+ gtk_notebook_switch_focus_tab (notebook, children);
+ gtk_widget_grab_focus (widget);
+
+ if (page_changed && !was_focus)
+ gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
+
break;
}
children = children->next;
num++;
}
- if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
- gtk_widget_grab_focus (widget);
return TRUE;
}
+static void
+stop_scrolling (GtkNotebook *notebook)
+{
+ if (notebook->timer)
+ {
+ g_source_remove (notebook->timer);
+ notebook->timer = 0;
+ notebook->need_timer = FALSE;
+ }
+ notebook->click_child = 0;
+ notebook->button = 0;
+ gtk_notebook_redraw_arrows (notebook);
+}
+
static gint
gtk_notebook_button_release (GtkWidget *widget,
GdkEventButton *event)
if (event->button == notebook->button)
{
- guint click_child;
-
- if (notebook->timer)
- {
- gtk_timeout_remove (notebook->timer);
- notebook->timer = 0;
- notebook->need_timer = FALSE;
- }
- click_child = notebook->click_child;
- notebook->click_child = 0;
- notebook->button = 0;
- gtk_notebook_redraw_arrows (notebook);
+ stop_scrolling (notebook);
return TRUE;
}
GdkEventCrossing *event)
{
GtkNotebook *notebook;
- GtkArrowType arrow;
+ GtkNotebookArrow arrow;
gint x, y;
g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
GdkEventCrossing *event)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkArrowType arrow;
+ GtkNotebookArrow arrow;
gint x, y;
if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
GdkEventMotion *event)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkArrowType arrow;
+ GtkNotebookArrow arrow;
gint x, y;
if (notebook->button)
return TRUE;
}
+static void
+gtk_notebook_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed)
+{
+ if (!was_grabbed)
+ stop_scrolling (GTK_NOTEBOOK (widget));
+}
+
+static void
+gtk_notebook_state_changed (GtkWidget *widget,
+ GtkStateType previous_state)
+{
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ stop_scrolling (GTK_NOTEBOOK (widget));
+}
+
static gint
gtk_notebook_focus_in (GtkWidget *widget,
GdkEventFocus *event)
{
GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
- return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
+ gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
+
+ return FALSE;
+}
+
+static gint
+gtk_notebook_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
+
+ return FALSE;
}
static void
}
}
+static void
+gtk_notebook_style_set (GtkWidget *widget,
+ GtkStyle *previous)
+{
+ GtkNotebook *notebook;
+
+ gboolean has_before_previous;
+ gboolean has_before_next;
+ gboolean has_after_previous;
+ gboolean has_after_next;
+
+ notebook = GTK_NOTEBOOK (widget);
+
+ gtk_widget_style_get (widget,
+ "has_backward_stepper", &has_before_previous,
+ "has_secondary_forward_stepper", &has_before_next,
+ "has_secondary_backward_stepper", &has_after_previous,
+ "has_forward_stepper", &has_after_next,
+ NULL);
+
+ notebook->has_before_previous = has_before_previous;
+ notebook->has_before_next = has_before_next;
+ notebook->has_after_previous = has_after_previous;
+ notebook->has_after_next = has_after_next;
+
+ (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
+}
+
/* Private GtkContainer Methods :
*
* gtk_notebook_set_child_arg
GtkNotebook *notebook;
GtkNotebookPage *page;
GList *children;
- guint page_num;
g_return_if_fail (GTK_IS_NOTEBOOK (container));
g_return_if_fail (widget != NULL);
notebook = GTK_NOTEBOOK (container);
children = notebook->children;
- page_num = 0;
while (children)
{
page = children->data;
if (page->child == widget)
{
- gtk_notebook_real_remove (notebook, children);
+ gtk_notebook_real_remove (notebook, children, FALSE);
break;
}
- page_num++;
children = children->next;
}
}
new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
search_direction, TRUE);
- if (!new_page)
- new_page = (search_direction == STEP_NEXT) ?
- notebook->children :
- g_list_last (notebook->children);
-
- gtk_notebook_switch_focus_tab (notebook, new_page);
+ if (new_page)
+ gtk_notebook_switch_focus_tab (notebook, new_page);
+ else
+ gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
return TRUE;
}
focus_child_in (GtkNotebook *notebook,
GtkDirectionType direction)
{
- return gtk_widget_child_focus (notebook->cur_page->child, direction);
+ if (notebook->cur_page)
+ return gtk_widget_child_focus (notebook->cur_page->child, direction);
+ else
+ return FALSE;
}
/* Focus in the notebook can either be on the pages, or on
GtkNotebook *notebook;
GtkDirectionType effective_direction;
- /* Remap the directions into the effective direction it would be for a
- * GTK_POS_TOP notebook
- */
-#define D(rest) GTK_DIR_##rest
-
- static const GtkDirectionType translate_direction[4][6] = {
- /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
- /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
- /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
- /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
- };
-
-#undef D
-
gboolean widget_is_focus;
GtkContainer *container;
container = GTK_CONTAINER (widget);
notebook = GTK_NOTEBOOK (container);
+ if (notebook->focus_out)
+ {
+ notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
+ return FALSE;
+ }
+
widget_is_focus = gtk_widget_is_focus (widget);
old_focus_child = container->focus_child;
- effective_direction = translate_direction[notebook->tab_pos][direction];
+ effective_direction = get_effective_direction (notebook, direction);
if (old_focus_child) /* Focus on page child */
{
return FALSE;
case GTK_DIR_TAB_FORWARD:
case GTK_DIR_DOWN:
- return focus_child_in (notebook, direction);
+ /* 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);
case GTK_DIR_LEFT:
return focus_tabs_move (notebook, direction, STEP_PREV);
case GTK_DIR_RIGHT:
g_assert_not_reached ();
return FALSE;
}
-
+
static void
gtk_notebook_set_focus_child (GtkContainer *container,
GtkWidget *child)
if (page_child->parent == GTK_WIDGET (container))
{
GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
- GtkNotebookPage *page = list->data;
-
- if (page->last_focus_child)
- g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
-
- page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
- g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
+ if (list != NULL)
+ {
+ GtkNotebookPage *page = list->data;
- break;
+ if (page->last_focus_child)
+ g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
+
+ page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
+ g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
+
+ break;
+ }
}
page_child = page_child->parent;
{
if (page->tab_label)
(* callback) (page->tab_label, callback_data);
- if (page->menu_label)
- (* callback) (page->menu_label, callback_data);
}
}
}
-static GtkType
+static GType
gtk_notebook_child_type (GtkContainer *container)
{
return GTK_TYPE_WIDGET;
/* Private GtkNotebook Functions:
*
* gtk_notebook_redraw_tabs
- * gtk_notebook_focus_changed
* gtk_notebook_real_remove
* gtk_notebook_update_labels
* gtk_notebook_timer
GtkNotebookPage *page;
GdkRectangle redraw_rect;
gint border;
+ gint tab_pos = get_effective_tab_pos (notebook);
widget = GTK_WIDGET (notebook);
border = GTK_CONTAINER (notebook)->border_width;
redraw_rect.x = border;
redraw_rect.y = border;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_BOTTOM:
redraw_rect.y = (widget->allocation.height - border -
static void
gtk_notebook_redraw_arrows (GtkNotebook *notebook)
{
- if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
- {
- GdkRectangle rect;
-
- gtk_notebook_get_arrow_rect (notebook, &rect);
- gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
- }
-}
-
-static void
-gtk_notebook_focus_changed (GtkNotebook *notebook,
- GtkNotebookPage *old_page)
-{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
- if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
- {
- GdkRectangle area;
- gint focus_width;
-
- gtk_widget_style_get (GTK_WIDGET (notebook), "focus-line-width", &focus_width, NULL);
-
- if (notebook->focus_tab)
- {
- GtkNotebookPage *page;
-
- page = notebook->focus_tab->data;
-
- area.x = page->tab_label->allocation.x - focus_width;
- area.y = page->tab_label->allocation.y - focus_width;
- area.width = page->tab_label->allocation.width + 2 * focus_width;
- area.height = page->tab_label->allocation.height + 2 * focus_width;
+ if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
+ {
+ GdkRectangle rect;
+ gint i;
+ GtkNotebookArrow arrow[4];
- gtk_notebook_draw_tab (notebook, page, &area);
- }
+ arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
+ arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
+ arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
+ arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
- if (old_page)
+ for (i = 0; i < 4; i++)
{
- area.x = old_page->tab_label->allocation.x - focus_width;
- area.y = old_page->tab_label->allocation.y - focus_width;
- area.width = old_page->tab_label->allocation.width + 2 * focus_width;
- area.height = old_page->tab_label->allocation.height + 2 * focus_width;
-
- gtk_notebook_draw_tab (notebook, old_page, &area);
+ if (arrow[i] == ARROW_NONE)
+ continue;
+
+ gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
+ gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
+ &rect, FALSE);
}
}
}
gboolean retval = FALSE;
GDK_THREADS_ENTER ();
-
+
if (notebook->timer)
{
- if (notebook->click_child == GTK_ARROW_LEFT)
- {
- if (!notebook->focus_tab ||
- gtk_notebook_search_page (notebook, notebook->focus_tab,
- STEP_PREV, TRUE))
- gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_LEFT);
- }
- else if (notebook->click_child == GTK_ARROW_RIGHT)
- {
- if (!notebook->focus_tab ||
- gtk_notebook_search_page (notebook, notebook->focus_tab,
- STEP_NEXT, TRUE))
- gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_RIGHT);
- }
+ gtk_notebook_do_arrow (notebook, notebook->click_child);
+
if (notebook->need_timer)
{
notebook->need_timer = FALSE;
- notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
- (GtkFunction) gtk_notebook_timer,
- (gpointer) notebook);
+ notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
+ (GSourceFunc) gtk_notebook_timer,
+ (gpointer) notebook);
}
else
retval = TRUE;
if (page->tab_label)
{
if (page->mnemonic_activate_signal)
- gtk_signal_disconnect (page->tab_label,
- page->mnemonic_activate_signal);
+ g_signal_handler_disconnect (page->tab_label,
+ page->mnemonic_activate_signal);
page->mnemonic_activate_signal = 0;
+ gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
gtk_widget_unparent (page->tab_label);
}
}
static void
gtk_notebook_real_remove (GtkNotebook *notebook,
- GList *list)
+ GList *list,
+ gboolean destroying)
{
GtkNotebookPage *page;
GList * next_list;
if (notebook->cur_page == list->data)
{
notebook->cur_page = NULL;
- if (next_list)
+ if (next_list && !destroying)
gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
}
if (list == notebook->first_tab)
notebook->first_tab = next_list;
- if (list == notebook->focus_tab)
+ if (list == notebook->focus_tab && !destroying)
gtk_notebook_switch_focus_tab (notebook, next_list);
page = list->data;
-
- if (page->last_focus_child)
- g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
need_resize = TRUE;
gtk_widget_queue_resize (notebook->menu);
}
if (!page->default_menu)
- gtk_widget_unref (page->menu_label);
+ g_object_unref (page->menu_label);
notebook->children = g_list_remove_link (notebook->children, list);
g_list_free (list);
- g_free (page);
- if (!notebook->children && notebook->show_tabs &&
- GTK_WIDGET_MAPPED (notebook))
- gdk_window_hide (notebook->event_window);
+ if (page->last_focus_child)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
+ page->last_focus_child = NULL;
+ }
+
+ g_free (page);
gtk_notebook_update_labels (notebook);
if (need_resize)
gint width, height;
gint x, y;
gint border_width = GTK_CONTAINER (widget)->border_width;
- gint gap_x = 0, gap_width = 0;
+ gint gap_x = 0, gap_width = 0, step = STEP_PREV;
+ gboolean is_rtl;
+ gint tab_pos;
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
g_return_if_fail (area != NULL);
return;
notebook = GTK_NOTEBOOK (widget);
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+ tab_pos = get_effective_tab_pos (notebook);
if ((!notebook->show_tabs && !notebook->show_border) ||
!notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
{
page = notebook->first_tab->data;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
y += page->allocation.height + widget->style->ythickness;
}
else
{
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
y += notebook->cur_page->allocation.height;
break;
}
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
gap_width = notebook->cur_page->allocation.width;
+ step = is_rtl ? STEP_NEXT : STEP_PREV;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
gap_width = notebook->cur_page->allocation.height;
+ step = STEP_PREV;
break;
}
- gtk_paint_box_gap(widget->style, widget->window,
- GTK_STATE_NORMAL, GTK_SHADOW_OUT,
- area, widget, "notebook",
- x, y, width, height,
- notebook->tab_pos, gap_x, gap_width);
+ gtk_paint_box_gap (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ area, widget, "notebook",
+ x, y, width, height,
+ tab_pos, gap_x, gap_width);
}
showarrow = FALSE;
- children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
+ children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
while (children)
{
page = children->data;
children = gtk_notebook_search_page (notebook, children,
- STEP_PREV, TRUE);
+ step, TRUE);
if (!GTK_WIDGET_VISIBLE (page->child))
continue;
if (!GTK_WIDGET_MAPPED (page->tab_label))
if (showarrow && notebook->scrollable)
{
- gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
- gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
+ if (notebook->has_before_previous)
+ gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
+ if (notebook->has_before_next)
+ gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
+ if (notebook->has_after_previous)
+ gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
+ if (notebook->has_after_next)
+ gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
}
gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
}
GdkRectangle page_area;
GtkStateType state_type;
GtkPositionType gap_side;
+ gint tab_pos = get_effective_tab_pos (notebook);
g_return_if_fail (notebook != NULL);
g_return_if_fail (page != NULL);
widget = GTK_WIDGET (notebook);
gap_side = 0;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
gap_side = GTK_POS_BOTTOM;
if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
GTK_WIDGET_DRAWABLE (page->tab_label))
{
- GdkEventExpose expose_event;
+ GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
/* This is a lame hack since all this code needs rewriting anyhow */
- expose_event.window = page->tab_label->window;
- expose_event.area = child_area;
- expose_event.region = gdk_region_rectangle (&child_area);
- expose_event.send_event = TRUE;
- expose_event.type = GDK_EXPOSE;
- expose_event.count = 0;
+ expose_event->expose.window = g_object_ref (page->tab_label->window);
+ expose_event->expose.area = child_area;
+ expose_event->expose.region = gdk_region_rectangle (&child_area);
+ expose_event->expose.send_event = TRUE;
+ expose_event->expose.count = 0;
- gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
+ gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
- gdk_region_destroy (expose_event.region);
+ gdk_event_free (expose_event);
}
}
}
static void
-gtk_notebook_draw_arrow (GtkNotebook *notebook,
- guint arrow)
+gtk_notebook_draw_arrow (GtkNotebook *notebook,
+ GtkNotebookArrow nbarrow)
{
GtkStateType state_type;
GtkShadowType shadow_type;
GtkWidget *widget;
GdkRectangle arrow_rect;
+ GtkArrowType arrow;
+ gboolean is_rtl, left;
- gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
+ gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ widget = GTK_WIDGET (notebook);
- widget = GTK_WIDGET(notebook);
+ is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+ left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
+ (!ARROW_IS_LEFT (nbarrow) && is_rtl);
if (GTK_WIDGET_DRAWABLE (notebook))
{
- if (notebook->in_child == arrow)
+ if (notebook->in_child == nbarrow)
{
- if (notebook->click_child == arrow)
+ if (notebook->click_child == nbarrow)
state_type = GTK_STATE_ACTIVE;
else
state_type = GTK_STATE_PRELIGHT;
}
else
- state_type = GTK_STATE_NORMAL;
+ state_type = GTK_WIDGET_STATE (widget);
- if (notebook->click_child == arrow)
+ if (notebook->click_child == nbarrow)
shadow_type = GTK_SHADOW_IN;
else
shadow_type = GTK_SHADOW_OUT;
- if (arrow == GTK_ARROW_LEFT)
+ if (notebook->focus_tab &&
+ !gtk_notebook_search_page (notebook, notebook->focus_tab,
+ left? STEP_PREV : STEP_NEXT, TRUE))
{
- if (notebook->focus_tab &&
- !gtk_notebook_search_page (notebook, notebook->focus_tab,
- STEP_PREV, TRUE))
- {
- shadow_type = GTK_SHADOW_ETCHED_IN;
- state_type = GTK_STATE_INSENSITIVE;
- }
-
- if (notebook->tab_pos == GTK_POS_LEFT ||
- notebook->tab_pos == GTK_POS_RIGHT)
- arrow = GTK_ARROW_UP;
-
- gtk_paint_arrow (widget->style, widget->window, state_type,
- shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
- arrow, TRUE,
- arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
+ shadow_type = GTK_SHADOW_ETCHED_IN;
+ state_type = GTK_STATE_INSENSITIVE;
}
+
+ if (notebook->tab_pos == GTK_POS_LEFT ||
+ notebook->tab_pos == GTK_POS_RIGHT)
+ arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
else
- {
- if (notebook->focus_tab &&
- !gtk_notebook_search_page (notebook, notebook->focus_tab,
- STEP_NEXT, TRUE))
- {
- shadow_type = GTK_SHADOW_ETCHED_IN;
- state_type = GTK_STATE_INSENSITIVE;
- }
-
- if (notebook->tab_pos == GTK_POS_LEFT ||
- notebook->tab_pos == GTK_POS_RIGHT)
- arrow = GTK_ARROW_DOWN;
-
- gtk_paint_arrow (widget->style, widget->window, state_type,
- shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
- arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
- arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
- }
+ arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
+
+ gtk_paint_arrow (widget->style, widget->window, state_type,
+ shadow_type, NULL, widget, "notebook",
+ arrow, TRUE, arrow_rect.x, arrow_rect.y,
+ ARROW_SIZE, ARROW_SIZE);
}
}
gboolean showarrow = FALSE;
gint tab_space = 0;
gint delta;
- gint x = 0;
- gint y = 0;
gint i;
gint n = 1;
gint old_fill = 0;
gint new_fill = 0;
+ gint tab_pos = get_effective_tab_pos (notebook);
+ gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
+ (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
+ gint memo_x;
if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
return;
child_allocation.x = widget->allocation.x + container->border_width;
child_allocation.y = widget->allocation.y + container->border_width;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_BOTTOM:
child_allocation.y = (widget->allocation.y +
else
focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
showarrow = TRUE;
page = focus_tab->data;
- tab_space = (allocation->width - TAB_OVERLAP -
- page->requisition.width -
- 2 * (container->border_width + ARROW_SPACING +
- ARROW_SIZE));
- x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
- container->border_width);
-
- page = notebook->children->data;
- if (notebook->tab_pos == GTK_POS_TOP)
- y = (container->border_width +
- (page->requisition.height - ARROW_SIZE) / 2);
- else
- y = (allocation->height - container->border_width -
- ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
+ tab_space = allocation->width - TAB_OVERLAP -
+ page->requisition.width - 2 * container->border_width;
+ if (notebook->has_after_previous)
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ if (notebook->has_after_next)
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ if (notebook->has_before_previous)
+ {
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ child_allocation.x += ARROW_SPACING + ARROW_SIZE;
+ }
+ if (notebook->has_before_next)
+ {
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ child_allocation.x += ARROW_SPACING + ARROW_SIZE;
+ }
}
break;
case GTK_POS_LEFT:
{
showarrow = TRUE;
page = focus_tab->data;
- tab_space = (allocation->height -
- ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
- 2 * container->border_width -
- page->requisition.height);
- y = allocation->height - container->border_width - ARROW_SIZE;
-
- page = notebook->children->data;
- if (notebook->tab_pos == GTK_POS_LEFT)
- x = (container->border_width +
- (page->requisition.width -
- (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
- else
- x = (allocation->width - container->border_width -
- (2 * ARROW_SIZE - ARROW_SPACING) -
- (page->requisition.width -
- (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
+ tab_space = allocation->height
+ - TAB_OVERLAP - 2 * container->border_width
+ - page->requisition.height;
+ if (notebook->has_after_previous || notebook->has_after_next)
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ if (notebook->has_before_previous || notebook->has_before_next)
+ {
+ tab_space -= ARROW_SPACING + ARROW_SIZE;
+ child_allocation.y += ARROW_SPACING + ARROW_SIZE;
+ }
}
break;
}
n = 0;
children = notebook->children;
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
}
children = notebook->first_tab;
- i = 1;
+ i = 1;
+
+ memo_x = child_allocation.x;
+ if (notebook->children && is_rtl)
+ {
+ child_allocation.x = (allocation->x + allocation->width -
+ container->border_width);
+ if (showarrow)
+ {
+ if (notebook->has_after_previous)
+ child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
+ if (notebook->has_after_next)
+ child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
+ }
+ }
+
while (children)
{
if (children == last_child)
}
page = children->data;
- if (!showarrow && page->pack != GTK_PACK_START)
+ if (!showarrow && page->pack != GTK_PACK_START)
break;
children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
old_fill = new_fill;
}
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
child_allocation.width = (page->requisition.width +
TAB_OVERLAP + delta);
+ if (is_rtl)
+ child_allocation.x -= child_allocation.width;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
}
gtk_notebook_page_allocate (notebook, page, &child_allocation);
-
- switch (notebook->tab_pos)
+
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- child_allocation.x += child_allocation.width - TAB_OVERLAP;
+ if (!is_rtl)
+ child_allocation.x += child_allocation.width - TAB_OVERLAP;
+ else
+ child_allocation.x += TAB_OVERLAP;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
if (children)
{
children = notebook->children;
- switch (notebook->tab_pos)
+
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- child_allocation.x = (allocation->x + allocation->width -
- container->border_width);
+ if (!is_rtl)
+ child_allocation.x = (allocation->x + allocation->width -
+ container->border_width);
+ else
+ child_allocation.x = memo_x;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
page = children->data;
children = children->next;
- if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
- continue;
+ if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
+ continue;
delta = 0;
if (n && (page->expand || notebook->homogeneous))
old_fill = new_fill;
}
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
child_allocation.width = (page->requisition.width +
TAB_OVERLAP + delta);
- child_allocation.x -= child_allocation.width;
+ if (!is_rtl)
+ child_allocation.x -= child_allocation.width;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
gtk_notebook_page_allocate (notebook, page, &child_allocation);
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- child_allocation.x += TAB_OVERLAP;
+ if (!is_rtl)
+ child_allocation.x += TAB_OVERLAP;
+ else
+ child_allocation.x += child_allocation.width - TAB_OVERLAP;
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
gint ythickness;
gint padding;
gint focus_width;
+ gint tab_pos = get_effective_tab_pos (notebook);
gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
xthickness = widget->style->xthickness;
ythickness = widget->style->ythickness;
- /* If the size of the notebook tabs change, we need to queue
- * a redraw on the tab area
- */
- if ((allocation->width != page->allocation.width) ||
- (allocation->height != page->allocation.height))
- {
- gint x, y, width, height, border_width;
-
- border_width = GTK_CONTAINER (notebook)->border_width;
-
- switch (notebook->tab_pos)
- {
- case GTK_POS_TOP:
- width = widget->allocation.width;
- height = MAX (page->allocation.height, allocation->height) + ythickness;
- x = 0;
- y = border_width;
- break;
-
- case GTK_POS_BOTTOM:
- width = widget->allocation.width + xthickness;
- height = MAX (page->allocation.height, allocation->height) + ythickness;
- x = 0;
- y = widget->allocation.height - height - border_width;
- break;
-
- case GTK_POS_LEFT:
- width = MAX (page->allocation.width, allocation->width) + xthickness;
- height = widget->allocation.height;
- x = border_width;
- y = 0;
- break;
-
- case GTK_POS_RIGHT:
- default: /* quiet gcc */
- width = MAX (page->allocation.width, allocation->width) + xthickness;
- height = widget->allocation.height;
- x = widget->allocation.width - width - border_width;
- y = 0;
- break;
- }
-
- gtk_widget_queue_clear_area (widget, x, y, width, height);
- }
-
page->allocation = *allocation;
gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
if (notebook->cur_page != page)
{
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
page->allocation.y += ythickness;
}
}
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
}
child_allocation.y = (notebook->tab_vborder + focus_width +
page->allocation.y);
- if (notebook->tab_pos == GTK_POS_TOP)
+ if (tab_pos == GTK_POS_TOP)
child_allocation.y += ythickness;
child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
2 * (notebook->tab_vborder + focus_width)));
child_allocation.height = tab_requisition.height;
}
child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
- if (notebook->tab_pos == GTK_POS_LEFT)
+ if (tab_pos == GTK_POS_LEFT)
child_allocation.x += xthickness;
child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
2 * (notebook->tab_hborder + focus_width)));
GList *children;
GList *last_list = NULL;
gboolean pack;
+ gint tab_pos = get_effective_tab_pos (notebook);
if (!start)
return;
while (1)
{
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
}
}
+static void
+gtk_notebook_update_tab_states (GtkNotebook *notebook)
+{
+ GList *list;
+
+ for (list = notebook->children; list != NULL; list = list->next)
+ {
+ GtkNotebookPage *page = list->data;
+
+ if (page->tab_label)
+ {
+ if (page == notebook->cur_page)
+ gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
+ else
+ gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
+ }
+ }
+}
+
/* Private GtkNotebook Page Switch Methods:
*
* gtk_notebook_real_switch_page
gtk_widget_grab_focus (GTK_WIDGET (notebook));
}
+ gtk_notebook_update_tab_states (notebook);
gtk_widget_queue_resize (GTK_WIDGET (notebook));
g_object_notify (G_OBJECT (notebook), "page");
}
if (page_num < 0)
page_num = g_list_index (notebook->children, page);
- gtk_signal_emit (GTK_OBJECT (notebook),
- notebook_signals[SWITCH_PAGE],
- page,
- page_num);
+ g_signal_emit (notebook,
+ notebook_signals[SWITCH_PAGE],
+ 0,
+ page,
+ page_num);
}
static gint
{
GtkNotebookPage *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 (move_focus)
{
- switch (notebook->tab_pos)
+ switch (tab_pos)
{
case GTK_POS_TOP:
dir = GTK_DIR_DOWN;
page = notebook->focus_tab->data;
if (GTK_WIDGET_MAPPED (page->tab_label))
- gtk_notebook_focus_changed (notebook, old_page);
+ gtk_notebook_redraw_tabs (notebook);
else
gtk_notebook_pages_allocate (notebook);
+
+ gtk_notebook_switch_page (notebook, page,
+ g_list_index (notebook->children, page));
}
static void
page_num++;
}
- gtk_signal_emit (GTK_OBJECT (notebook),
- notebook_signals[SWITCH_PAGE],
- page,
- page_num);
+ g_signal_emit (notebook,
+ notebook_signals[SWITCH_PAGE],
+ 0,
+ page,
+ page_num);
}
/* Private GtkNotebook Menu Functions:
gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
gtk_notebook_real_page_position (notebook, list));
- gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
- GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (gtk_notebook_menu_switch_page), page);
if (GTK_WIDGET_VISIBLE (page->child))
gtk_widget_show (menu_item);
}
notebook->menu = NULL;
}
+/* Private GtkNotebook Setter Functions:
+ *
+ * gtk_notebook_set_homogeneous_tabs_internal
+ * gtk_notebook_set_tab_border_internal
+ * gtk_notebook_set_tab_hborder_internal
+ * gtk_notebook_set_tab_vborder_internal
+ */
+static void
+gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
+ gboolean homogeneous)
+{
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ if (homogeneous == notebook->homogeneous)
+ return;
+
+ notebook->homogeneous = homogeneous;
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "homogeneous");
+}
+
+static void
+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;
+
+ if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_freeze_notify (G_OBJECT (notebook));
+ g_object_notify (G_OBJECT (notebook), "tab_hborder");
+ g_object_notify (G_OBJECT (notebook), "tab_vborder");
+ g_object_thaw_notify (G_OBJECT (notebook));
+}
+
+static void
+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;
+
+ notebook->tab_hborder = tab_hborder;
+
+ if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "tab_hborder");
+}
+
+static void
+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;
+
+ notebook->tab_vborder = tab_vborder;
+
+ if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "tab_vborder");
+}
+
/* Public GtkNotebook Page Insert/Remove Methods :
*
* gtk_notebook_append_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
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_append_page (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
+ 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);
- gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
+ return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
}
/**
*
* Appends a page to @notebook, specifying the widget to use as the
* label in the popup menu.
+ *
+ * Return value: the index (starting from 0) of the appended
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_append_page_menu (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label,
GtkWidget *menu_label)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
- g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
+ 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_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
+ return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
}
/**
* or %NULL to use the default label, 'page N'.
*
* Prepends a page to @notebook.
+ *
+ * Return value: the index (starting from 0) of the prepended
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_prepend_page (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
+ 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);
- gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
+ return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
}
/**
*
* Prepends a page to @notebook, specifying the widget to use as the
* label in the popup menu.
+ *
+ * Return value: the index (starting from 0) of the prepended
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label,
GtkWidget *menu_label)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
- g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
+ 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_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
+ return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
}
/**
* @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
+ * Insert a page into @notebook at the given position.
+ *
+ * Return value: the index (starting from 0) of the inserted
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_insert_page (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label,
gint position)
{
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
+ 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);
- gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
+ return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
}
*
* Insert a page into @notebook at the given position, specifying
* the widget to use as the label in the popup menu.
+ *
+ * Return value: the index (starting from 0) of the inserted
+ * page in the notebook, or -1 if function fails
**/
-void
+gint
gtk_notebook_insert_page_menu (GtkNotebook *notebook,
GtkWidget *child,
GtkWidget *tab_label,
GtkNotebookPage *page;
gint nchildren;
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
- g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
+ 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->menu_label = menu_label;
page->expand = FALSE;
page->fill = TRUE;
- page->pack = GTK_PACK_START;
+ page->pack = GTK_PACK_START;
if (!menu_label)
page->default_menu = TRUE;
else
{
- gtk_widget_ref (page->menu_label);
+ g_object_ref (page->menu_label);
gtk_object_sink (GTK_OBJECT (page->menu_label));
}
gtk_notebook_switch_focus_tab (notebook, NULL);
}
+ gtk_notebook_update_tab_states (notebook);
+
if (tab_label)
page->mnemonic_activate_signal =
- gtk_signal_connect (GTK_OBJECT (tab_label),
- "mnemonic_activate",
- (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
- notebook);
-
- if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
- gdk_window_show_unraised (notebook->event_window);
+ g_signal_connect (tab_label,
+ "mnemonic_activate",
+ G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
+ notebook);
gtk_widget_child_notify (child, "tab_expand");
gtk_widget_child_notify (child, "tab_fill");
gtk_widget_child_notify (child, "menu_label");
gtk_widget_child_notify (child, "position");
gtk_widget_thaw_child_notify (child);
+
+ return position;
}
/**
{
list = g_list_nth (notebook->children, page_num);
if (list)
- gtk_notebook_real_remove (notebook, list);
+ gtk_notebook_real_remove (notebook, list, FALSE);
}
else
{
list = g_list_last (notebook->children);
if (list)
- gtk_notebook_real_remove (notebook, list);
+ gtk_notebook_real_remove (notebook, list, FALSE);
}
}
/**
* gtk_notebook_get_nth_page:
* @notebook: a #GtkNotebook
- * @page_num: the index of a page in the noteobok
+ * @page_num: the index of a page in the noteobok, or -1
+ * to get the last page.
*
* Returns the child widget contained in page number @page_num.
*
gint page_num)
{
GtkNotebookPage *page;
+ GList *list;
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
- page = g_list_nth_data (notebook->children, page_num);
+ if (page_num >= 0)
+ list = g_list_nth (notebook->children, page_num);
+ else
+ list = g_list_last (notebook->children);
- if (page)
- return page->child;
+ if (list)
+ {
+ page = list->data;
+ return page->child;
+ }
return NULL;
}
+/**
+ * gtk_notebook_get_n_pages:
+ * @notebook: a #GtkNotebook
+ *
+ * Gets the number of pages in a notebook.
+ *
+ * Return value: the number of pages in the notebook.
+ *
+ * Since: 2.2
+ **/
+gint
+gtk_notebook_get_n_pages (GtkNotebook *notebook)
+{
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
+
+ return g_list_length (notebook->children);
+}
+
/**
* gtk_notebook_page_num:
* @notebook: a #GtkNotebook
* gtk_notebook_set_current_page:
* @notebook: a #GtkNotebook
* @page_num: index of the page to switch to, starting from 0.
- * If negative, or greater than the number of pages
- * in the notebook the last page will be used.
+ * If negative, the last page will be used. If greater
+ * than the number of pages in the notebook, nothing
+ * will be done.
*
* Switches to the page number @page_num.
**/
* @show_border: %TRUE if a bevel should be drawn around the notebook.
*
* Sets whether a bevel will be drawn around the notebook pages.
- * this is only has an effect when the tabs are not shown.
+ * This only has a visual effect when the tabs are not shown.
* See gtk_notebook_set_show_tabs().
**/
void
{
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- if (homogeneous == notebook->homogeneous)
- return;
-
- notebook->homogeneous = homogeneous;
- gtk_widget_queue_resize (GTK_WIDGET (notebook));
-
- g_object_notify (G_OBJECT (notebook), "homogeneous");
+ gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
}
/**
{
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- notebook->tab_hborder = border_width;
- notebook->tab_vborder = border_width;
-
- if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
- gtk_widget_queue_resize (GTK_WIDGET (notebook));
-
- g_object_freeze_notify (G_OBJECT (notebook));
- g_object_notify (G_OBJECT (notebook), "tab_hborder");
- g_object_notify (G_OBJECT (notebook), "tab_vborder");
- g_object_thaw_notify (G_OBJECT (notebook));
-
+ gtk_notebook_set_tab_border_internal (notebook, border_width);
}
/**
{
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- if (notebook->tab_hborder == tab_hborder)
- return;
-
- notebook->tab_hborder = tab_hborder;
-
- if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
- gtk_widget_queue_resize (GTK_WIDGET (notebook));
-
- g_object_notify (G_OBJECT (notebook), "tab_hborder");
+ gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
}
/**
{
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- if (notebook->tab_vborder == tab_vborder)
- return;
-
- notebook->tab_vborder = tab_vborder;
-
- if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
- gtk_widget_queue_resize (GTK_WIDGET (notebook));
-
- g_object_notify (G_OBJECT (notebook), "tab_vborder");
+ gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
}
/**
if (page->tab_label)
page->mnemonic_activate_signal =
- gtk_signal_connect (GTK_OBJECT (page->tab_label),
- "mnemonic_activate",
- (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
- notebook);
+ g_signal_connect (page->tab_label,
+ "mnemonic_activate",
+ G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
+ notebook);
if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
{
gtk_widget_show (page->tab_label);
gtk_widget_queue_resize (GTK_WIDGET (notebook));
}
+
+ gtk_notebook_update_tab_states (notebook);
gtk_widget_child_notify (child, "tab_label");
}
page->menu_label->parent);
if (!page->default_menu)
- gtk_widget_unref (page->menu_label);
+ g_object_unref (page->menu_label);
}
if (menu_label)
{
page->menu_label = menu_label;
- gtk_widget_ref (page->menu_label);
+ g_object_ref (page->menu_label);
gtk_object_sink (GTK_OBJECT(page->menu_label));
page->default_menu = FALSE;
}
gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
}
-
+
+ gtk_notebook_update_tab_states (notebook);
gtk_notebook_update_labels (notebook);
}
* gtk_notebook_reorder_child:
* @notebook: a #GtkNotebook
* @child: the child to move
- * @position: the new position
+ * @position: the new position, or -1 to move to the end
*
* Reorders the page containing @child, so that it appears in position
- * @position. Out of bounds @position will be clamped.
+ * @position. If @position is greater than or equal to the number of
+ * children in the list or negative, @child will be moved to the end
+ * of the list.
**/
void
gtk_notebook_reorder_child (GtkNotebook *notebook,
GList *list, *new_list;
GtkNotebookPage *page;
gint old_pos;
+ gint max_pos;
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
g_return_if_fail (GTK_IS_WIDGET (child));
if (!list)
return;
+ max_pos = g_list_length (notebook->children) - 1;
+ if (position < 0 || position > max_pos)
+ position = max_pos;
+
old_pos = g_list_position (notebook->children, list);
if (old_pos == position)
page = list->data;
notebook->children = g_list_delete_link (notebook->children, list);
- position = CLAMP (position, 0, g_list_length (notebook->children));
-
notebook->children = g_list_insert (notebook->children, page, position);
new_list = g_list_nth (notebook->children, position);
gtk_widget_freeze_child_notify (child);
- /* Move around the menu items if necesary */
+ /* Move around the menu items if necessary */
gtk_notebook_child_reordered (notebook, page);
gtk_widget_child_notify (child, "tab_pack");
gtk_widget_child_notify (child, "position");
gtk_widget_thaw_child_notify (child);
}
+
+#define __GTK_NOTEBOOK_C__
+#include "gtkaliasdef.c"