gtknotebook.c 210 KB
Newer Older
1
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
Elliot Lee's avatar
Elliot Lee committed
2 3 4 5
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
19
 */
20 21

/*
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23 24 25 26 27
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

28
#include <config.h>
Johan Dahlin's avatar
Johan Dahlin committed
29
#include <string.h>
Elliot Lee's avatar
Elliot Lee committed
30
#include "gtknotebook.h"
31 32 33 34 35 36
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtklabel.h"
#include <gdk/gdkkeysyms.h>
#include <stdio.h>
37
#include "gtkintl.h"
38
#include "gtkmarshalers.h"
39
#include "gtkbindings.h"
40
#include "gtkprivate.h"
41
#include "gtkdnd.h"
Johan Dahlin's avatar
Johan Dahlin committed
42
#include "gtkbuildable.h"
43
#include "gtkalias.h"
Elliot Lee's avatar
Elliot Lee committed
44

45
#define SCROLL_DELAY_FACTOR   5
46 47
#define SCROLL_THRESHOLD      12
#define DND_THRESHOLD_MULTIPLIER 4
48 49
#define FRAMES_PER_SECOND     45
#define MSECS_BETWEEN_UPDATES (1000 / FRAMES_PER_SECOND)
Elliot Lee's avatar
Elliot Lee committed
50

51 52
enum {
  SWITCH_PAGE,
53 54
  FOCUS_TAB,
  SELECT_PAGE,
55
  CHANGE_CURRENT_PAGE,
56
  MOVE_FOCUS_OUT,
57
  REORDER_TAB,
58 59 60
  PAGE_REORDERED,
  PAGE_REMOVED,
  PAGE_ADDED,
61
  CREATE_WINDOW,
62 63 64
  LAST_SIGNAL
};

65 66 67 68 69
enum {
  STEP_PREV,
  STEP_NEXT
};

70 71 72 73 74 75 76 77 78
typedef enum
{
  ARROW_NONE,
  ARROW_LEFT_BEFORE,
  ARROW_RIGHT_BEFORE,
  ARROW_LEFT_AFTER,
  ARROW_RIGHT_AFTER
} GtkNotebookArrow;

79 80 81 82 83 84 85 86 87 88 89 90 91 92
typedef enum
{
  POINTER_BEFORE,
  POINTER_AFTER,
  POINTER_BETWEEN
} GtkNotebookPointerPosition;

typedef enum
{
  DRAG_OPERATION_NONE,
  DRAG_OPERATION_REORDER,
  DRAG_OPERATION_DETACH
} GtkNotebookDragOperation;

93 94 95
#define ARROW_IS_LEFT(arrow)  ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
#define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)

96
enum {
97 98 99 100 101 102 103 104 105 106
  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,
107
  PROP_GROUP_ID,
108
  PROP_GROUP,
109
  PROP_HOMOGENEOUS
110 111 112
};

enum {
Tim Janik's avatar
Tim Janik committed
113 114 115 116 117 118
  CHILD_PROP_0,
  CHILD_PROP_TAB_LABEL,
  CHILD_PROP_MENU_LABEL,
  CHILD_PROP_POSITION,
  CHILD_PROP_TAB_EXPAND,
  CHILD_PROP_TAB_FILL,
119 120 121
  CHILD_PROP_TAB_PACK,
  CHILD_PROP_REORDERABLE,
  CHILD_PROP_DETACHABLE
122 123
};

124 125
#define GTK_NOTEBOOK_PAGE(_glist_)         ((GtkNotebookPage *)((GList *)(_glist_))->data)

126 127 128 129 130 131 132
/* some useful defines for calculating coords */
#define PAGE_LEFT_X(_page_)   (((GtkNotebookPage *) (_page_))->allocation.x)
#define PAGE_RIGHT_X(_page_)  (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width)
#define PAGE_MIDDLE_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width / 2)
#define PAGE_TOP_Y(_page_)    (((GtkNotebookPage *) (_page_))->allocation.y)
#define PAGE_BOTTOM_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height)
#define PAGE_MIDDLE_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height / 2)
133
#define NOTEBOOK_IS_TAB_LABEL_PARENT(_notebook_,_page_) (((GtkNotebookPage *) (_page_))->tab_label->parent == ((GtkWidget *) (_notebook_)))
134

135 136 137 138 139
struct _GtkNotebookPage
{
  GtkWidget *child;
  GtkWidget *tab_label;
  GtkWidget *menu_label;
140
  GtkWidget *last_focus_child;	/* Last descendant of the page that had focus */
141 142 143 144 145 146

  guint default_menu : 1;	/* If true, we create the menu label ourself */
  guint default_tab  : 1;	/* If true, we create the tab label ourself */
  guint expand       : 1;
  guint fill         : 1;
  guint pack         : 1;
147 148
  guint reorderable  : 1;
  guint detachable   : 1;
149 150 151

  GtkRequisition requisition;
  GtkAllocation allocation;
152

153 154
  gulong mnemonic_activate_signal;
  gulong notify_visible_handler;
155 156
};

157 158 159 160 161 162
#define GTK_NOTEBOOK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_NOTEBOOK, GtkNotebookPrivate))

typedef struct _GtkNotebookPrivate GtkNotebookPrivate;

struct _GtkNotebookPrivate
{
163
  gpointer group;
164 165 166 167
  gint  mouse_x;
  gint  mouse_y;
  gint  pressed_button;
  guint dnd_timer;
168
  guint switch_tab_timer;
169

170 171 172 173 174 175 176
  gint  drag_begin_x;
  gint  drag_begin_y;

  gint  drag_offset_x;
  gint  drag_offset_y;

