*/
#include "gtknotebook.h"
-#include "gtksignal.h"
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include <gdk/gdkkeysyms.h>
#include <stdio.h>
#include "gtkintl.h"
+#include "gtkmarshalers.h"
+#include "gtkbindings.h"
#define TAB_OVERLAP 2
#define TAB_CURVATURE 1
#define ARROW_SIZE 12
#define ARROW_SPACING 0
-#define FOCUS_WIDTH 1
#define NOTEBOOK_INIT_SCROLL_DELAY (200)
#define NOTEBOOK_SCROLL_DELAY (100)
enum {
SWITCH_PAGE,
+ FOCUS_TAB,
+ SELECT_PAGE,
+ CHANGE_CURRENT_PAGE,
+ MOVE_FOCUS_OUT,
LAST_SIGNAL
};
};
enum {
- ARG_0,
- ARG_TAB_POS,
- ARG_SHOW_TABS,
- ARG_SHOW_BORDER,
- ARG_SCROLLABLE,
- ARG_TAB_BORDER,
- ARG_TAB_HBORDER,
- ARG_TAB_VBORDER,
- ARG_PAGE,
- ARG_ENABLE_POPUP,
- ARG_HOMOGENEOUS
+ PROP_0,
+ PROP_TAB_POS,
+ PROP_SHOW_TABS,
+ PROP_SHOW_BORDER,
+ PROP_SCROLLABLE,
+ PROP_TAB_BORDER,
+ PROP_TAB_HBORDER,
+ PROP_TAB_VBORDER,
+ PROP_PAGE,
+ PROP_ENABLE_POPUP,
+ PROP_HOMOGENEOUS
};
enum {
- CHILD_ARG_0,
- CHILD_ARG_TAB_LABEL,
- CHILD_ARG_MENU_LABEL,
- CHILD_ARG_POSITION,
- CHILD_ARG_TAB_EXPAND,
- CHILD_ARG_TAB_FILL,
- CHILD_ARG_TAB_PACK
+ CHILD_PROP_0,
+ CHILD_PROP_TAB_LABEL,
+ CHILD_PROP_MENU_LABEL,
+ CHILD_PROP_POSITION,
+ CHILD_PROP_TAB_EXPAND,
+ CHILD_PROP_TAB_FILL,
+ CHILD_PROP_TAB_PACK
};
#define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
GtkWidget *child;
GtkWidget *tab_label;
GtkWidget *menu_label;
+ GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
guint default_menu : 1; /* If true, we create the menu label ourself */
guint default_tab : 1; /* If true, we create the tab label ourself */
#ifdef G_DISABLE_CHECKS
#define CHECK_FIND_CHILD(notebook, child) \
- gtk_notebook_find_child(notebook, child, \
- G_GNUC_PRETTY_FUNCTION)
+ gtk_notebook_find_child (notebook, child, G_STRLOC)
#else
#define CHECK_FIND_CHILD(notebook, child) \
- gtk_notebook_find_child(notebook, child, NULL)
+ gtk_notebook_find_child (notebook, child, NULL)
#endif
/*** GtkNotebook Methods ***/
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 void gtk_notebook_move_focus_out (GtkNotebook *notebook,
+ GtkDirectionType direction_type);
+
/*** GtkObject Methods ***/
static void gtk_notebook_destroy (GtkObject *object);
-static void gtk_notebook_set_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
-static void gtk_notebook_get_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
+static void gtk_notebook_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_notebook_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
/*** GtkWidget Methods ***/
static void gtk_notebook_map (GtkWidget *widget);
GdkEventCrossing *event);
static gint gtk_notebook_motion_notify (GtkWidget *widget,
GdkEventMotion *event);
-static gint gtk_notebook_key_press (GtkWidget *widget,
- GdkEventKey *event);
static gint gtk_notebook_focus_in (GtkWidget *widget,
GdkEventFocus *event);
static void gtk_notebook_draw_focus (GtkWidget *widget);
-static void gtk_notebook_style_set (GtkWidget *widget,
- GtkStyle *previous_style);
+static gint gtk_notebook_focus (GtkWidget *widget,
+ GtkDirectionType direction);
/*** GtkContainer Methods ***/
-static void gtk_notebook_set_child_arg (GtkContainer *container,
+static void gtk_notebook_set_child_property (GtkContainer *container,
GtkWidget *child,
- GtkArg *arg,
- guint arg_id);
-static void gtk_notebook_get_child_arg (GtkContainer *container,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_notebook_get_child_property (GtkContainer *container,
GtkWidget *child,
- GtkArg *arg,
- guint arg_id);
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
static void gtk_notebook_add (GtkContainer *container,
GtkWidget *widget);
static void gtk_notebook_remove (GtkContainer *container,
GtkWidget *widget);
-static gint gtk_notebook_focus (GtkContainer *container,
- GtkDirectionType direction);
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,
gpointer callback_data);
/*** GtkNotebook Private Functions ***/
-static void gtk_notebook_panel_realize (GtkNotebook *notebook);
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,
gconstpointer b);
-static GList *gtk_notebook_find_child (GtkNotebook *notebook,
+static GList* gtk_notebook_find_child (GtkNotebook *notebook,
GtkWidget *child,
const gchar *function);
static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
GdkRectangle *area);
static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
guint arrow);
-static void gtk_notebook_set_shape (GtkNotebook *notebook);
/*** 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 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
-gtk_notebook_class_init (GtkNotebookClass *class)
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ GtkDirectionType direction)
{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
+ 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);
+}
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
- container_class = (GtkContainerClass*) class;
- parent_class = gtk_type_class (gtk_container_get_type ());
+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)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GtkBindingSet *binding_set;
+
+ parent_class = g_type_class_peek_parent (class);
- object_class->set_arg = gtk_notebook_set_arg;
- object_class->get_arg = gtk_notebook_get_arg;
+ gobject_class->set_property = gtk_notebook_set_property;
+ gobject_class->get_property = gtk_notebook_get_property;
object_class->destroy = gtk_notebook_destroy;
widget_class->map = gtk_notebook_map;
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->key_press_event = gtk_notebook_key_press;
widget_class->focus_in_event = gtk_notebook_focus_in;
- widget_class->style_set = gtk_notebook_style_set;
-
+ widget_class->focus = gtk_notebook_focus;
+
container_class->add = gtk_notebook_add;
container_class->remove = gtk_notebook_remove;
container_class->forall = gtk_notebook_forall;
- container_class->focus = gtk_notebook_focus;
container_class->set_focus_child = gtk_notebook_set_focus_child;
- container_class->get_child_arg = gtk_notebook_get_child_arg;
- container_class->set_child_arg = gtk_notebook_set_child_arg;
+ container_class->get_child_property = gtk_notebook_get_child_property;
+ container_class->set_child_property = gtk_notebook_set_child_property;
container_class->child_type = gtk_notebook_child_type;
class->switch_page = gtk_notebook_real_switch_page;
- gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
- gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
- gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_WRITABLE, ARG_TAB_BORDER);
- gtk_object_add_arg_type ("GtkNotebook::tab_hborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_HBORDER);
- gtk_object_add_arg_type ("GtkNotebook::tab_vborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_VBORDER);
- gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
- gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
- gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
- gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
- gtk_object_add_arg_type ("GtkNotebook::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
-
- gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
- gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
- gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
- gtk_container_add_child_arg_type ("GtkNotebook::tab_fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_FILL);
- gtk_container_add_child_arg_type ("GtkNotebook::tab_pack", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_PACK);
-
+ 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"),
+ 0,
+ G_MAXINT,
+ 0,
+ G_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"),
+ GTK_TYPE_POSITION_TYPE,
+ GTK_POS_TOP,
+ G_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"),
+ 0,
+ G_MAXUINT,
+ 2,
+ G_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"),
+ 0,
+ G_MAXUINT,
+ 2,
+ G_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"),
+ 0,
+ G_MAXUINT,
+ 2,
+ G_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"),
+ TRUE,
+ G_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"),
+ TRUE,
+ G_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 too many tabs to fit"),
+ FALSE,
+ G_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"),
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_HOMOGENEOUS,
+ g_param_spec_boolean ("homogeneous",
+ _("Homogeneous"),
+ _("Whether tabs should have homogeneous sizes"),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_TAB_LABEL,
+ g_param_spec_string ("tab_label",
+ _("Tab label"),
+ _("The string displayed on the childs tab label"),
+ NULL,
+ G_PARAM_READWRITE));
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_MENU_LABEL,
+ g_param_spec_string ("menu_label",
+ _("Menu label"),
+ _("The string displayed in the childs menu entry"),
+ NULL,
+ G_PARAM_READWRITE));
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_POSITION,
+ g_param_spec_int ("position",
+ _("Position"),
+ _("The index of the child in the parent"),
+ -1, G_MAXINT, 0,
+ G_PARAM_READWRITE));
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_TAB_EXPAND,
+ g_param_spec_boolean ("tab_expand",
+ _("Tab expand"),
+ _("Whether to expand the childs tab or not"),
+ TRUE,
+ G_PARAM_READWRITE));
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_TAB_FILL,
+ g_param_spec_boolean ("tab_fill",
+ _("Tab fill"),
+ _("Wheather the childs tab should fill the allocated area or not"),
+ TRUE,
+ G_PARAM_READWRITE));
+ gtk_container_class_install_child_property (container_class,
+ CHILD_PROP_TAB_PACK,
+ g_param_spec_enum ("tab_pack",
+ _("Tab pack type"),
+ _("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));
+
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 (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
+ NULL, NULL,
+ _gtk_marshal_BOOLEAN__ENUM,
+ G_TYPE_BOOLEAN, 1,
+ GTK_TYPE_NOTEBOOK_TAB);
+ notebook_signals[SELECT_PAGE] =
+ g_signal_new ("select_page",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkNotebookClass, select_page),
+ NULL, NULL,
+ _gtk_marshal_BOOLEAN__BOOLEAN,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_BOOLEAN);
+ notebook_signals[CHANGE_CURRENT_PAGE] =
+ g_signal_new ("change_current_page",
+ 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_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 (class);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_space, 0,
+ "select_page", 1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KP_Space, 0,
+ "select_page", 1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Home, 0,
+ "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,
+ GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_End, 0,
+ "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,
+ 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,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Page_Down, GDK_CONTROL_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_UNSET_FLAGS (notebook, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
+ GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
notebook->cur_page = NULL;
notebook->children = NULL;
notebook->first_tab = NULL;
notebook->focus_tab = NULL;
- notebook->panel = NULL;
+ notebook->event_window = NULL;
notebook->menu = NULL;
notebook->tab_hborder = 2;
notebook->need_timer = 0;
notebook->child_has_focus = FALSE;
notebook->have_visible_child = FALSE;
+ notebook->focus_out = FALSE;
+}
+
+static gboolean
+gtk_notebook_select_page (GtkNotebook *notebook,
+ gboolean move_focus)
+{
+ if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
+ {
+ gtk_notebook_page_select (notebook, move_focus);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+gtk_notebook_focus_tab (GtkNotebook *notebook,
+ GtkNotebookTab type)
+{
+ GList *list;
+
+ if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
+ {
+ switch (type)
+ {
+ case GTK_NOTEBOOK_TAB_FIRST:
+ list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
+ if (list)
+ gtk_notebook_switch_focus_tab (notebook, list);
+ break;
+ case GTK_NOTEBOOK_TAB_LAST:
+ list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
+ if (list)
+ gtk_notebook_switch_focus_tab (notebook, list);
+ break;
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+gtk_notebook_change_current_page (GtkNotebook *notebook,
+ gint offset)
+{
+ GList *current = NULL;
+
+ if (notebook->cur_page)
+ current = g_list_find (notebook->children, notebook->cur_page);
+
+ while (offset != 0)
+ {
+ current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
+ offset += offset < 0 ? 1 : -1;
+ }
+
+ 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[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
+
+ return translate_direction[notebook->tab_pos][direction];
+}
+
+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)
{
- GtkNotebook *notebook;
+ GList *children;
+ GtkNotebook *notebook = GTK_NOTEBOOK (object);
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (object));
-
- 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);
}
static void
-gtk_notebook_set_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id)
+gtk_notebook_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GtkNotebook *notebook;
notebook = GTK_NOTEBOOK (object);
- switch (arg_id)
+ switch (prop_id)
{
- case ARG_SHOW_TABS:
- gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
+ case PROP_SHOW_TABS:
+ gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
break;
- case ARG_SHOW_BORDER:
- gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
+ case PROP_SHOW_BORDER:
+ gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
break;
- case ARG_SCROLLABLE:
- gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
+ case PROP_SCROLLABLE:
+ gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
break;
- case ARG_ENABLE_POPUP:
- if (GTK_VALUE_BOOL (*arg))
+ case PROP_ENABLE_POPUP:
+ if (g_value_get_boolean (value))
gtk_notebook_popup_enable (notebook);
else
gtk_notebook_popup_disable (notebook);
break;
- case ARG_HOMOGENEOUS:
- gtk_notebook_set_homogeneous_tabs (notebook, GTK_VALUE_BOOL (*arg));
+ case PROP_HOMOGENEOUS:
+ gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
break;
- case ARG_PAGE:
- gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
+ case PROP_PAGE:
+ gtk_notebook_set_current_page (notebook, g_value_get_int (value));
break;
- case ARG_TAB_POS:
- gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
+ case PROP_TAB_POS:
+ gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
break;
- case ARG_TAB_BORDER:
- gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
+ case PROP_TAB_BORDER:
+ gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
break;
- case ARG_TAB_HBORDER:
- gtk_notebook_set_tab_hborder (notebook, GTK_VALUE_UINT (*arg));
+ case PROP_TAB_HBORDER:
+ gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
break;
- case ARG_TAB_VBORDER:
- gtk_notebook_set_tab_vborder (notebook, GTK_VALUE_UINT (*arg));
+ case PROP_TAB_VBORDER:
+ gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
break;
default:
break;
}
static void
-gtk_notebook_get_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id)
+gtk_notebook_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkNotebook *notebook;
notebook = GTK_NOTEBOOK (object);
- switch (arg_id)
+ switch (prop_id)
{
- case ARG_SHOW_TABS:
- GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
+ case PROP_SHOW_TABS:
+ g_value_set_boolean (value, notebook->show_tabs);
break;
- case ARG_SHOW_BORDER:
- GTK_VALUE_BOOL (*arg) = notebook->show_border;
+ case PROP_SHOW_BORDER:
+ g_value_set_boolean (value, notebook->show_border);
break;
- case ARG_SCROLLABLE:
- GTK_VALUE_BOOL (*arg) = notebook->scrollable;
+ case PROP_SCROLLABLE:
+ g_value_set_boolean (value, notebook->scrollable);
break;
- case ARG_ENABLE_POPUP:
- GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
+ case PROP_ENABLE_POPUP:
+ g_value_set_boolean (value, notebook->menu != NULL);
break;
- case ARG_HOMOGENEOUS:
- GTK_VALUE_BOOL (*arg) = notebook->homogeneous;
+ case PROP_HOMOGENEOUS:
+ g_value_set_boolean (value, notebook->homogeneous);
break;
- case ARG_PAGE:
- GTK_VALUE_INT (*arg) = gtk_notebook_get_current_page (notebook);
+ case PROP_PAGE:
+ g_value_set_int (value, gtk_notebook_get_current_page (notebook));
break;
- case ARG_TAB_POS:
- GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
+ case PROP_TAB_POS:
+ g_value_set_enum (value, notebook->tab_pos);
break;
- case ARG_TAB_HBORDER:
- GTK_VALUE_UINT (*arg) = notebook->tab_hborder;
+ case PROP_TAB_HBORDER:
+ g_value_set_uint (value, notebook->tab_hborder);
break;
- case ARG_TAB_VBORDER:
- GTK_VALUE_UINT (*arg) = notebook->tab_vborder;
+ case PROP_TAB_VBORDER:
+ g_value_set_uint (value, notebook->tab_vborder);
break;
default:
- arg->type = GTK_TYPE_INVALID;
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
* gtk_notebook_enter_notify
* gtk_notebook_leave_notify
* gtk_notebook_motion_notify
- * gtk_notebook_key_press
* gtk_notebook_focus_in
* gtk_notebook_focus_out
* gtk_notebook_draw_focus
* gtk_notebook_style_set
*/
+static gboolean
+gtk_notebook_get_event_window_position (GtkNotebook *notebook,
+ GdkRectangle *rectangle)
+{
+ GtkWidget *widget = GTK_WIDGET (notebook);
+ gint border_width = GTK_CONTAINER (notebook)->border_width;
+ GtkNotebookPage *visible_page = NULL;
+ GList *tmp_list;
+
+ for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkNotebookPage *page = tmp_list->data;
+ if (GTK_WIDGET_VISIBLE (page->child))
+ {
+ 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)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ rectangle->width = widget->allocation.width - 2 * border_width;
+ rectangle->height = visible_page->requisition.height;
+ if (notebook->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 = visible_page->requisition.width;
+ rectangle->height = widget->allocation.height - 2 * border_width;
+ if (notebook->tab_pos == GTK_POS_RIGHT)
+ rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ if (rectangle)
+ {
+ rectangle->x = rectangle->y = 0;
+ rectangle->width = rectangle->height = 10;
+ }
+ }
+
+ return FALSE;
+}
+
static void
gtk_notebook_map (GtkWidget *widget)
{
GtkNotebookPage *page;
GList *children;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
}
}
- gdk_window_show (widget->window);
+ if (gtk_notebook_get_event_window_position (notebook, NULL))
+ gdk_window_show_unraised (notebook->event_window);
}
static void
gtk_notebook_unmap (GtkWidget *widget)
{
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
- gdk_window_hide (widget->window);
- if (GTK_NOTEBOOK (widget)->panel)
- gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
+
+ gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
+
+ GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
static void
GtkNotebook *notebook;
GdkWindowAttr attributes;
gint attributes_mask;
+ GdkRectangle event_window_pos;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
notebook = GTK_NOTEBOOK (widget);
GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
+ gtk_notebook_get_event_window_position (notebook, &event_window_pos);
+
+ widget->window = gtk_widget_get_parent_window (widget);
+ g_object_ref (widget->window);
+
attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.x = event_window_pos.x;
+ attributes.y = event_window_pos.y;
+ attributes.width = event_window_pos.width;
+ 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_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
- gdk_window_set_user_data (widget->window, notebook);
+ notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (notebook->event_window, notebook);
widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-
- gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
- if (notebook->scrollable)
- gtk_notebook_panel_realize (notebook);
}
static void
{
GtkNotebook *notebook;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
notebook = GTK_NOTEBOOK (widget);
- if (notebook->panel)
- {
- gdk_window_set_user_data (notebook->panel, NULL);
- gdk_window_destroy (notebook->panel);
- notebook->panel = NULL;
- }
+ gdk_window_set_user_data (notebook->event_window, NULL);
+ gdk_window_destroy (notebook->event_window);
+ notebook->event_window = NULL;
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
gtk_notebook_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
- GtkNotebook *notebook;
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPage *page;
GList *children;
GtkRequisition child_requisition;
gboolean switch_page = FALSE;
gint vis_pages;
+ gint focus_width;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
- g_return_if_fail (requisition != NULL);
-
- notebook = GTK_NOTEBOOK (widget);
+ gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
+
widget->requisition.width = 0;
widget->requisition.height = 0;
widget->requisition.height = MAX (widget->requisition.height,
child_requisition.height);
- if (GTK_WIDGET_MAPPED (page->child) && page != notebook->cur_page)
- gtk_widget_unmap (page->child);
if (notebook->menu && page->menu_label->parent &&
!GTK_WIDGET_VISIBLE (page->menu_label->parent))
gtk_widget_show (page->menu_label->parent);
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
page->requisition.height += 2 * (notebook->tab_vborder +
- FOCUS_WIDTH);
+ focus_width);
tab_height = MAX (tab_height, page->requisition.height);
tab_max = MAX (tab_max, page->requisition.width);
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
page->requisition.width += 2 * (notebook->tab_hborder +
- FOCUS_WIDTH);
+ focus_width);
tab_width = MAX (tab_width, page->requisition.width);
tab_max = MAX (tab_max, page->requisition.height);
break;
widget->requisition.width < tab_width)
tab_height = MAX (tab_height, ARROW_SIZE);
- padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
+ padding = 2 * (TAB_CURVATURE + focus_width +
notebook->tab_hborder) - TAB_OVERLAP;
tab_max += padding;
while (children)
widget->requisition.height < tab_height)
tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
- padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
+ padding = 2 * (TAB_CURVATURE + focus_width +
notebook->tab_vborder) - TAB_OVERLAP;
tab_max += padding;
gtk_notebook_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
- GtkNotebook *notebook;
- GtkNotebookPage *page;
- GtkAllocation child_allocation;
- GList *children;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
- g_return_if_fail (allocation != NULL);
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ gint vis_pages = 0;
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
- gdk_window_move_resize (widget->window,
- allocation->x, allocation->y,
- allocation->width, allocation->height);
+ {
+ 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);
+ }
- notebook = GTK_NOTEBOOK (widget);
if (notebook->children)
{
- child_allocation.x = GTK_CONTAINER (widget)->border_width;
- child_allocation.y = GTK_CONTAINER (widget)->border_width;
- child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
- child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
+ gint border_width = GTK_CONTAINER (widget)->border_width;
+ GtkNotebookPage *page;
+ GtkAllocation child_allocation;
+ GList *children;
+
+ child_allocation.x = widget->allocation.x + border_width;
+ child_allocation.y = widget->allocation.y + border_width;
+ child_allocation.width = MAX (1, allocation->width - border_width * 2);
+ child_allocation.height = MAX (1, allocation->height - border_width * 2);
if (notebook->show_tabs || notebook->show_border)
{
child_allocation.x += widget->style->xthickness;
child_allocation.y += widget->style->ythickness;
- child_allocation.width = MAX (1, (gint)child_allocation.width -
- (gint) widget->style->xthickness * 2);
- child_allocation.height = MAX (1, (gint)child_allocation.height -
- (gint) widget->style->ythickness * 2);
+ child_allocation.width = MAX (1, child_allocation.width -
+ widget->style->xthickness * 2);
+ child_allocation.height = MAX (1, child_allocation.height -
+ widget->style->ythickness * 2);
if (notebook->show_tabs && notebook->children && notebook->cur_page)
{
child_allocation.y += notebook->cur_page->requisition.height;
case GTK_POS_BOTTOM:
child_allocation.height =
- MAX (1, (gint)child_allocation.height -
- (gint)notebook->cur_page->requisition.height);
+ MAX (1, child_allocation.height -
+ notebook->cur_page->requisition.height);
break;
case GTK_POS_LEFT:
child_allocation.x += notebook->cur_page->requisition.width;
case GTK_POS_RIGHT:
child_allocation.width =
- MAX (1, (gint)child_allocation.width -
- (gint)notebook->cur_page->requisition.width);
+ MAX (1, child_allocation.width -
+ notebook->cur_page->requisition.width);
break;
}
}
children = children->next;
if (GTK_WIDGET_VISIBLE (page->child))
- gtk_widget_size_allocate (page->child, &child_allocation);
+ {
+ gtk_widget_size_allocate (page->child, &child_allocation);
+ vis_pages++;
+ }
}
gtk_notebook_pages_allocate (notebook);
}
- gtk_notebook_set_shape (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
GtkNotebook *notebook;
GdkRectangle child_area;
- g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
return FALSE;
}
+static gboolean
+gtk_notebook_show_arrows (GtkNotebook *notebook)
+{
+ gboolean show_arrow = FALSE;
+ GList *children;
+
+ if (!notebook->scrollable)
+ return FALSE;
+
+ children = notebook->children;
+ while (children)
+ {
+ GtkNotebookPage *page = children->data;
+
+ if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
+ show_arrow = TRUE;
+
+ children = children->next;
+ }
+
+ return show_arrow;
+}
+
+static void
+gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
+ GdkRectangle *rectangle)
+{
+ GdkRectangle event_window_pos;
+
+ if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
+ {
+ rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
+ rectangle->height = ARROW_SIZE;
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ 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;
+ break;
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
+ rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
+ break;
+ }
+ }
+}
+
+static GtkArrowType
+gtk_notebook_get_arrow (GtkNotebook *notebook,
+ gint x,
+ gint y)
+{
+ GdkRectangle arrow_rect;
+ GdkRectangle event_window_pos;
+
+ if (gtk_notebook_show_arrows (notebook))
+ {
+ gtk_notebook_get_event_window_position (notebook, &event_window_pos);
+ gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
+
+ x -= arrow_rect.x;
+ y -= arrow_rect.y;
+
+ 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;
+ }
+ }
+
+ return 0;
+}
+
+static void
+gtk_notebook_do_arrow (GtkNotebook *notebook,
+ GtkArrowType arrow)
+{
+ GtkWidget *widget = GTK_WIDGET (notebook);
+ 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);
+ }
+}
+
static gboolean
gtk_notebook_arrow_button_press (GtkNotebook *notebook,
+ GtkArrowType arrow,
GdkEventButton *event)
{
GtkWidget *widget = GTK_WIDGET (notebook);
- GtkArrowType arrow = event->x <= ARROW_SIZE + ARROW_SPACING / 2 ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT;
-
if (!GTK_WIDGET_HAS_FOCUS (widget))
gtk_widget_grab_focus (widget);
if (event->button == 1)
{
- if (!notebook->focus_tab ||
- gtk_notebook_search_page (notebook, notebook->focus_tab,
- arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
- TRUE))
- gtk_container_focus (GTK_CONTAINER (notebook),
- arrow == GTK_ARROW_LEFT ? GTK_DIR_LEFT : GTK_DIR_RIGHT);
+ gtk_notebook_do_arrow (notebook, arrow);
if (!notebook->timer)
{
return TRUE;
}
+static gboolean
+get_widget_coordinates (GtkWidget *widget,
+ GdkEvent *event,
+ gint *x,
+ gint *y)
+{
+ GdkWindow *window = ((GdkEventAny *)event)->window;
+ gdouble tx, ty;
+
+ if (!gdk_event_get_coords (event, &tx, &ty))
+ return FALSE;
+
+ while (window && window != widget->window)
+ {
+ gint window_x, window_y;
+
+ gdk_window_get_position (window, &window_x, &window_y);
+ tx += window_x;
+ ty += window_y;
+
+ window = gdk_window_get_parent (window);
+ }
+
+ if (window)
+ {
+ *x = tx;
+ *y = ty;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
static gboolean
gtk_notebook_button_press (GtkWidget *widget,
GdkEventButton *event)
{
- GtkNotebook *notebook;
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPage *page;
GList *children;
+ GtkArrowType arrow;
gint num;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- notebook = GTK_NOTEBOOK (widget);
+ gint x, y;
if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
notebook->button)
return FALSE;
- if (event->window == notebook->panel)
+ if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
+ return FALSE;
+
+ arrow = gtk_notebook_get_arrow (notebook, x, y);
+ if (arrow)
+ return gtk_notebook_arrow_button_press (notebook, arrow, event);
+
+ if (event->button == 3 && notebook->menu)
{
- return gtk_notebook_arrow_button_press (notebook, event);
+ gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
+ NULL, NULL, 3, event->time);
+ return TRUE;
}
- else if (event->window == widget->window)
- {
- if (event->button == 3 && notebook->menu)
- {
- gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
- NULL, NULL, 3, event->time);
- return TRUE;
- }
- num = 0;
- children = notebook->children;
- while (children)
+ if (event->button != 1)
+ return FALSE;
+
+ num = 0;
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+
+ if (GTK_WIDGET_VISIBLE (page->child) &&
+ page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
+ (x >= page->allocation.x) &&
+ (y >= page->allocation.y) &&
+ (x <= (page->allocation.x + page->allocation.width)) &&
+ (y <= (page->allocation.y + page->allocation.height)))
{
- page = children->data;
+ gboolean page_changed = page != notebook->cur_page;
+ gboolean was_focus = gtk_widget_is_focus (widget);
- if (GTK_WIDGET_VISIBLE (page->child) &&
- page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
- (event->x >= page->allocation.x) &&
- (event->y >= page->allocation.y) &&
- (event->x <= (page->allocation.x + page->allocation.width)) &&
- (event->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);
- }
- break;
- }
- children = children->next;
- num++;
+ 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;
}
- if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
- gtk_widget_grab_focus (widget);
- return TRUE;
+ children = children->next;
+ num++;
}
-
- return FALSE;
+ if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ return TRUE;
}
static gint
{
GtkNotebook *notebook;
- g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
GdkEventCrossing *event)
{
GtkNotebook *notebook;
+ GtkArrowType arrow;
+ gint x, y;
- g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
notebook = GTK_NOTEBOOK (widget);
- if (event->window == notebook->panel)
- {
- gint x;
- gint y;
-
- gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
+ if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
+ return FALSE;
- if (x <= ARROW_SIZE + ARROW_SPACING / 2)
- notebook->in_child = GTK_ARROW_LEFT;
- else
- notebook->in_child = GTK_ARROW_RIGHT;
+ arrow = gtk_notebook_get_arrow (notebook, x, y);
+ if (arrow != notebook->in_child)
+ {
+ notebook->in_child = arrow;
gtk_notebook_redraw_arrows (notebook);
+
+ return TRUE;
}
- return FALSE;
+ return TRUE;
}
static gint
gtk_notebook_leave_notify (GtkWidget *widget,
GdkEventCrossing *event)
{
- GtkNotebook *notebook;
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ GtkArrowType arrow;
+ gint x, y;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
+ return FALSE;
- notebook = GTK_NOTEBOOK (widget);
+ arrow = gtk_notebook_get_arrow (notebook, x, y);
- if (event->window == notebook->panel)
- gtk_notebook_redraw_arrows (notebook);
+ if (notebook->in_child)
+ {
+ notebook->in_child = 0;
+ gtk_notebook_redraw_arrows (notebook);
+ }
- return FALSE;
+ return TRUE;
}
static gint
gtk_notebook_motion_notify (GtkWidget *widget,
GdkEventMotion *event)
{
- GtkNotebook *notebook;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- notebook = GTK_NOTEBOOK (widget);
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ GtkArrowType arrow;
+ gint x, y;
if (notebook->button)
return FALSE;
- if (event->window == notebook->panel)
- {
- gint x;
- GtkArrowType old_child = notebook->in_child;
-
- x = event->x;
- if (event->is_hint)
- gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
-
- if (x <= ARROW_SIZE + ARROW_SPACING / 2)
- notebook->in_child = GTK_ARROW_LEFT;
- else
- notebook->in_child = GTK_ARROW_RIGHT;
-
- if (old_child != notebook->in_child)
- gtk_notebook_redraw_arrows (notebook);
- }
-
- return FALSE;
-}
-
-static gint
-gtk_notebook_key_press (GtkWidget *widget,
- GdkEventKey *event)
-{
- GtkNotebook *notebook;
- GList *list;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- notebook = GTK_NOTEBOOK (widget);
-
- if (!notebook->children || !notebook->show_tabs)
+ if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
return FALSE;
- switch (event->keyval)
- {
- case GDK_Home:
- list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
- if (list)
- gtk_notebook_switch_focus_tab (notebook, list);
- return TRUE;
- case GDK_End:
- list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
- if (list)
- gtk_notebook_switch_focus_tab (notebook, list);
- return TRUE;
- case GDK_Return:
- gtk_notebook_page_select (GTK_NOTEBOOK (widget), TRUE);
- return TRUE;
- case GDK_space:
- gtk_notebook_page_select (GTK_NOTEBOOK (widget), FALSE);
- return TRUE;
- }
+ arrow = gtk_notebook_get_arrow (notebook, x, y);
- return FALSE;
+ if (arrow != notebook->in_child)
+ {
+ notebook->in_child = arrow;
+ gtk_notebook_redraw_arrows (notebook);
+ }
+
+ return TRUE;
}
static gint
gtk_notebook_focus_in (GtkWidget *widget,
GdkEventFocus *event)
{
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
static void
gtk_notebook_draw_focus (GtkWidget *widget)
{
- GtkNotebook *notebook;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (widget));
-
- notebook = GTK_NOTEBOOK (widget);
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
notebook->focus_tab)
{
GtkNotebookPage *page;
GdkRectangle area;
+ gint focus_width;
+
+ gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
page = notebook->focus_tab->data;
- area.x = page->tab_label->allocation.x - 1;
- area.y = page->tab_label->allocation.y - 1;
- area.width = page->tab_label->allocation.width + 2;
- area.height = page->tab_label->allocation.height + 2;
+ 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;
gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
}
}
-static void
-gtk_notebook_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- if (GTK_WIDGET_REALIZED (widget) &&
- !GTK_WIDGET_NO_WINDOW (widget))
- {
- gtk_style_set_background (widget->style, widget->window, widget->state);
- if (GTK_WIDGET_DRAWABLE (widget))
- gdk_window_clear (widget->window);
- }
-
- gtk_notebook_set_shape (GTK_NOTEBOOK(widget));
-}
-
/* Private GtkContainer Methods :
*
* gtk_notebook_set_child_arg
* gtk_notebook_forall
*/
static void
-gtk_notebook_set_child_arg (GtkContainer *container,
- GtkWidget *child,
- GtkArg *arg,
- guint arg_id)
+gtk_notebook_set_child_property (GtkContainer *container,
+ GtkWidget *child,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
gboolean expand;
gboolean fill;
GtkPackType pack_type;
- switch (arg_id)
+ /* not finding child's page is valid for menus or labels */
+ if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
+ return;
+
+ switch (property_id)
{
- case CHILD_ARG_TAB_LABEL:
+ case CHILD_PROP_TAB_LABEL:
/* a NULL pointer indicates a default_tab setting, otherwise
* we need to set the associated label
*/
gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
- GTK_VALUE_STRING(*arg));
+ g_value_get_string (value));
break;
- case CHILD_ARG_MENU_LABEL:
+ case CHILD_PROP_MENU_LABEL:
gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
- GTK_VALUE_STRING (*arg));
+ g_value_get_string (value));
break;
- case CHILD_ARG_POSITION:
+ case CHILD_PROP_POSITION:
gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
- GTK_VALUE_INT (*arg));
+ g_value_get_int (value));
break;
- case CHILD_ARG_TAB_EXPAND:
+ case CHILD_PROP_TAB_EXPAND:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
&expand, &fill, &pack_type);
gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
- GTK_VALUE_BOOL (*arg),
+ g_value_get_boolean (value),
fill, pack_type);
break;
- case CHILD_ARG_TAB_FILL:
+ case CHILD_PROP_TAB_FILL:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
&expand, &fill, &pack_type);
gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
expand,
- GTK_VALUE_BOOL (*arg),
+ g_value_get_boolean (value),
pack_type);
break;
- case CHILD_ARG_TAB_PACK:
+ case CHILD_PROP_TAB_PACK:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
&expand, &fill, &pack_type);
gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
expand, fill,
- GTK_VALUE_BOOL (*arg));
+ g_value_get_enum (value));
break;
default:
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
break;
}
}
static void
-gtk_notebook_get_child_arg (GtkContainer *container,
- GtkWidget *child,
- GtkArg *arg,
- guint arg_id)
+gtk_notebook_get_child_property (GtkContainer *container,
+ GtkWidget *child,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GList *list;
GtkNotebook *notebook;
notebook = GTK_NOTEBOOK (container);
- arg->type = GTK_TYPE_INVALID;
-
- list = CHECK_FIND_CHILD (notebook, child);
- if (!list)
+ /* not finding child's page is valid for menus or labels */
+ list = gtk_notebook_find_child (notebook, child, NULL);
+ if (!list)
{
- arg->type = GTK_TYPE_INVALID;
+ /* nothing to set on labels or menus */
+ g_param_value_set_default (pspec, value);
return;
}
- switch (arg_id)
+ switch (property_id)
{
- case CHILD_ARG_TAB_LABEL:
+ case CHILD_PROP_TAB_LABEL:
label = gtk_notebook_get_tab_label (notebook, child);
if (label && GTK_IS_LABEL (label))
- GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
+ g_value_set_string (value, GTK_LABEL (label)->label);
else
- GTK_VALUE_STRING (*arg) = NULL;
+ g_value_set_string (value, NULL);
break;
- case CHILD_ARG_MENU_LABEL:
+ case CHILD_PROP_MENU_LABEL:
label = gtk_notebook_get_menu_label (notebook, child);
if (label && GTK_IS_LABEL (label))
- GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
+ g_value_set_string (value, GTK_LABEL (label)->label);
else
- GTK_VALUE_STRING (*arg) = NULL;
+ g_value_set_string (value, NULL);
break;
- case CHILD_ARG_POSITION:
- GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
+ case CHILD_PROP_POSITION:
+ g_value_set_int (value, g_list_position (notebook->children, list));
break;
- case CHILD_ARG_TAB_EXPAND:
+ case CHILD_PROP_TAB_EXPAND:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
&expand, NULL, NULL);
- GTK_VALUE_BOOL (*arg) = expand;
+ g_value_set_boolean (value, expand);
break;
- case CHILD_ARG_TAB_FILL:
+ case CHILD_PROP_TAB_FILL:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
NULL, &fill, NULL);
- GTK_VALUE_BOOL (*arg) = fill;
+ g_value_set_boolean (value, fill);
break;
- case CHILD_ARG_TAB_PACK:
+ case CHILD_PROP_TAB_PACK:
gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
NULL, NULL, &pack_type);
- GTK_VALUE_BOOL (*arg) = pack_type;
+ g_value_set_enum (value, pack_type);
break;
default:
- arg->type = GTK_TYPE_INVALID;
+ GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
break;
}
}
gtk_notebook_add (GtkContainer *container,
GtkWidget *widget)
{
- g_return_if_fail (container != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (container));
gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
GList *children;
guint page_num;
- g_return_if_fail (container != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (container));
g_return_if_fail (widget != NULL);
page = children->data;
if (page->child == widget)
{
- gtk_notebook_real_remove (notebook, children);
+ gtk_notebook_real_remove (notebook, children, FALSE);
break;
}
page_num++;
static gboolean
focus_tabs_in (GtkNotebook *notebook)
{
- if (notebook->cur_page)
+ if (notebook->show_tabs && notebook->cur_page)
{
gtk_widget_grab_focus (GTK_WIDGET (notebook));
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)
{
- if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) &&
- GTK_WIDGET_IS_SENSITIVE (notebook->cur_page->child))
- {
- if (GTK_IS_CONTAINER (notebook->cur_page->child))
- {
- if (gtk_container_focus (GTK_CONTAINER (notebook->cur_page->child), direction))
- return TRUE;
- }
- else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
- {
- gtk_widget_grab_focus (notebook->cur_page->child);
- return TRUE;
- }
- }
- return FALSE;
+ 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
* the tabs.
*/
static gint
-gtk_notebook_focus (GtkContainer *container,
+gtk_notebook_focus (GtkWidget *widget,
GtkDirectionType direction)
{
GtkWidget *old_focus_child;
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;
- g_return_val_if_fail (container != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
+ container = GTK_CONTAINER (widget);
notebook = GTK_NOTEBOOK (container);
- widget_is_focus = gtk_widget_is_focus (GTK_WIDGET (container));
- old_focus_child = container->focus_child;
+ if (notebook->focus_out)
+ {
+ notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
+ return FALSE;
+ }
- effective_direction = translate_direction[notebook->tab_pos][direction];
+ widget_is_focus = gtk_widget_is_focus (widget);
+ old_focus_child = container->focus_child;
- if (old_focus_child &&
- GTK_IS_CONTAINER (old_focus_child) &&
- GTK_WIDGET_DRAWABLE (old_focus_child) &&
- GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
- gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
- return TRUE;
+ effective_direction = get_effective_direction (notebook, direction);
if (old_focus_child) /* Focus on page child */
{
+ if (gtk_widget_child_focus (old_focus_child, direction))
+ return TRUE;
+
switch (effective_direction)
{
case GTK_DIR_TAB_BACKWARD:
case GTK_DIR_UP:
/* Focus onto the tabs */
- if (notebook->show_tabs)
- return focus_tabs_in (notebook);
- else
- return FALSE;
+ return focus_tabs_in (notebook);
case GTK_DIR_DOWN:
case GTK_DIR_TAB_FORWARD:
case GTK_DIR_LEFT:
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)
{
- GtkNotebook *notebook;
+ GtkNotebook *notebook = GTK_NOTEBOOK (container);
+ GtkWidget *page_child;
+ GtkWidget *toplevel;
- g_return_if_fail (container != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (container));
+ /* If the old focus widget was within a page of the notebook,
+ * (child may either be NULL or not in this case), record it
+ * for future use if we switch to the page with a mnemonic.
+ */
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
+ if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
+ {
+ page_child = GTK_WINDOW (toplevel)->focus_widget;
+ while (page_child)
+ {
+ if (page_child->parent == GTK_WIDGET (container))
+ {
+ GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
+ if (list != 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);
+
+ break;
+ }
+ }
+
+ page_child = page_child->parent;
+ }
+ }
if (child)
{
g_return_if_fail (GTK_IS_WIDGET (child));
- notebook = GTK_NOTEBOOK (container);
-
notebook->child_has_focus = TRUE;
if (!notebook->focus_tab)
{
}
}
}
+
parent_class->set_focus_child (container, child);
}
GtkNotebook *notebook;
GList *children;
- g_return_if_fail (container != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (container));
g_return_if_fail (callback != NULL);
}
}
-static GtkType
+static GType
gtk_notebook_child_type (GtkContainer *container)
{
return GTK_TYPE_WIDGET;
/* Private GtkNotebook Functions:
*
- * gtk_notebook_panel_realize
* gtk_notebook_redraw_tabs
- * gtk_notebook_focus_changed
* gtk_notebook_real_remove
* gtk_notebook_update_labels
* gtk_notebook_timer
* gtk_notebook_real_page_position
* gtk_notebook_search_page
*/
-static void
-gtk_notebook_panel_realize (GtkNotebook *notebook)
-{
- GtkWidget *widget;
- GdkWindowAttr attributes;
- gint attributes_mask;
-
- g_return_if_fail (notebook != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
- widget = GTK_WIDGET (notebook);
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = gtk_widget_get_events (widget);
- attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
- | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
- attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
- attributes.height = ARROW_SIZE;
-
- attributes.x = (widget->allocation.width - attributes.width -
- GTK_CONTAINER (notebook)->border_width);
- attributes.y = (widget->allocation.height - ARROW_SIZE -
- GTK_CONTAINER (notebook)->border_width);
- if (notebook->tab_pos == GTK_POS_TOP)
- attributes.y = GTK_CONTAINER (notebook)->border_width;
- else if (notebook->tab_pos == GTK_POS_LEFT)
- attributes.x = (widget->allocation.x +
- GTK_CONTAINER (notebook)->border_width);
-
- notebook->panel = gdk_window_new (widget->window, &attributes,
- attributes_mask);
- gtk_style_set_background (widget->style, notebook->panel,
- GTK_STATE_NORMAL);
- gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
- gdk_window_set_user_data (notebook->panel, widget);
-}
-
static void
gtk_notebook_redraw_tabs (GtkNotebook *notebook)
{
break;
}
+ redraw_rect.x += widget->allocation.x;
+ redraw_rect.y += widget->allocation.y;
+
gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
}
static void
gtk_notebook_redraw_arrows (GtkNotebook *notebook)
{
- if (GTK_WIDGET_MAPPED (notebook) && notebook->panel)
- gdk_window_invalidate_rect (notebook->panel, NULL, FALSE);
-}
-
-static void
-gtk_notebook_focus_changed (GtkNotebook *notebook,
- GtkNotebookPage *old_page)
-{
- g_return_if_fail (notebook != NULL);
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-
- if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
+ if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
{
- GdkRectangle area;
-
- if (notebook->focus_tab)
- {
- GtkNotebookPage *page;
-
- page = notebook->focus_tab->data;
-
- area.x = page->tab_label->allocation.x - 1;
- area.y = page->tab_label->allocation.y - 1;
- area.width = page->tab_label->allocation.width + 2;
- area.height = page->tab_label->allocation.height + 2;
-
- gtk_notebook_draw_tab (notebook, page, &area);
- }
-
- if (old_page)
- {
- area.x = old_page->tab_label->allocation.x - 1;
- area.y = old_page->tab_label->allocation.y - 1;
- area.width = old_page->tab_label->allocation.width + 2;
- area.height = old_page->tab_label->allocation.height + 2;
+ GdkRectangle rect;
- gtk_notebook_draw_tab (notebook, old_page, &area);
- }
+ gtk_notebook_get_arrow_rect (notebook, &rect);
+ 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_container_focus (GTK_CONTAINER (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_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
- }
+ gtk_notebook_do_arrow (notebook, notebook->click_child);
+
if (notebook->need_timer)
{
notebook->need_timer = FALSE;
return (((GtkNotebookPage *) a)->child != b);
}
-static GList *
-gtk_notebook_find_child (GtkNotebook *notebook,
- GtkWidget *child,
- const gchar *function)
+static GList*
+gtk_notebook_find_child (GtkNotebook *notebook,
+ GtkWidget *child,
+ const gchar *function)
{
GList *list = g_list_find_custom (notebook->children, child,
gtk_notebook_page_compare);
#ifndef G_DISABLE_CHECKS
- if (!list)
- g_warning ("child argument to '%s' does not refer to the contents of a notebook page",
- function);
+ if (!list && function)
+ g_warning ("%s: unable to find child %p in notebook %p",
+ function, child, notebook);
#endif
return list;
}
+static void
+gtk_notebook_remove_tab_label (GtkNotebook *notebook,
+ GtkNotebookPage *page)
+{
+ if (page->tab_label)
+ {
+ if (page->mnemonic_activate_signal)
+ g_signal_handler_disconnect (page->tab_label,
+ page->mnemonic_activate_signal);
+ page->mnemonic_activate_signal = 0;
+
+ 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 (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
need_resize = TRUE;
- if (page->tab_label && page->mnemonic_activate_signal)
- gtk_signal_disconnect (page->tab_label,
- page->mnemonic_activate_signal);
-
gtk_widget_unparent (page->child);
- if (page->tab_label)
- gtk_widget_unparent (page->tab_label);
-
+ gtk_notebook_remove_tab_label (notebook, page);
+
if (notebook->menu)
{
gtk_container_remove (GTK_CONTAINER (notebook->menu),
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);
+
+ 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);
+ if (!notebook->children && notebook->show_tabs &&
+ GTK_WIDGET_MAPPED (notebook))
+ gdk_window_hide (notebook->event_window);
+
gtk_notebook_update_labels (notebook);
if (need_resize)
gtk_widget_queue_resize (GTK_WIDGET (notebook));
GList *work;
gint count_start;
- g_return_val_if_fail (notebook != NULL, -1);
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
g_return_val_if_fail (list != NULL, -1);
GList *old_list = NULL;
gint flag = 0;
- g_return_val_if_fail (notebook != NULL, NULL);
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
switch (direction)
* gtk_notebook_paint
* gtk_notebook_draw_tab
* gtk_notebook_draw_arrow
- * gtk_notebook_set_shape
*/
static void
gtk_notebook_paint (GtkWidget *widget,
gboolean showarrow;
gint width, height;
gint x, y;
+ gint border_width = GTK_CONTAINER (widget)->border_width;
gint gap_x = 0, gap_width = 0;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
g_return_if_fail (area != NULL);
if ((!notebook->show_tabs && !notebook->show_border) ||
!notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
- {
- gdk_window_clear_area (widget->window,
- area->x, area->y,
- area->width, area->height);
- return;
- }
+ return;
- x = GTK_CONTAINER (widget)->border_width;
- y = GTK_CONTAINER (widget)->border_width;
- width = widget->allocation.width - x * 2;
- height = widget->allocation.height - y * 2;
+ x = widget->allocation.x + border_width;
+ y = widget->allocation.y + border_width;
+ width = widget->allocation.width - border_width * 2;
+ height = widget->allocation.height - border_width * 2;
if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
{
switch (notebook->tab_pos)
{
case GTK_POS_TOP:
- gap_x = (notebook->cur_page->allocation.x -
- GTK_CONTAINER(notebook)->border_width);
- gap_width = notebook->cur_page->allocation.width;
- break;
case GTK_POS_BOTTOM:
- gap_x = (notebook->cur_page->allocation.x -
- GTK_CONTAINER(notebook)->border_width);
+ gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
gap_width = notebook->cur_page->allocation.width;
break;
case GTK_POS_LEFT:
- gap_x = (notebook->cur_page->allocation.y -
- GTK_CONTAINER(notebook)->border_width);
- gap_width = notebook->cur_page->allocation.height;
- break;
case GTK_POS_RIGHT:
- gap_x = (notebook->cur_page->allocation.y -
- GTK_CONTAINER(notebook)->border_width);
+ gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
gap_width = notebook->cur_page->allocation.height;
break;
}
if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
notebook->focus_tab && (notebook->focus_tab->data == page))
{
- gtk_paint_focus (widget->style, widget->window,
+ gint focus_width;
+
+ gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
+
+ gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
area, widget, "tab",
- page->tab_label->allocation.x - 1,
- page->tab_label->allocation.y - 1,
- page->tab_label->allocation.width + 1,
- page->tab_label->allocation.height + 1);
+ page->tab_label->allocation.x - focus_width,
+ page->tab_label->allocation.y - focus_width,
+ page->tab_label->allocation.width + 2 * focus_width,
+ page->tab_label->allocation.height + 2 * focus_width);
}
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);
}
}
}
GtkStateType state_type;
GtkShadowType shadow_type;
GtkWidget *widget;
+ GdkRectangle arrow_rect;
+
+ gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
widget = GTK_WIDGET(notebook);
STEP_PREV, TRUE))
{
shadow_type = GTK_SHADOW_ETCHED_IN;
- state_type = GTK_STATE_NORMAL;
+ state_type = GTK_STATE_INSENSITIVE;
}
if (notebook->tab_pos == GTK_POS_LEFT ||
notebook->tab_pos == GTK_POS_RIGHT)
arrow = GTK_ARROW_UP;
- gdk_window_clear_area (notebook->panel, 0, 0, ARROW_SIZE, ARROW_SIZE);
- gtk_paint_arrow (widget->style, notebook->panel, state_type,
+ gtk_paint_arrow (widget->style, widget->window, state_type,
shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
arrow, TRUE,
- 0, 0, ARROW_SIZE, ARROW_SIZE);
+ arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
}
else
{
STEP_NEXT, TRUE))
{
shadow_type = GTK_SHADOW_ETCHED_IN;
- state_type = GTK_STATE_NORMAL;
+ state_type = GTK_STATE_INSENSITIVE;
}
if (notebook->tab_pos == GTK_POS_LEFT ||
notebook->tab_pos == GTK_POS_RIGHT)
arrow = GTK_ARROW_DOWN;
- gdk_window_clear_area(notebook->panel, ARROW_SIZE + ARROW_SPACING,
- 0, ARROW_SIZE, ARROW_SIZE);
- gtk_paint_arrow (widget->style, notebook->panel, state_type,
+ gtk_paint_arrow (widget->style, widget->window, state_type,
shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
- arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
- 0, ARROW_SIZE, ARROW_SIZE);
- }
- }
-}
-
-static void
-gtk_notebook_set_shape (GtkNotebook *notebook)
-{
- GtkWidget *widget = NULL;
- GdkPixmap *pm = NULL;
- GdkGC *pmgc = NULL;
- GdkColor col;
- gint x, y, width, height, w, h, depth;
- GtkNotebookPage *page;
- GList *children;
-
- if (!GTK_WIDGET(notebook)->window)
- return;
-
- widget = GTK_WIDGET(notebook);
-
- w = widget->allocation.width;
- h = widget->allocation.height;
-
- pm = gdk_pixmap_new (widget->window, w, h, 1);
- pmgc = gdk_gc_new (pm);
-
- /* clear the shape mask */
- col.pixel = 0;
- gdk_gc_set_foreground(pmgc, &col);
- gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, w, h);
-
- col.pixel = 1;
- gdk_gc_set_foreground(pmgc, &col);
-
- /* draw the shape for the notebook page itself */
- x = GTK_CONTAINER(notebook)->border_width;
- y = GTK_CONTAINER(notebook)->border_width;
- width = widget->allocation.width - x * 2;
- height = widget->allocation.height - y * 2;
-
- if (notebook->show_tabs && notebook->children)
- {
- if (!(notebook->show_tabs))
- {
- page = notebook->first_tab->data;
- switch (notebook->tab_pos)
- {
- case GTK_POS_TOP:
- y += page->allocation.height +
- widget->style->ythickness;
- case GTK_POS_BOTTOM:
- height -= page->allocation.height +
- widget->style->ythickness;
- break;
- case GTK_POS_LEFT:
- x += page->allocation.width +
- widget->style->xthickness;
- case GTK_POS_RIGHT:
- width -= page->allocation.width +
- widget->style->xthickness;
- break;
- }
- }
- else
- {
- if (notebook->cur_page)
- page = notebook->cur_page;
- else
- page = notebook->children->data;
-
- if (!GTK_WIDGET_MAPPED (page->tab_label))
- {
- if (notebook->tab_pos == GTK_POS_LEFT)
- {
- x -= widget->style->xthickness * 2;
- width += widget->style->xthickness * 2;
- }
- else if (notebook->tab_pos == GTK_POS_RIGHT)
- width += widget->style->xthickness * 2;
- }
- switch (notebook->tab_pos)
- {
- case GTK_POS_TOP:
- y += page->allocation.height;
- case GTK_POS_BOTTOM:
- height -= page->allocation.height;
- break;
- case GTK_POS_LEFT:
- x += page->allocation.width;
- case GTK_POS_RIGHT:
- width -= page->allocation.width;
- break;
- }
- }
- }
- gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
-
- /* if theres an area for scrolling arrows draw the shape for them */
- if (notebook->panel && gdk_window_is_visible (notebook->panel))
- {
- gdk_window_get_geometry(notebook->panel, &x, &y, &width, &height, &depth);
- gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
- }
-
- /* draw the shapes of all the children */
- if (notebook->show_tabs)
- {
- children = notebook->children;
- while (children)
- {
- page = children->data;
- if (GTK_WIDGET_MAPPED (page->tab_label))
- {
- x = page->allocation.x;
- y = page->allocation.y;
- width = page->allocation.width;
- height = page->allocation.height;
- gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
- }
- children = children->next;
+ arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
+ arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
}
}
-
- /* set the mask */
- gdk_window_shape_combine_mask(widget->window, pm, 0, 0);
- gdk_pixmap_unref(pm);
- gdk_gc_destroy(pmgc);
}
/* Private GtkNotebook Size Allocate Functions:
if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
return;
- child_allocation.x = container->border_width;
- child_allocation.y = container->border_width;
+ child_allocation.x = widget->allocation.x + container->border_width;
+ child_allocation.y = widget->allocation.y + container->border_width;
switch (notebook->tab_pos)
{
case GTK_POS_BOTTOM:
- child_allocation.y = (allocation->height -
+ child_allocation.y = (widget->allocation.y +
+ allocation->height -
notebook->cur_page->requisition.height -
container->border_width);
/* fall through */
break;
case GTK_POS_RIGHT:
- child_allocation.x = (allocation->width -
+ child_allocation.x = (widget->allocation.x +
+ allocation->width -
notebook->cur_page->requisition.width -
container->border_width);
/* fall through */
}
}
- if (GTK_WIDGET_REALIZED (notebook))
- {
- gdk_window_move (notebook->panel, x, y);
- gdk_window_show (notebook->panel);
- }
-
if (tab_space < 0)
{
tab_space = -tab_space;
STEP_NEXT, TRUE))
{
page = children->data;
- if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
- gtk_widget_unmap (page->tab_label);
+ if (page->tab_label)
+ gtk_widget_set_child_visible (page->tab_label, FALSE);
}
for (children = last_child; children;
children = gtk_notebook_search_page (notebook, children,
STEP_NEXT, TRUE))
{
page = children->data;
- if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
- gtk_widget_unmap (page->tab_label);
+ if (page->tab_label)
+ gtk_widget_set_child_visible (page->tab_label, FALSE);
}
}
else /* !showarrow */
notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
STEP_NEXT, TRUE);
tab_space = 0;
- if (GTK_WIDGET_REALIZED (notebook))
- gdk_window_hide (notebook->panel);
}
}
break;
}
- if (GTK_WIDGET_REALIZED (notebook) &&
- page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
- {
- if (GTK_WIDGET_VISIBLE (page->tab_label))
- gtk_widget_map (page->tab_label);
- else
- gtk_widget_show (page->tab_label);
- }
+ if (page->tab_label)
+ gtk_widget_set_child_visible (page->tab_label, TRUE);
}
if (children)
break;
}
- if (GTK_WIDGET_REALIZED (notebook) && page->tab_label &&
- !GTK_WIDGET_MAPPED (page->tab_label))
- {
- if (GTK_WIDGET_VISIBLE (page->tab_label))
- gtk_widget_map (page->tab_label);
- else
- gtk_widget_show (page->tab_label);
- }
+ if (page->tab_label)
+ gtk_widget_set_child_visible (page->tab_label, TRUE);
}
}
done:
- gtk_notebook_set_shape (notebook);
gtk_notebook_redraw_tabs (notebook);
}
GtkNotebookPage *page,
GtkAllocation *allocation)
{
- GtkWidget *widget;
+ GtkWidget *widget = GTK_WIDGET (notebook);
GtkAllocation child_allocation;
GtkRequisition tab_requisition;
gint xthickness;
gint ythickness;
gint padding;
+ gint focus_width;
- g_return_if_fail (notebook != NULL);
- g_return_if_fail (page != NULL);
- g_return_if_fail (allocation != NULL);
-
- widget = GTK_WIDGET (notebook);
-
+ gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
+
xthickness = widget->style->xthickness;
ythickness = widget->style->ythickness;
break;
}
- gtk_widget_queue_clear_area (widget, x, y, width, height);
+ gtk_widget_queue_draw_area (widget, x, y, width, height);
}
page->allocation = *allocation;
{
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
- padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_hborder;
+ padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
if (page->fill)
{
- child_allocation.x = (xthickness + FOCUS_WIDTH +
+ child_allocation.x = (xthickness + focus_width +
notebook->tab_hborder);
- child_allocation.width = MAX (1, (((gint) page->allocation.width) -
+ child_allocation.width = MAX (1, (page->allocation.width -
2 * child_allocation.x));
child_allocation.x += page->allocation.x;
}
tab_requisition.width) / 2);
child_allocation.width = tab_requisition.width;
}
- child_allocation.y = (notebook->tab_vborder + FOCUS_WIDTH +
+ child_allocation.y = (notebook->tab_vborder + focus_width +
page->allocation.y);
if (notebook->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)));
+ 2 * (notebook->tab_vborder + focus_width)));
break;
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
- padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_vborder;
+ padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
if (page->fill)
{
child_allocation.y = ythickness + padding;
- child_allocation.height = MAX (1, (((gint) page->allocation.height) -
+ child_allocation.height = MAX (1, (page->allocation.height -
2 * child_allocation.y));
child_allocation.y += page->allocation.y;
}
tab_requisition.height) / 2);
child_allocation.height = tab_requisition.height;
}
- child_allocation.x = page->allocation.x + notebook->tab_hborder + FOCUS_WIDTH;
+ child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
if (notebook->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)));
+ 2 * (notebook->tab_hborder + focus_width)));
break;
}
GtkNotebookPage *page,
guint page_num)
{
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
g_return_if_fail (page != NULL);
if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
return;
- if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
- gtk_widget_unmap (notebook->cur_page->child);
+ if (notebook->cur_page)
+ gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
notebook->cur_page = page;
notebook->focus_tab =
g_list_find (notebook->children, notebook->cur_page);
- if (GTK_WIDGET_MAPPED (notebook))
- gtk_widget_map (notebook->cur_page->child);
+ gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
+ /* If the focus was on the previous page, move it to the first
+ * element on the new page, if possible, or if not, to the
+ * notebook itself.
+ */
+ if (notebook->child_has_focus)
+ {
+ if (notebook->cur_page->last_focus_child &&
+ gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
+ gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
+ else
+ if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
+ gtk_widget_grab_focus (GTK_WIDGET (notebook));
+ }
+
gtk_widget_queue_resize (GTK_WIDGET (notebook));
+ g_object_notify (G_OBJECT (notebook), "page");
}
/* Private GtkNotebook Page Switch Functions:
GtkNotebookPage *page,
gint page_num)
{
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
g_return_if_fail (page != NULL);
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 */
- g_return_val_if_fail (notebook != NULL, FALSE);
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
if (!notebook->focus_tab)
dir = GTK_DIR_LEFT;
break;
}
-
- if (GTK_WIDGET_VISIBLE (page->child))
- {
- if (GTK_IS_CONTAINER (page->child))
- {
- if (gtk_container_focus (GTK_CONTAINER (page->child),
- dir))
- return TRUE;
- }
- else if (GTK_WIDGET_CAN_FOCUS (page->child))
- {
- gtk_widget_grab_focus (page->child);
- return TRUE;
- }
- }
+
+ if (gtk_widget_child_focus (page->child, dir))
+ return TRUE;
}
return FALSE;
}
GtkNotebookPage *old_page = NULL;
GtkNotebookPage *page;
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
if (notebook->focus_tab == new_child)
old_child = notebook->focus_tab;
notebook->focus_tab = new_child;
- if (notebook->scrollable && GTK_WIDGET_DRAWABLE (notebook))
+ if (notebook->scrollable)
gtk_notebook_redraw_arrows (notebook);
if (!notebook->show_tabs || !notebook->focus_tab)
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_set_shape (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_widget_show (page->menu_label);
menu_item = gtk_menu_item_new ();
- gtk_widget_lock_accelerators (menu_item);
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);
}
{
GtkNotebook *notebook;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (widget));
notebook = GTK_NOTEBOOK (widget);
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
* @tab_label: the #GtkWidget to be used as the label for the page,
* or %NULL to use the default label, 'page N'.
*
- * Prepends a page to @noteobook.
+ * Prepends a page to @notebook.
**/
void
gtk_notebook_prepend_page (GtkNotebook *notebook,
{
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);
+ focus_tabs_in (notebook);
}
return TRUE;
g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
+ gtk_widget_freeze_child_notify (child);
+
page = g_new (GtkNotebookPage, 1);
page->child = child;
+ page->last_focus_child = NULL;
page->requisition.width = 0;
page->requisition.height = 0;
page->allocation.x = 0;
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_menu_item_create (notebook,
g_list_find (notebook->children, page));
+ gtk_widget_set_parent (child, GTK_WIDGET (notebook));
+ if (tab_label)
+ gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
+
gtk_notebook_update_labels (notebook);
if (!notebook->first_tab)
notebook->first_tab = notebook->children;
- gtk_widget_set_parent (child, GTK_WIDGET (notebook));
+ if (!notebook->cur_page)
+ gtk_widget_set_child_visible (child, TRUE);
+ else
+ gtk_widget_set_child_visible (child, FALSE);
+
if (tab_label)
- gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
+ {
+ if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
+ gtk_widget_show (tab_label);
+ else
+ gtk_widget_hide (tab_label);
+ }
if (!notebook->cur_page)
{
gtk_notebook_switch_focus_tab (notebook, NULL);
}
- if (GTK_WIDGET_REALIZED (child->parent))
- gtk_widget_realize (child);
-
- if (GTK_WIDGET_VISIBLE (notebook))
- {
- if (GTK_WIDGET_VISIBLE (child))
- {
- if (GTK_WIDGET_MAPPED (notebook) &&
- !GTK_WIDGET_MAPPED (child) &&
- notebook->cur_page == page)
- gtk_widget_map (child);
-
- gtk_widget_queue_resize (child);
- }
-
- if (tab_label)
- {
- if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
- {
- if (!GTK_WIDGET_VISIBLE (tab_label))
- gtk_widget_show (tab_label);
-
- if (GTK_WIDGET_REALIZED (notebook) &&
- !GTK_WIDGET_REALIZED (tab_label))
- gtk_widget_realize (tab_label);
-
- if (GTK_WIDGET_MAPPED (notebook) &&
- !GTK_WIDGET_MAPPED (tab_label))
- gtk_widget_map (tab_label);
- }
- else if (GTK_WIDGET_VISIBLE (tab_label))
- gtk_widget_hide (tab_label);
- }
- }
-
if (tab_label)
page->mnemonic_activate_signal =
- gtk_signal_connect (GTK_OBJECT (tab_label),
- "mnemonic_activate",
- (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
- notebook);
+ g_signal_connect (tab_label,
+ "mnemonic_activate",
+ G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
+ notebook);
+
+ if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
+ gdk_window_show_unraised (notebook->event_window);
+
+ gtk_widget_child_notify (child, "tab_expand");
+ gtk_widget_child_notify (child, "tab_fill");
+ gtk_widget_child_notify (child, "tab_pack");
+ gtk_widget_child_notify (child, "tab_label");
+ gtk_widget_child_notify (child, "menu_label");
+ gtk_widget_child_notify (child, "position");
+ gtk_widget_thaw_child_notify (child);
}
/**
{
GList *list;
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
if (page_num >= 0)
{
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);
}
}
/* Public GtkNotebook Page Switch Methods :
* gtk_notebook_get_current_page
* gtk_notebook_page_num
- * gtk_notebook_set_page
+ * gtk_notebook_set_current_page
* gtk_notebook_next_page
* gtk_notebook_prev_page
*/
/**
* 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_page:
+ * 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.
**/
void
-gtk_notebook_set_page (GtkNotebook *notebook,
- gint page_num)
+gtk_notebook_set_current_page (GtkNotebook *notebook,
+ gint page_num)
{
GList *list;
* @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
gtk_notebook_set_show_border (GtkNotebook *notebook,
gboolean show_border)
{
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
if (notebook->show_border != show_border)
if (GTK_WIDGET_VISIBLE (notebook))
gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "show_border");
}
}
+/**
+ * gtk_notebook_get_show_border:
+ * @notebook: a #GtkNotebook
+ *
+ * Returns whether a bevel will be drawn around the notebook pages. See
+ * gtk_notebook_set_show_border().
+ *
+ * Return value: %TRUE if the bevel is drawn
+ **/
+gboolean
+gtk_notebook_get_show_border (GtkNotebook *notebook)
+{
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
+
+ return notebook->show_border;
+}
+
/**
* gtk_notebook_set_show_tabs:
* @notebook: a #GtkNotebook
GtkNotebookPage *page;
GList *children;
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
show_tabs = show_tabs != FALSE;
else
gtk_widget_hide (page->tab_label);
}
-
- if (notebook->panel)
- gdk_window_hide (notebook->panel);
}
else
{
gtk_notebook_update_labels (notebook);
}
gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "show_tabs");
+}
+
+/**
+ * gtk_notebook_get_show_tabs:
+ * @notebook: a #GtkNotebook
+ *
+ * Returns whether the tabs of the notebook are shown. See
+ * gtk_notebook_set_show_tabs().
+ *
+ * Return value: %TRUE if the tabs are shown
+ **/
+gboolean
+gtk_notebook_get_show_tabs (GtkNotebook *notebook)
+{
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
+
+ return notebook->show_tabs;
}
/**
* gtk_notebook_set_tab_pos:
- * @notebook:
- * @pos:
+ * @notebook: a #GtkNotebook.
+ * @pos: the edge to draw the tabs at.
*
* Sets the edge at which the tabs for switching pages in the
* notebook are drawn.
if (GTK_WIDGET_VISIBLE (notebook))
gtk_widget_queue_resize (GTK_WIDGET (notebook));
}
+
+ g_object_notify (G_OBJECT (notebook), "tab_pos");
+}
+
+/**
+ * gtk_notebook_get_tab_pos:
+ * @notebook: a #GtkNotebook
+ *
+ * Gets the edge at which the tabs for switching pages in the
+ * notebook are drawn.
+ *
+ * Return value: the edge at which the tabs are drawn
+ **/
+GtkPositionType
+gtk_notebook_get_tab_pos (GtkNotebook *notebook)
+{
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
+
+ return notebook->tab_pos;
}
/**
{
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- if (homogeneous == notebook->homogeneous)
- return;
-
- notebook->homogeneous = homogeneous;
- gtk_widget_queue_resize (GTK_WIDGET (notebook));
+ gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
}
/**
* Sets the width the border around the tab labels
* in a notebook. This is equivalent to calling
* gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
- * by gtk_noteobok_set_tab_vborder (@notebook, @border_width).
+ * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
**/
void
gtk_notebook_set_tab_border (GtkNotebook *notebook,
{
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));
+ 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));
+ 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));
+ gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
}
/**
*
* Sets whether the tab label area will have arrows for scrolling if
* there are too many tabs to fit in the area.
-
**/
void
gtk_notebook_set_scrollable (GtkNotebook *notebook,
{
notebook->scrollable = scrollable;
- if (GTK_WIDGET_REALIZED (notebook))
- {
- if (scrollable)
- {
- gtk_notebook_panel_realize (notebook);
- }
- else if (notebook->panel)
- {
- gdk_window_set_user_data (notebook->panel, NULL);
- gdk_window_destroy (notebook->panel);
- notebook->panel = NULL;
- }
- }
-
if (GTK_WIDGET_VISIBLE (notebook))
gtk_widget_queue_resize (GTK_WIDGET (notebook));
+
+ g_object_notify (G_OBJECT (notebook), "scrollable");
}
}
+/**
+ * gtk_notebook_get_scrollable:
+ * @notebook: a #GtkNotebook
+ *
+ * Returns whether the tab label area has arrows for scrolling. See
+ * gtk_notebook_set_scrollable().
+ *
+ * Return value: %TRUE if arrows for scrolling are present
+ **/
+gboolean
+gtk_notebook_get_scrollable (GtkNotebook *notebook)
+{
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
+
+ return notebook->scrollable;
+}
+
/* Public GtkNotebook Popup Menu Methods:
*
* gtk_notebook_popup_enable
gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
GTK_WIDGET (notebook),
gtk_notebook_menu_detacher);
+
+ g_object_notify (G_OBJECT (notebook), "enable_popup");
}
/**
gtk_container_foreach (GTK_CONTAINER (notebook->menu),
(GtkCallback) gtk_notebook_menu_label_unparent, NULL);
gtk_widget_destroy (notebook->menu);
+
+ g_object_notify (G_OBJECT (notebook), "enable_popup");
}
/* Public GtkNotebook Page Properties Functions:
GList *list;
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
- g_return_val_if_fail (child != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
GList *list;
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (child));
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
* we need to set the associated label
*/
page = list->data;
- if (page->tab_label)
- gtk_widget_unparent (page->tab_label);
+
+ if (page->tab_label == tab_label)
+ return;
+
+ gtk_notebook_remove_tab_label (notebook, page);
+
if (tab_label)
{
page->default_tab = FALSE;
}
}
+ if (page->tab_label)
+ page->mnemonic_activate_signal =
+ 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_widget_child_notify (child, "tab_label");
}
/**
if (tab_text)
tab_label = gtk_label_new (tab_text);
gtk_notebook_set_tab_label (notebook, child, tab_label);
+ gtk_widget_child_notify (child, "tab_label");
+}
+
+/**
+ * gtk_notebook_get_tab_label_text:
+ * @notebook: a #GtkNotebook
+ * @child: a widget contained in a page of @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.
+ **/
+G_CONST_RETURN gchar *
+gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
+ GtkWidget *child)
+{
+ GtkWidget *tab_label;
+
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
+
+ tab_label = gtk_notebook_get_tab_label (notebook, child);
+
+ if (tab_label && GTK_IS_LABEL (tab_label))
+ return gtk_label_get_text (GTK_LABEL (tab_label));
+ else
+ return NULL;
}
/**
* gtk_notebook_get_menu_label:
* @notebook: a #GtkNotebook
- * @child: the page
+ * @child: a widget contained in a page of @notebook
*
- * Returns the menu label of the page containing @child. NULL is
- * returned if @child is not in @notebook or NULL if it has the
- * default menu label.
+ * Retrieves the menu label widget of the page containing @child.
*
- * Return value: the menu label
+ * Return value: the menu label, or %NULL if the
+ * notebook page does not have a menu label other
+ * than the default (the tab label).
**/
GtkWidget*
gtk_notebook_get_menu_label (GtkNotebook *notebook,
GList *list;
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
- g_return_val_if_fail (child != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
GtkNotebookPage *page;
GList *list;
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (child));
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
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;
}
if (notebook->menu)
gtk_notebook_menu_item_create (notebook, list);
+ gtk_widget_child_notify (child, "menu_label");
}
/**
if (menu_text)
menu_label = gtk_label_new (menu_text);
gtk_notebook_set_menu_label (notebook, child, menu_label);
+ gtk_widget_child_notify (child, "menu_label");
}
+/**
+ * gtk_notebook_get_menu_label_text:
+ * @notebook: a #GtkNotebook
+ * @child: the child widget of a page of the 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.
+ **/
+G_CONST_RETURN gchar *
+gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
+ GtkWidget *child)
+{
+ GtkWidget *menu_label;
+
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
+
+ menu_label = gtk_notebook_get_menu_label (notebook, child);
+
+ if (menu_label && GTK_IS_LABEL (menu_label))
+ return gtk_label_get_text (GTK_LABEL (menu_label));
+ else
+ return NULL;
+}
+
/* Helper function called when pages are reordered
*/
static void
GtkNotebookPage *page;
GList *list;
- g_return_if_fail (notebook != NULL);
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (child));
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
return;
page = list->data;
+ expand = expand != FALSE;
+ fill = fill != FALSE;
if (page->pack == pack_type && page->expand == expand && page->fill == fill)
return;
+ gtk_widget_freeze_child_notify (child);
page->expand = expand;
+ gtk_widget_child_notify (child, "tab_expand");
page->fill = fill;
-
+ gtk_widget_child_notify (child, "tab_fill");
if (page->pack != pack_type)
{
page->pack = pack_type;
gtk_notebook_child_reordered (notebook, page);
}
-
- if (!notebook->show_tabs)
- return;
-
- gtk_notebook_pages_allocate (notebook);
+ gtk_widget_child_notify (child, "tab_pack");
+ gtk_widget_child_notify (child, "position");
+ if (notebook->show_tabs)
+ gtk_notebook_pages_allocate (notebook);
+ gtk_widget_thaw_child_notify (child);
}
/**
GList *list;
g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
- g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (child));
list = CHECK_FIND_CHILD (notebook, child);
if (!list)
* 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);
if (notebook->focus_tab == list)
notebook->focus_tab = new_list;
+ gtk_widget_freeze_child_notify (child);
+
/* Move around the menu items if necesary */
gtk_notebook_child_reordered (notebook, page);
-
+ gtk_widget_child_notify (child, "tab_pack");
+ gtk_widget_child_notify (child, "position");
+
if (notebook->show_tabs)
gtk_notebook_pages_allocate (notebook);
+
+ gtk_widget_thaw_child_notify (child);
}