  GtkWidget *dnd_window;
177
  GtkTargetList *source_targets;
178 179 180 181 182 183
  GtkNotebookDragOperation operation;
  GdkWindow *drag_window;
  gint drag_window_x;
  gint drag_window_y;
  GtkNotebookPage *detached_tab;

184 185
  guint32 timestamp;

186 187 188
  guint during_reorder : 1;
  guint during_detach  : 1;
  guint has_scrolled   : 1;
189 190
};

191
static const GtkTargetEntry notebook_targets [] = {
192
  { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
193 194
};

195 196
#ifdef G_DISABLE_CHECKS
#define CHECK_FIND_CHILD(notebook, child)                           \
197
 gtk_notebook_find_child (notebook, child, G_STRLOC)
198 199
#else
#define CHECK_FIND_CHILD(notebook, child)                           \
200
 gtk_notebook_find_child (notebook, child, NULL)
201 202
#endif
 
203
/*** GtkNotebook Methods ***/
204 205 206 207
static gboolean gtk_notebook_select_page         (GtkNotebook      *notebook,
						  gboolean          move_focus);
static gboolean gtk_notebook_focus_tab           (GtkNotebook      *notebook,
						  GtkNotebookTab    type);
208
static gboolean gtk_notebook_change_current_page (GtkNotebook      *notebook,
209 210 211
						  gint              offset);
static void     gtk_notebook_move_focus_out      (GtkNotebook      *notebook,
						  GtkDirectionType  direction_type);
212
static gboolean gtk_notebook_reorder_tab         (GtkNotebook      *notebook,
213 214
						  GtkDirectionType  direction_type,
						  gboolean          move_to_last);
215 216
static void     gtk_notebook_remove_tab_label    (GtkNotebook      *notebook,
						  GtkNotebookPage  *page);
217

218
/*** GtkObject Methods ***/
219
static void gtk_notebook_destroy             (GtkObject        *object);
220 221 222 223 224 225 226 227
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);
228

229
/*** GtkWidget Methods ***/
230 231 232
static void gtk_notebook_map                 (GtkWidget        *widget);
static void gtk_notebook_unmap               (GtkWidget        *widget);
static void gtk_notebook_realize             (GtkWidget        *widget);
233
static void gtk_notebook_unrealize           (GtkWidget        *widget);
234 235 236 237 238 239
static void gtk_notebook_size_request        (GtkWidget        *widget,
					      GtkRequisition   *requisition);
static void gtk_notebook_size_allocate       (GtkWidget        *widget,
					      GtkAllocation    *allocation);
static gint gtk_notebook_expose              (GtkWidget        *widget,
					      GdkEventExpose   *event);
240 241
static gboolean gtk_notebook_scroll          (GtkWidget        *widget,
                                              GdkEventScroll   *event);
242 243 244 245
static gint gtk_notebook_button_press        (GtkWidget        *widget,
					      GdkEventButton   *event);
static gint gtk_notebook_button_release      (GtkWidget        *widget,
					      GdkEventButton   *event);
246
static gboolean gtk_notebook_popup_menu      (GtkWidget        *widget);
247 248 249 250
static gint gtk_notebook_leave_notify        (GtkWidget        *widget,
					      GdkEventCrossing *event);
static gint gtk_notebook_motion_notify       (GtkWidget        *widget,
					      GdkEventMotion   *event);
251 252
static gint gtk_notebook_focus_in            (GtkWidget        *widget,
					      GdkEventFocus    *event);
253 254
static gint gtk_notebook_focus_out           (GtkWidget        *widget,
					      GdkEventFocus    *event);
Matthias Clasen's avatar
Matthias Clasen committed
255 256 257 258
static void gtk_notebook_grab_notify         (GtkWidget          *widget,
					      gboolean            was_grabbed);
static void gtk_notebook_state_changed       (GtkWidget          *widget,
					      GtkStateType        previous_state);
259 260
static void gtk_notebook_draw_focus          (GtkWidget        *widget,
					      GdkEventExpose   *event);
261 262
static gint gtk_notebook_focus               (GtkWidget        *widget,
					      GtkDirectionType  direction);
263 264
static void gtk_notebook_style_set           (GtkWidget        *widget,
					      GtkStyle         *previous);
265

266 267 268
/*** Drag and drop Methods ***/
static void gtk_notebook_drag_begin          (GtkWidget        *widget,
					      GdkDragContext   *context);
269 270
static void gtk_notebook_drag_end            (GtkWidget        *widget,
					      GdkDragContext   *context);
271 272 273 274
static gboolean gtk_notebook_drag_failed     (GtkWidget        *widget,
					      GdkDragContext   *context,
					      GtkDragResult     result,
					      gpointer          data);
275 276 277 278 279
static gboolean gtk_notebook_drag_motion     (GtkWidget        *widget,
					      GdkDragContext   *context,
					      gint              x,
					      gint              y,
					      guint             time);
280 281 282
static void gtk_notebook_drag_leave          (GtkWidget        *widget,
					      GdkDragContext   *context,
					      guint             time);
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
static gboolean gtk_notebook_drag_drop       (GtkWidget        *widget,
					      GdkDragContext   *context,
					      gint              x,
					      gint              y,
					      guint             time);
static void gtk_notebook_drag_data_get       (GtkWidget        *widget,
					      GdkDragContext   *context,
					      GtkSelectionData *data,
					      guint             info,
					      guint             time);
static void gtk_notebook_drag_data_received  (GtkWidget        *widget,
					      GdkDragContext   *context,
					      gint              x,
					      gint              y,
					      GtkSelectionData *data,
					      guint             info,
					      guint             time);

301
/*** GtkContainer Methods ***/
Tim Janik's avatar
Tim Janik committed
302
static void gtk_notebook_set_child_property  (GtkContainer     *container,
303
					      GtkWidget        *child,
Tim Janik's avatar
Tim Janik committed
304 305 306 307
					      guint             property_id,
					      const GValue     *value,
					      GParamSpec       *pspec);
static void gtk_notebook_get_child_property  (GtkContainer     *container,
308
					      GtkWidget        *child,
Tim Janik's avatar
Tim Janik committed
309 310 311
					      guint             property_id,
					      GValue           *value,
					      GParamSpec       *pspec);
312 313 314 315
static void gtk_notebook_add                 (GtkContainer     *container,
					      GtkWidget        *widget);
static void gtk_notebook_remove              (GtkContainer     *container,
					      GtkWidget        *widget);
316 317
static void gtk_notebook_set_focus_child     (GtkContainer     *container,
					      GtkWidget        *child);
Manish Singh's avatar
Manish Singh committed
318
static GType gtk_notebook_child_type       (GtkContainer     *container);
319 320
static void gtk_notebook_forall              (GtkContainer     *container,
					      gboolean		include_internals,
321 322
					      GtkCallback       callback,
					      gpointer          callback_data);
323

324 325 326 327 328 329 330
/*** GtkNotebook Methods ***/
static gint gtk_notebook_real_insert_page    (GtkNotebook      *notebook,
					      GtkWidget        *child,
					      GtkWidget        *tab_label,
					      GtkWidget        *menu_label,
					      gint              position);

331 332 333 334 335
static GtkNotebook *gtk_notebook_create_window (GtkNotebook    *notebook,
                                                GtkWidget      *page,
                                                gint            x,
                                                gint            y);

336
/*** GtkNotebook Private Functions ***/
337 338
static void gtk_notebook_redraw_tabs         (GtkNotebook      *notebook);
static void gtk_notebook_redraw_arrows       (GtkNotebook      *notebook);
339
static void gtk_notebook_real_remove         (GtkNotebook      *notebook,
340
					      GList            *list);
341 342
static void gtk_notebook_update_labels       (GtkNotebook      *notebook);
static gint gtk_notebook_timer               (GtkNotebook      *notebook);
343
static void gtk_notebook_set_scroll_timer    (GtkNotebook *notebook);
344 345
static gint gtk_notebook_page_compare        (gconstpointer     a,
					      gconstpointer     b);
346
static GList* gtk_notebook_find_child        (GtkNotebook      *notebook,
347 348
					      GtkWidget        *child,
					      const gchar      *function);
349 350 351 352 353 354
static gint  gtk_notebook_real_page_position (GtkNotebook      *notebook,
					      GList            *list);
static GList * gtk_notebook_search_page      (GtkNotebook      *notebook,
					      GList            *list,
					      gint              direction,
					      gboolean          find_visible);
355 356
static void  gtk_notebook_child_reordered    (GtkNotebook      *notebook,
			                      GtkNotebookPage  *page);
357

358
/*** GtkNotebook Drawing Functions ***/
359 360
static void gtk_notebook_paint               (GtkWidget        *widget,
					      GdkRectangle     *area);
361 362 363
static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
					      GtkNotebookPage  *page,
					      GdkRectangle     *area);
364
static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
365
					      GtkNotebookArrow  arrow);
366

367
/*** GtkNotebook Size Allocate Functions ***/
368
static void gtk_notebook_pages_allocate      (GtkNotebook      *notebook);
369
static void gtk_notebook_page_allocate       (GtkNotebook      *notebook,
Matthias Clasen's avatar
Matthias Clasen committed
370
					      GtkNotebookPage  *page);
371 372
static void gtk_notebook_calc_tabs           (GtkNotebook      *notebook,
			                      GList            *start,
373 374 375
					      GList           **end,
					      gint             *tab_space,
					      guint             direction);
376

377
/*** GtkNotebook Page Switch Methods ***/
378
static void gtk_notebook_real_switch_page    (GtkNotebook      *notebook,
Lars Hamann's avatar
Lars Hamann committed
379
					      GtkNotebookPage  *page,
380
					      guint             page_num);
381

382
/*** GtkNotebook Page Switch Functions ***/
383
static void gtk_notebook_switch_page         (GtkNotebook      *notebook,
384
					      GtkNotebookPage  *page);
385 386
static gint gtk_notebook_page_select         (GtkNotebook      *notebook,
					      gboolean          move_focus);
387 388
static void gtk_notebook_switch_focus_tab    (GtkNotebook      *notebook,
                                              GList            *new_child);
389 390
static void gtk_notebook_menu_switch_page    (GtkWidget        *widget,
					      GtkNotebookPage  *page);
391

392
/*** GtkNotebook Menu Functions ***/
393 394 395 396
static void gtk_notebook_menu_item_create    (GtkNotebook      *notebook,
					      GList            *list);
static void gtk_notebook_menu_label_unparent (GtkWidget        *widget,
					      gpointer          data);
397 398
static void gtk_notebook_menu_detacher       (GtkWidget        *widget,
					      GtkMenu          *menu);
399

400 401 402 403 404 405 406 407 408 409
/*** 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);

410 411 412 413 414
static void gtk_notebook_update_tab_states             (GtkNotebook *notebook);
static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
							    gboolean overload,
							    gpointer data);

415 416 417
static gboolean focus_tabs_in  (GtkNotebook      *notebook);
static gboolean focus_child_in (GtkNotebook      *notebook,
				GtkDirectionType  direction);
Elliot Lee's avatar
Elliot Lee committed
418

419
static void stop_scrolling (GtkNotebook *notebook);
420 421 422 423 424
static void do_detach_tab  (GtkNotebook *from,
			    GtkNotebook *to,
			    GtkWidget   *child,
			    gint         x,
			    gint         y);
425

Johan Dahlin's avatar
Johan Dahlin committed
426 427
/* GtkBuildable */
static void gtk_notebook_buildable_init           (GtkBuildableIface *iface);
428
static void gtk_notebook_buildable_add_child      (GtkBuildable *buildable,
Johan Dahlin's avatar
Johan Dahlin committed
429 430 431
						   GtkBuilder   *builder,
						   GObject      *child,
						   const gchar  *type);
432

433 434
static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
static gpointer window_creation_hook_data;
435
static GDestroyNotify window_creation_hook_destroy = NULL;
436

437
static guint notebook_signals[LAST_SIGNAL] = { 0 };
Elliot Lee's avatar
Elliot Lee committed
438

Johan Dahlin's avatar
Johan Dahlin committed
439 440 441
G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
						gtk_notebook_buildable_init))
Elliot Lee's avatar
Elliot Lee committed
442

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
static void
add_tab_bindings (GtkBindingSet    *binding_set,
		  GdkModifierType   modifiers,
		  GtkDirectionType  direction)
{
  gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
}

static void
add_arrow_bindings (GtkBindingSet    *binding_set,
		    guint             keysym,
		    GtkDirectionType  direction)
{
  guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
  
  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
}

471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
static void
add_reorder_bindings (GtkBindingSet    *binding_set,
		      guint             keysym,
		      GtkDirectionType  direction,
		      gboolean          move_to_last)
{
  guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;

  gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
				"reorder_tab", 2,
				GTK_TYPE_DIRECTION_TYPE, direction,
				G_TYPE_BOOLEAN, move_to_last);
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
				"reorder_tab", 2,
				GTK_TYPE_DIRECTION_TYPE, direction,
				G_TYPE_BOOLEAN, move_to_last);
}

489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
static gboolean
gtk_object_handled_accumulator (GSignalInvocationHint *ihint,
                                GValue                *return_accu,
                                const GValue          *handler_return,
                                gpointer               dummy)
{
  gboolean continue_emission;
  GObject *object;

  object = g_value_get_object (handler_return);
  g_value_set_object (return_accu, object);
  continue_emission = !object;

  return continue_emission;
}

Elliot Lee's avatar
Elliot Lee committed
505 506 507
static void
gtk_notebook_class_init (GtkNotebookClass *class)
{
Tim Janik's avatar
Tim Janik committed
508 509 510 511
  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);
512 513
  GtkBindingSet *binding_set;
  
514 515
  gobject_class->set_property = gtk_notebook_set_property;
  gobject_class->get_property = gtk_notebook_get_property;
516 517
  object_class->destroy = gtk_notebook_destroy;

Elliot Lee's avatar
Elliot Lee committed
518 519 520
  widget_class->map = gtk_notebook_map;
  widget_class->unmap = gtk_notebook_unmap;
  widget_class->realize = gtk_notebook_realize;
521
  widget_class->unrealize = gtk_notebook_unrealize;
Elliot Lee's avatar
Elliot Lee committed
522 523 524
  widget_class->size_request = gtk_notebook_size_request;
  widget_class->size_allocate = gtk_notebook_size_allocate;
  widget_class->expose_event = gtk_notebook_expose;
525
  widget_class->scroll_event = gtk_notebook_scroll;
Elliot Lee's avatar
Elliot Lee committed
526
  widget_class->button_press_event = gtk_notebook_button_press;
527
  widget_class->button_release_event = gtk_notebook_button_release;
528
  widget_class->popup_menu = gtk_notebook_popup_menu;
529 530
  widget_class->leave_notify_event = gtk_notebook_leave_notify;
  widget_class->motion_notify_event = gtk_notebook_motion_notify;
Matthias Clasen's avatar
Matthias Clasen committed
531 532
  widget_class->grab_notify = gtk_notebook_grab_notify;
  widget_class->state_changed = gtk_notebook_state_changed;
533
  widget_class->focus_in_event = gtk_notebook_focus_in;
534
  widget_class->focus_out_event = gtk_notebook_focus_out;
535
  widget_class->focus = gtk_notebook_focus;
536
  widget_class->style_set = gtk_notebook_style_set;
537
  widget_class->drag_begin = gtk_notebook_drag_begin;
538
  widget_class->drag_end = gtk_notebook_drag_end;
539
  widget_class->drag_motion = gtk_notebook_drag_motion;
540
  widget_class->drag_leave = gtk_notebook_drag_leave;
541 542 543 544
  widget_class->drag_drop = gtk_notebook_drag_drop;
  widget_class->drag_data_get = gtk_notebook_drag_data_get;
  widget_class->drag_data_received = gtk_notebook_drag_data_received;

Elliot Lee's avatar
Elliot Lee committed
545 546
  container_class->add = gtk_notebook_add;
  container_class->remove = gtk_notebook_remove;
547
  container_class->forall = gtk_notebook_forall;
Lars Hamann's avatar
Lars Hamann committed
548
  container_class->set_focus_child = gtk_notebook_set_focus_child;
Tim Janik's avatar
Tim Janik committed
549 550
  container_class->get_child_property = gtk_notebook_get_child_property;
  container_class->set_child_property = gtk_notebook_set_child_property;
551
  container_class->child_type = gtk_notebook_child_type;
552

553
  class->switch_page = gtk_notebook_real_switch_page;
554
  class->insert_page = gtk_notebook_real_insert_page;
555

556 557
  class->focus_tab = gtk_notebook_focus_tab;
  class->select_page = gtk_notebook_select_page;
558
  class->change_current_page = gtk_notebook_change_current_page;
559
  class->move_focus_out = gtk_notebook_move_focus_out;
560
  class->reorder_tab = gtk_notebook_reorder_tab;
561
  class->create_window = gtk_notebook_create_window;
562
  
563 564 565
  g_object_class_install_property (gobject_class,
				   PROP_PAGE,
				   g_param_spec_int ("page",
566 567
 						     P_("Page"),
 						     P_("The index of the current page"),
568
 						     -1,
569
 						     G_MAXINT,
570
 						     -1,
571
 						     GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
572 573
  g_object_class_install_property (gobject_class,
				   PROP_TAB_POS,
Matthias Clasen's avatar
x  
Matthias Clasen committed
574
				   g_param_spec_enum ("tab-pos",
575 576
 						      P_("Tab Position"),
 						      P_("Which side of the notebook holds the tabs"),
577 578
 						      GTK_TYPE_POSITION_TYPE,
 						      GTK_POS_TOP,
579
 						      GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
580 581
  g_object_class_install_property (gobject_class,
				   PROP_TAB_BORDER,
Matthias Clasen's avatar
x  
Matthias Clasen committed
582
				   g_param_spec_uint ("tab-border",
583 584
 						      P_("Tab Border"),
 						      P_("Width of the border around the tab labels"),
585 586 587
 						      0,
 						      G_MAXUINT,
 						      2,
588
 						      GTK_PARAM_WRITABLE));
Tim Janik's avatar
Tim Janik committed
589 590
  g_object_class_install_property (gobject_class,
				   PROP_TAB_HBORDER,
Matthias Clasen's avatar
x  
Matthias Clasen committed
591
				   g_param_spec_uint ("tab-hborder",
592 593
 						      P_("Horizontal Tab Border"),
 						      P_("Width of the horizontal border of tab labels"),
594 595 596
 						      0,
 						      G_MAXUINT,
 						      2,
597
 						      GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
598 599
  g_object_class_install_property (gobject_class,
				   PROP_TAB_VBORDER,
Matthias Clasen's avatar
x  
Matthias Clasen committed
600
				   g_param_spec_uint ("tab-vborder",
601 602
 						      P_("Vertical Tab Border"),
 						      P_("Width of the vertical border of tab labels"),
603 604 605
 						      0,
 						      G_MAXUINT,
 						      2,
606
 						      GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
607 608
  g_object_class_install_property (gobject_class,
				   PROP_SHOW_TABS,
Matthias Clasen's avatar
x  
Matthias Clasen committed
609
				   g_param_spec_boolean ("show-tabs",
610 611
 							 P_("Show Tabs"),
 							 P_("Whether tabs should be shown or not"),
612
 							 TRUE,
613
 							 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
614 615
  g_object_class_install_property (gobject_class,
				   PROP_SHOW_BORDER,
Matthias Clasen's avatar
x  
Matthias Clasen committed
616
				   g_param_spec_boolean ("show-border",
617 618
 							 P_("Show Border"),
 							 P_("Whether the border should be shown or not"),
619
 							 TRUE,
620
 							 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
621 622 623
  g_object_class_install_property (gobject_class,
				   PROP_SCROLLABLE,
				   g_param_spec_boolean ("scrollable",
624 625
 							 P_("Scrollable"),
 							 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
626
 							 FALSE,
627
 							 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
628 629
  g_object_class_install_property (gobject_class,
				   PROP_ENABLE_POPUP,
Matthias Clasen's avatar
x  
Matthias Clasen committed
630
				   g_param_spec_boolean ("enable-popup",
631 632
 							 P_("Enable Popup"),
 							 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
633
 							 FALSE,
634
 							 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
635 636 637
  g_object_class_install_property (gobject_class,
				   PROP_HOMOGENEOUS,
				   g_param_spec_boolean ("homogeneous",
638 639
 							 P_("Homogeneous"),
 							 P_("Whether tabs should have homogeneous sizes"),
640
 							 FALSE,
641
							 GTK_PARAM_READWRITE));
642 643 644 645 646 647 648 649 650
  g_object_class_install_property (gobject_class,
				   PROP_GROUP_ID,
				   g_param_spec_int ("group-id",
						     P_("Group ID"),
						     P_("Group ID for tabs drag and drop"),
						     -1,
						     G_MAXINT,
						     -1,
						     GTK_PARAM_READWRITE));
Matthias Clasen's avatar
Matthias Clasen committed
651 652 653 654 655 656 657 658

  /**
   * GtkNotebook:group:
   *  
   * Group for tabs drag and drop.
   *
   * Since: 2.12
   */    
659 660 661 662 663 664
  g_object_class_install_property (gobject_class,
				   PROP_GROUP,
				   g_param_spec_pointer ("group",
							 P_("Group"),
							 P_("Group for tabs drag and drop"),
							 GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
665 666 667

  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_TAB_LABEL,
Matthias Clasen's avatar
x  
Matthias Clasen committed
668
					      g_param_spec_string ("tab-label", 
669
								   P_("Tab label"),
Matthias Clasen's avatar
Matthias Clasen committed
670
								   P_("The string displayed on the child's tab label"),
Tim Janik's avatar
Tim Janik committed
671
								   NULL,
672
								   GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
673 674
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_MENU_LABEL,
Matthias Clasen's avatar
x  
Matthias Clasen committed
675
					      g_param_spec_string ("menu-label", 
676
								   P_("Menu label"), 
Matthias Clasen's avatar
Matthias Clasen committed
677
								   P_("The string displayed in the child's menu entry"),
Tim Janik's avatar
Tim Janik committed
678
								   NULL,
679
								   GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
680 681
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_POSITION,
682
					      g_param_spec_int ("position", 
683 684
								P_("Position"), 
								P_("The index of the child in the parent"),
Tim Janik's avatar
Tim Janik committed
685
								-1, G_MAXINT, 0,
686
								GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
687 688
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_TAB_EXPAND,
Matthias Clasen's avatar
x  
Matthias Clasen committed
689
					      g_param_spec_boolean ("tab-expand", 
690
								    P_("Tab expand"), 
Matthias Clasen's avatar
Matthias Clasen committed
691
								    P_("Whether to expand the child's tab or not"),
692
								    FALSE,
693
								    GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
694 695
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_TAB_FILL,
Matthias Clasen's avatar
x  
Matthias Clasen committed
696
					      g_param_spec_boolean ("tab-fill", 
697
								    P_("Tab fill"), 
Matthias Clasen's avatar
Matthias Clasen committed
698
								    P_("Whether the child's tab should fill the allocated area or not"),
Tim Janik's avatar
Tim Janik committed
699
								    TRUE,
700
								    GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
701 702
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_TAB_PACK,
Matthias Clasen's avatar
x  
Matthias Clasen committed
703
					      g_param_spec_enum ("tab-pack", 
704 705
								 P_("Tab pack type"),
								 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
706
								 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
707
								 GTK_PARAM_READWRITE));
708 709 710 711 712 713 714 715 716 717 718 719 720 721
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_REORDERABLE,
					      g_param_spec_boolean ("reorderable",
								    P_("Tab reorderable"),
								    P_("Whether the tab is reorderable by user action or not"),
								    FALSE,
								    GTK_PARAM_READWRITE));
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_DETACHABLE,
					      g_param_spec_boolean ("detachable",
								    P_("Tab detachable"),
								    P_("Whether the tab is detachable"),
								    FALSE,
								    GTK_PARAM_READWRITE));
722 723 724 725 726 727 728 729 730 731

/**
 * GtkNotebook:has-secondary-backward-stepper:
 *
 * The "has-secondary-backward-stepper" property determines whether 
 * a second backward arrow button is displayed on the opposite end 
 * of the tab area.
 *
 * Since: 2.4
 */  
732
  gtk_widget_class_install_style_property (widget_class,
Matthias Clasen's avatar
x  
Matthias Clasen committed
733
					   g_param_spec_boolean ("has-secondary-backward-stepper",
734 735
								 P_("Secondary backward stepper"),
								 P_("Display a second backward arrow button on the opposite end of the tab area"),
736
								 FALSE,
737
								 GTK_PARAM_READABLE));
738

739 740 741 742 743 744 745 746 747
/**
 * GtkNotebook:has-secondary-forward-stepper:
 *
 * The "has-secondary-forward-stepper" property determines whether 
 * a second forward arrow button is displayed on the opposite end 
 * of the tab area.
 *
 * Since: 2.4
 */  
748
  gtk_widget_class_install_style_property (widget_class,
Matthias Clasen's avatar
x  
Matthias Clasen committed
749
					   g_param_spec_boolean ("has-secondary-forward-stepper",
750 751
								 P_("Secondary forward stepper"),
								 P_("Display a second forward arrow button on the opposite end of the tab area"),
752
								 FALSE,
753
								 GTK_PARAM_READABLE));
754

755 756 757 758 759 760 761 762
/**
 * GtkNotebook:has-backward-stepper:
 *
 * The "has-backward-stepper" property determines whether 
 * the standard backward arrow button is displayed.
 *
 * Since: 2.4
 */  
763
  gtk_widget_class_install_style_property (widget_class,
Matthias Clasen's avatar
x  
Matthias Clasen committed
764
					   g_param_spec_boolean ("has-backward-stepper",
765 766
								 P_("Backward stepper"),
								 P_("Display the standard backward arrow button"),
767
								 TRUE,
768
								 GTK_PARAM_READABLE));
769

770 771 772 773 774 775 776 777
/**
 * GtkNotebook:has-forward-stepper:
 *
 * The "has-forward-stepper" property determines whether 
 * the standard forward arrow button is displayed.
 *
 * Since: 2.4
 */  
778
  gtk_widget_class_install_style_property (widget_class,
Matthias Clasen's avatar
x  
Matthias Clasen committed
779
					   g_param_spec_boolean ("has-forward-stepper",
780 781
								 P_("Forward stepper"),
								 P_("Display the standard forward arrow button"),
782
								 TRUE,
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
								 GTK_PARAM_READABLE));
  
/**
 * GtkNotebook:tab-overlap:
 *
 * The "tab-overlap" property defines size of tab overlap
 * area.
 *
 * Since: 2.10
 */  
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_int ("tab-overlap",
							     P_("Tab overlap"),
							     P_("Size of tab overlap area"),
							     G_MININT,
							     G_MAXINT,
							     2,
							     GTK_PARAM_READABLE));

/**
 * GtkNotebook:tab-curvature:
 *
 * The "tab-curvature" property defines size of tab curvature.
 *
 * Since: 2.10
 */  
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_int ("tab-curvature",
							     P_("Tab curvature"),
							     P_("Size of tab curvature"),
							     0,
							     G_MAXINT,
							     1,
							     GTK_PARAM_READABLE));
817

818 819 820
  /**
   * GtkNotebook:arrow-spacing:
   *
821
   * The "arrow-spacing" property defines the spacing between the scroll
822 823 824 825 826 827 828 829 830 831 832 833 834
   * arrows and the tabs.
   *
   * Since: 2.10
   */
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("arrow-spacing",
                                                             _("Arrow spacing"),
                                                             _("Scroll arrow spacing"),
                                                             0,
                                                             G_MAXINT,
                                                             0,
                                                             GTK_PARAM_READABLE));

835
  notebook_signals[SWITCH_PAGE] =
Matthias Clasen's avatar
Matthias Clasen committed
836
    g_signal_new (I_("switch_page"),
Manish Singh's avatar
Manish Singh committed
837 838 839 840 841 842 843 844
		  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);
845
  notebook_signals[FOCUS_TAB] = 
Matthias Clasen's avatar
Matthias Clasen committed
846
    g_signal_new (I_("focus_tab"),
Manish Singh's avatar
Manish Singh committed
847
                  G_TYPE_FROM_CLASS (gobject_class),
848 849 850
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
                  NULL, NULL,
851
                  _gtk_marshal_BOOLEAN__ENUM,
852
                  G_TYPE_BOOLEAN, 1,
853
                  GTK_TYPE_NOTEBOOK_TAB);
854
  notebook_signals[SELECT_PAGE] = 
Matthias Clasen's avatar
Matthias Clasen committed
855
    g_signal_new (I_("select_page"),
Manish Singh's avatar
Manish Singh committed
856
                  G_TYPE_FROM_CLASS (gobject_class),
857 858 859
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, select_page),
                  NULL, NULL,
860 861
                  _gtk_marshal_BOOLEAN__BOOLEAN,
                  G_TYPE_BOOLEAN, 1,
862
                  G_TYPE_BOOLEAN);
863
  notebook_signals[CHANGE_CURRENT_PAGE] = 
Matthias Clasen's avatar
Matthias Clasen committed
864
    g_signal_new (I_("change_current_page"),
Manish Singh's avatar
Manish Singh committed
865
                  G_TYPE_FROM_CLASS (gobject_class),
866 867 868
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
                  NULL, NULL,
869 870
                  _gtk_marshal_BOOLEAN__INT,
                  G_TYPE_BOOLEAN, 1,
871
                  G_TYPE_INT);
872
  notebook_signals[MOVE_FOCUS_OUT] =
Matthias Clasen's avatar
Matthias Clasen committed
873
    g_signal_new (I_("move_focus_out"),
Manish Singh's avatar
Manish Singh committed
874
                  G_TYPE_FROM_CLASS (gobject_class),
875 876 877 878 879 880
                  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);
881 882 883 884 885 886
  notebook_signals[REORDER_TAB] =
    g_signal_new (I_("reorder_tab"),
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
                  NULL, NULL,
887 888
                  _gtk_marshal_BOOLEAN__ENUM_BOOLEAN,
                  G_TYPE_BOOLEAN, 2,
889 890 891
                  GTK_TYPE_DIRECTION_TYPE,
		  G_TYPE_BOOLEAN);
  /**
892
   * GtkNotebook::page-reordered:
893 894 895 896
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
897 898
   * the ::page-reordered signal is emitted in the notebook
   * right after a page has been reordered.
899 900 901
   *
   * Since: 2.10
   **/
902 903
  notebook_signals[PAGE_REORDERED] =
    g_signal_new (I_("page_reordered"),
904
                  G_TYPE_FROM_CLASS (gobject_class),
905
                  G_SIGNAL_RUN_LAST,
906
                  0, NULL, NULL,
907
		  _gtk_marshal_VOID__OBJECT_UINT,
908
                  G_TYPE_NONE, 2,
909
		  GTK_TYPE_WIDGET,
910 911
		  G_TYPE_UINT);
  /**
912
   * GtkNotebook::page-removed:
913 914 915 916
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the @child page number
   *
917
   * the ::page-removed signal is emitted in the notebook
918
   * right after a page is removed from the notebook.
919 920 921
   *
   * Since: 2.10
   **/
922 923
  notebook_signals[PAGE_REMOVED] =
    g_signal_new (I_("page_removed"),
924
                  G_TYPE_FROM_CLASS (gobject_class),
925
                  G_SIGNAL_RUN_LAST,
926
                  0, NULL, NULL,
927
		  _gtk_marshal_VOID__OBJECT_UINT,
928
                  G_TYPE_NONE, 2,
929
		  GTK_TYPE_WIDGET,
930 931
		  G_TYPE_UINT);
  /**
932
   * GtkNotebook::page-added:
933 934 935 936
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
937 938
   * the ::page-added signal is emitted in the notebook
   * right after a page is added to the notebook.
939 940 941
   *
   * Since: 2.10
   **/
942 943
  notebook_signals[PAGE_ADDED] =
    g_signal_new (I_("page_added"),
944
                  G_TYPE_FROM_CLASS (gobject_class),
945
                  G_SIGNAL_RUN_LAST,
946
                  0, NULL, NULL,
947
		  _gtk_marshal_VOID__OBJECT_UINT,
948
                  G_TYPE_NONE, 2,
949
		  GTK_TYPE_WIDGET,
950 951
		  G_TYPE_UINT);

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
  /**
   * GtkNotebook::create-window:
   * @notebook: the #GtkNotebook emitting the signal
   * @page: the tab of @notebook that is being detached
   * @x: the X coordinate where the drop happens
   * @y: the Y coordinate where the drop happens
   *
   * The ::create-window signal is emitted when a detachable
   * tab is dropped on the root window. 
   *
   * A handler for this signal can create a window containing 
   * a notebook where the tab will be attached. It is also 
   * responsible for moving/resizing the window and adding the 
   * necessary properties to the notebook (e.g. the 
   * #GtkNotebook:group-id ).
   *
   * The default handler uses the global window creation hook,
   * if one has been set with gtk_notebook_set_window_creation_hook().
   *
   * Returns: a #GtkNotebook that @page should be added to, or %NULL.
   *
   * Since: 2.12
   */
  notebook_signals[CREATE_WINDOW] = 
    g_signal_new (I_("create_window"),
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkNotebookClass, create_window),
                  gtk_object_handled_accumulator, NULL,
                  _gtk_marshal_OBJECT__OBJECT_INT_INT,
                  GTK_TYPE_NOTEBOOK, 3,
                  GTK_TYPE_WIDGET, G_TYPE_INT, G_TYPE_INT);
 
Manish Singh's avatar
Manish Singh committed
985
  binding_set = gtk_binding_set_by_class (class);
986 987 988 989
  gtk_binding_entry_add_signal (binding_set,
                                GDK_space, 0,
                                "select_page", 1, 
                                G_TYPE_BOOLEAN, FALSE);
990 991 992 993 994
  gtk_binding_entry_add_signal (binding_set,
                                GDK_KP_Space, 0,
                                "select_page", 1, 
                                G_TYPE_BOOLEAN, FALSE);
  
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
  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);
1011 1012 1013 1014 1015 1016 1017 1018 1019

  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);
1020

1021
  gtk_binding_entry_add_signal (binding_set,
1022
                                GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
1023 1024 1025
                                "change_current_page", 1,
                                G_TYPE_INT, -1);
  gtk_binding_entry_add_signal (binding_set,
1026
                                GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
1027 1028 1029
                                "change_current_page", 1,
                                G_TYPE_INT, 1);

1030 1031 1032 1033 1034
  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);

1035 1036 1037 1038 1039 1040 1041 1042 1043
  add_reorder_bindings (binding_set, GDK_Up, GTK_DIR_UP, FALSE);
  add_reorder_bindings (binding_set, GDK_Down, GTK_DIR_DOWN, FALSE);
  add_reorder_bindings (binding_set, GDK_Left, GTK_DIR_LEFT, FALSE);
  add_reorder_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT, FALSE);
  add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_LEFT, TRUE);
  add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_UP, TRUE);
  add_reorder_bindings (binding_set, GDK_End, GTK_DIR_RIGHT, TRUE);
  add_reorder_bindings (binding_set, GDK_End, GTK_DIR_DOWN, TRUE);

1044 1045
  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);
1046 1047

  g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
Elliot Lee's avatar
Elliot Lee committed
1048 1049
}

1050
static void
1051 1052
gtk_notebook_init (GtkNotebook *notebook)
{
1053 1054
  GtkNotebookPrivate *priv;

1055
  GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
1056
  GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
1057

1058 1059
  priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);

1060 1061 1062 1063
  notebook->cur_page = NULL;
  notebook->children = NULL;
  notebook->first_tab = NULL;
  notebook->focus_tab = NULL;
1064
  notebook->event_window = NULL;
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
  notebook->menu = NULL;

  notebook->tab_hborder = 2;
  notebook->tab_vborder = 2;

  notebook->show_tabs = TRUE;
  notebook->show_border = TRUE;
  notebook->tab_pos = GTK_POS_TOP;
  notebook->scrollable = FALSE;
  notebook->in_child = 0;
  notebook->click_child = 0;
  notebook->button = 0;
  notebook->need_timer = 0;
  notebook->child_has_focus = FALSE;
1079
  notebook->have_visible_child = FALSE;
1080
  notebook->focus_out = FALSE;
1081 1082 1083 1084 1085

  notebook->has_before_previous = 1;
  notebook->has_before_next     = 0;
  notebook->has_after_previous  = 0;
  notebook->has_after_next      = 1;
1086

1087
  priv->group = NULL;
1088 1089
  priv->pressed_button = -1;
  priv->dnd_timer = 0;
1090
  priv->switch_tab_timer = 0;
1091 1092
  priv->source_targets = gtk_target_list_new (notebook_targets,
					      G_N_ELEMENTS (notebook_targets));
1093 1094 1095 1096
  priv->operation = DRAG_OPERATION_NONE;
  priv->detached_tab = NULL;
  priv->during_detach = FALSE;
  priv->has_scrolled = FALSE;
1097

1098
  gtk_drag_dest_set (GTK_WIDGET (notebook), 0,
1099
		     notebook_targets, G_N_ELEMENTS (notebook_targets),
1100
                     GDK_ACTION_MOVE);
1101

1102 1103 1104
  g_signal_connect (G_OBJECT (notebook), "drag-failed",
		    G_CALLBACK (gtk_notebook_drag_failed), NULL);

1105
  gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
1106 1107
}

Johan Dahlin's avatar
Johan Dahlin committed
1108 1109 1110
static void
gtk_notebook_buildable_init (GtkBuildableIface *iface)
{
1111
  iface->add_child = gtk_notebook_buildable_add_child;
Johan Dahlin's avatar
Johan Dahlin committed
1112 1113 1114
}

static void
1115 1116 1117 1118
gtk_notebook_buildable_add_child (GtkBuildable  *buildable,
				  GtkBuilder    *builder,
				  GObject       *child,
				  const gchar   *type)
Johan Dahlin's avatar
Johan Dahlin committed
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
{
  GtkNotebook *notebook = GTK_NOTEBOOK (buildable);

  if (type && strcmp (type, "tab") == 0)
    {
      GtkWidget * page;

      page = gtk_notebook_get_nth_page (notebook, -1);
      /* To set the tab label widget, we must have already a child
       * inside the tab container. */
      g_assert (page != NULL);
      gtk_notebook_set_tab_label (notebook, page, GTK_WIDGET (child));
    }
  else if (!type)
    gtk_notebook_append_page (notebook, GTK_WIDGET (child), NULL);
  else
    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (notebook, type);
}

1138
static gboolean
1139 1140 1141
gtk_notebook_select_page (GtkNotebook *notebook,
                          gboolean     move_focus)
{
1142
  if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && notebook->show_tabs)