gtktoolbar.c 105 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 * GtkToolbar copyright (C) Federico Mena
 *
5
 * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
6
 * Copyright (C) 2002 James Henstridge <james@daa.com.au>
7
 * Copyright (C) 2003, 2004 Soeren Sandmann <sandmann@daimi.au.dk>
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11 12 13 14 15 16
 * 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
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
20
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 22
 */

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

30

31
#include "config.h"
32 33 34 35

#include <math.h>
#include <string.h>

36
#include "gtktoolbar.h"
37
#include "gtktoolbarprivate.h"
38

39
#include "gtkbindings.h"
40
#include "gtkbox.h"
41
#include "gtkcontainerprivate.h"
42
#include "gtkcsscustomgadgetprivate.h"
43
#include "gtkcssnodeprivate.h"
44
#include "gtkimage.h"
45
#include "gtkintl.h"
46
#include "gtklabel.h"
47
#include "gtkmain.h"
48 49 50
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkorientable.h"
51
#include "gtkorientableprivate.h"
52
#include "gtkprivate.h"
53 54
#include "gtkradiobutton.h"
#include "gtkradiotoolbutton.h"
55
#include "gtkrender.h"
56 57 58
#include "gtkseparatormenuitem.h"
#include "gtkseparatortoolitem.h"
#include "gtktoolshell.h"
59
#include "gtktypebuiltins.h"
60
#include "gtkwidgetpath.h"
61
#include "gtkwidgetprivate.h"
62
#include "gtkwindowprivate.h"
63

64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/**
 * SECTION:gtktoolbar
 * @Short_description: Create bars of buttons and other widgets
 * @Title: GtkToolbar
 * @See_also: #GtkToolItem
 *
 * A toolbar is created with a call to gtk_toolbar_new().
 *
 * A toolbar can contain instances of a subclass of #GtkToolItem. To add
 * a #GtkToolItem to the a toolbar, use gtk_toolbar_insert(). To remove
 * an item from the toolbar use gtk_container_remove(). To add a button
 * to the toolbar, add an instance of #GtkToolButton.
 *
 * Toolbar items can be visually grouped by adding instances of
 * #GtkSeparatorToolItem to the toolbar. If the GtkToolbar child property
80
 * “expand” is #TRUE and the property #GtkSeparatorToolItem:draw is set to
81 82 83 84
 * #FALSE, the effect is to force all following items to the end of the toolbar.
 *
 * Creating a context menu for the toolbar can be done by connecting to
 * the #GtkToolbar::popup-context-menu signal.
85 86 87 88
 *
 * # CSS nodes
 *
 * GtkToolbar has a single CSS node with name toolbar.
89 90 91
 */


92 93
typedef struct _ToolbarContent ToolbarContent;

94
#define DEFAULT_SPACE_SIZE  12
95
#define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
96
#define SPACE_LINE_DIVISION 10.0
97 98
#define SPACE_LINE_START    2.0
#define SPACE_LINE_END      8.0
99

100
#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
101
#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH_HORIZ
102
#define DEFAULT_ANIMATION_STATE TRUE
103

104 105
#define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
				    * in the homogeneous game. In units of
106 107
				    * pango_font_get_estimated_char_width().
				    */
108 109
#define SLIDE_SPEED 600.0	   /* How fast the items slide, in pixels per second */
#define ACCEL_THRESHOLD 0.18	   /* After how much time in seconds will items start speeding up */
110

111

112
struct _GtkToolbarPrivate
113 114 115
{
  GtkMenu         *menu;
  GtkSettings     *settings;
116 117

  GtkIconSize      icon_size;
118
  GtkToolbarStyle  style;
119

120 121 122 123 124 125
  GtkToolItem     *highlight_tool_item;
  GtkWidget       *arrow;
  GtkWidget       *arrow_button;

  GdkWindow       *event_window;

126 127 128
  GtkCssGadget    *gadget;
  GtkAllocation    prev_allocation;

129 130 131 132
  GList           *content;

  GTimer          *timer;

133 134
  gulong           settings_connection;

135 136 137 138 139 140
  gint             idle_id;
  gint             button_maxw;         /* maximum width of homogeneous children */
  gint             button_maxh;         /* maximum height of homogeneous children */
  gint             max_homogeneous_pixels;
  gint             num_children;

141
  GtkOrientation   orientation;
142 143 144 145 146 147 148 149 150 151

  guint            animation : 1;
  guint            icon_size_set : 1;
  guint            is_sliding : 1;
  guint            need_rebuild : 1;  /* whether the overflow menu should be regenerated */
  guint            need_sync : 1;
  guint            show_arrow : 1;
  guint            style_set     : 1;
};

152
/* Properties */
153
enum {
154 155
  PROP_0,
  PROP_ORIENTATION,
156
  PROP_TOOLBAR_STYLE,
157
  PROP_SHOW_ARROW,
158 159 160
  PROP_TOOLTIPS,
  PROP_ICON_SIZE,
  PROP_ICON_SIZE_SET
161 162
};

163
/* Child properties */
164 165 166
enum {
  CHILD_PROP_0,
  CHILD_PROP_EXPAND,
167
  CHILD_PROP_HOMOGENEOUS
168 169
};

170
/* Signals */
171
enum {
172 173
  ORIENTATION_CHANGED,
  STYLE_CHANGED,
174
  POPUP_CONTEXT_MENU,
175
  FOCUS_HOME_OR_END,
176
  LAST_SIGNAL
177 178
};

179 180 181 182
typedef enum {
  NOT_ALLOCATED,
  NORMAL,
  HIDDEN,
183
  OVERFLOWN
184
} ItemState;
Matthias Clasen's avatar
Matthias Clasen committed
185

186

187 188 189 190 191 192 193 194
static void       gtk_toolbar_set_property         (GObject             *object,
						    guint                prop_id,
						    const GValue        *value,
						    GParamSpec          *pspec);
static void       gtk_toolbar_get_property         (GObject             *object,
						    guint                prop_id,
						    GValue              *value,
						    GParamSpec          *pspec);
195 196
static gint       gtk_toolbar_draw                 (GtkWidget           *widget,
                                                    cairo_t             *cr);
197 198
static void       gtk_toolbar_realize              (GtkWidget           *widget);
static void       gtk_toolbar_unrealize            (GtkWidget           *widget);
199 200 201 202 203 204 205
static void       gtk_toolbar_get_preferred_width  (GtkWidget           *widget,
                                                    gint                *minimum,
                                                    gint                *natural);
static void       gtk_toolbar_get_preferred_height (GtkWidget           *widget,
                                                    gint                *minimum,
                                                    gint                *natural);

206 207
static void       gtk_toolbar_size_allocate        (GtkWidget           *widget,
						    GtkAllocation       *allocation);
208
static void       gtk_toolbar_style_updated        (GtkWidget           *widget);
209 210
static gboolean   gtk_toolbar_focus                (GtkWidget           *widget,
						    GtkDirectionType     dir);
211 212
static void       gtk_toolbar_move_focus           (GtkWidget           *widget,
						    GtkDirectionType     dir);
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
static void       gtk_toolbar_screen_changed       (GtkWidget           *widget,
						    GdkScreen           *previous_screen);
static void       gtk_toolbar_map                  (GtkWidget           *widget);
static void       gtk_toolbar_unmap                (GtkWidget           *widget);
static void       gtk_toolbar_set_child_property   (GtkContainer        *container,
						    GtkWidget           *child,
						    guint                property_id,
						    const GValue        *value,
						    GParamSpec          *pspec);
static void       gtk_toolbar_get_child_property   (GtkContainer        *container,
						    GtkWidget           *child,
						    guint                property_id,
						    GValue              *value,
						    GParamSpec          *pspec);
static void       gtk_toolbar_finalize             (GObject             *object);
228
static void       gtk_toolbar_dispose              (GObject             *object);
229 230 231 232 233 234 235 236 237 238
static void       gtk_toolbar_show_all             (GtkWidget           *widget);
static void       gtk_toolbar_add                  (GtkContainer        *container,
						    GtkWidget           *widget);
static void       gtk_toolbar_remove               (GtkContainer        *container,
						    GtkWidget           *widget);
static void       gtk_toolbar_forall               (GtkContainer        *container,
						    gboolean             include_internals,
						    GtkCallback          callback,
						    gpointer             callback_data);
static GType      gtk_toolbar_child_type           (GtkContainer        *container);
239

240 241
static void       gtk_toolbar_direction_changed    (GtkWidget           *widget,
                                                    GtkTextDirection     previous_direction);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
static void       gtk_toolbar_orientation_changed  (GtkToolbar          *toolbar,
						    GtkOrientation       orientation);
static void       gtk_toolbar_real_style_changed   (GtkToolbar          *toolbar,
						    GtkToolbarStyle      style);
static gboolean   gtk_toolbar_focus_home_or_end    (GtkToolbar          *toolbar,
						    gboolean             focus_home);
static gboolean   gtk_toolbar_button_press         (GtkWidget           *toolbar,
						    GdkEventButton      *event);
static gboolean   gtk_toolbar_arrow_button_press   (GtkWidget           *button,
						    GdkEventButton      *event,
						    GtkToolbar          *toolbar);
static void       gtk_toolbar_arrow_button_clicked (GtkWidget           *button,
						    GtkToolbar          *toolbar);
static void       gtk_toolbar_update_button_relief (GtkToolbar          *toolbar);
static gboolean   gtk_toolbar_popup_menu           (GtkWidget           *toolbar);
static void       gtk_toolbar_reconfigured         (GtkToolbar          *toolbar);
258

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
static void       gtk_toolbar_allocate             (GtkCssGadget        *gadget,
                                                    const GtkAllocation *allocation,
                                                    int                  baseline,
                                                    GtkAllocation       *out_clip,
                                                    gpointer             data);
static void       gtk_toolbar_measure              (GtkCssGadget   *gadget,
                                                    GtkOrientation  orientation,
                                                    int             for_size,
                                                    int            *minimum,
                                                    int            *natural,
                                                    int            *minimum_baseline,
                                                    int            *natural_baseline,
                                                    gpointer        data);
static gboolean   gtk_toolbar_render               (GtkCssGadget *gadget,
                                                    cairo_t      *cr,
                                                    int           x,
                                                    int           y,
                                                    int           width,
                                                    int           height,
                                                    gpointer      data);

280
static GtkReliefStyle       get_button_relief    (GtkToolbar *toolbar);
281
static gint                 get_max_child_expand (GtkToolbar *toolbar);
282

283 284 285 286 287 288 289 290
/* methods on ToolbarContent 'class' */
static ToolbarContent *toolbar_content_new_tool_item        (GtkToolbar          *toolbar,
							     GtkToolItem         *item,
							     gboolean             is_placeholder,
							     gint                 pos);
static void            toolbar_content_remove               (ToolbarContent      *content,
							     GtkToolbar          *toolbar);
static void            toolbar_content_free                 (ToolbarContent      *content);
291
static void            toolbar_content_draw                 (ToolbarContent      *content,
292
							     GtkContainer        *container,
293
                                                             cairo_t             *cr);
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
static gboolean        toolbar_content_visible              (ToolbarContent      *content,
							     GtkToolbar          *toolbar);
static void            toolbar_content_size_request         (ToolbarContent      *content,
							     GtkToolbar          *toolbar,
							     GtkRequisition      *requisition);
static gboolean        toolbar_content_is_homogeneous       (ToolbarContent      *content,
							     GtkToolbar          *toolbar);
static gboolean        toolbar_content_is_placeholder       (ToolbarContent      *content);
static gboolean        toolbar_content_disappearing         (ToolbarContent      *content);
static ItemState       toolbar_content_get_state            (ToolbarContent      *content);
static gboolean        toolbar_content_child_visible        (ToolbarContent      *content);
static void            toolbar_content_get_goal_allocation  (ToolbarContent      *content,
							     GtkAllocation       *allocation);
static void            toolbar_content_get_allocation       (ToolbarContent      *content,
							     GtkAllocation       *allocation);
static void            toolbar_content_set_start_allocation (ToolbarContent      *content,
							     GtkAllocation       *new_start_allocation);
static void            toolbar_content_get_start_allocation (ToolbarContent      *content,
							     GtkAllocation       *start_allocation);
static gboolean        toolbar_content_get_expand           (ToolbarContent      *content);
static void            toolbar_content_set_goal_allocation  (ToolbarContent      *content,
							     GtkAllocation       *allocation);
static void            toolbar_content_set_child_visible    (ToolbarContent      *content,
							     GtkToolbar          *toolbar,
							     gboolean             visible);
static void            toolbar_content_size_allocate        (ToolbarContent      *content,
							     GtkAllocation       *allocation);
static void            toolbar_content_set_state            (ToolbarContent      *content,
							     ItemState            new_state);
static GtkWidget *     toolbar_content_get_widget           (ToolbarContent      *content);
static void            toolbar_content_set_disappearing     (ToolbarContent      *content,
							     gboolean             disappearing);
static void            toolbar_content_set_size_request     (ToolbarContent      *content,
							     gint                 width,
							     gint                 height);
static void            toolbar_content_toolbar_reconfigured (ToolbarContent      *content,
							     GtkToolbar          *toolbar);
static GtkWidget *     toolbar_content_retrieve_menu_item   (ToolbarContent      *content);
332
static gboolean        toolbar_content_has_proxy_menu_item  (ToolbarContent	 *content);
333 334
static gboolean        toolbar_content_is_separator         (ToolbarContent      *content);
static void            toolbar_content_show_all             (ToolbarContent      *content);
335 336
static void	       toolbar_content_set_expand	    (ToolbarContent      *content,
							     gboolean		  expand);
337

338 339 340 341 342 343 344
static void            toolbar_tool_shell_iface_init        (GtkToolShellIface   *iface);
static GtkIconSize     toolbar_get_icon_size                (GtkToolShell        *shell);
static GtkOrientation  toolbar_get_orientation              (GtkToolShell        *shell);
static GtkToolbarStyle toolbar_get_style                    (GtkToolShell        *shell);
static GtkReliefStyle  toolbar_get_relief_style             (GtkToolShell        *shell);
static void            toolbar_rebuild_menu                 (GtkToolShell        *shell);

345

346
G_DEFINE_TYPE_WITH_CODE (GtkToolbar, gtk_toolbar, GTK_TYPE_CONTAINER,
347
                         G_ADD_PRIVATE (GtkToolbar)
348 349 350 351 352 353 354
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL,
                                                toolbar_tool_shell_iface_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
                                                NULL))

static guint toolbar_signals[LAST_SIGNAL] = { 0 };

355 356 357 358 359 360

static void
add_arrow_bindings (GtkBindingSet   *binding_set,
		    guint            keysym,
		    GtkDirectionType dir)
{
361
  guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
362 363
  
  gtk_binding_entry_add_signal (binding_set, keysym, 0,
364
                                "move-focus", 1,
365 366
                                GTK_TYPE_DIRECTION_TYPE, dir);
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
367
                                "move-focus", 1,
368 369
                                GTK_TYPE_DIRECTION_TYPE, dir);
}
370

371 372 373 374 375 376
static void
add_ctrl_tab_bindings (GtkBindingSet    *binding_set,
		       GdkModifierType   modifiers,
		       GtkDirectionType  direction)
{
  gtk_binding_entry_add_signal (binding_set,
377
				GDK_KEY_Tab, GDK_CONTROL_MASK | modifiers,
378
				"move-focus", 1,
379 380
				GTK_TYPE_DIRECTION_TYPE, direction);
  gtk_binding_entry_add_signal (binding_set,
381
				GDK_KEY_KP_Tab, GDK_CONTROL_MASK | modifiers,
382
				"move-focus", 1,
383
				GTK_TYPE_DIRECTION_TYPE, direction);
384 385 386
}

static void
387
gtk_toolbar_class_init (GtkToolbarClass *klass)
388
{
389
  GObjectClass *gobject_class;
390 391
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;
392
  GtkBindingSet *binding_set;
393
  
394 395 396 397
  gobject_class = (GObjectClass *)klass;
  widget_class = (GtkWidgetClass *)klass;
  container_class = (GtkContainerClass *)klass;
  
398 399
  gobject_class->set_property = gtk_toolbar_set_property;
  gobject_class->get_property = gtk_toolbar_get_property;
400
  gobject_class->finalize = gtk_toolbar_finalize;
401
  gobject_class->dispose = gtk_toolbar_dispose;
402
  
403
  widget_class->button_press_event = gtk_toolbar_button_press;
404
  widget_class->draw = gtk_toolbar_draw;
405 406
  widget_class->get_preferred_width = gtk_toolbar_get_preferred_width;
  widget_class->get_preferred_height = gtk_toolbar_get_preferred_height;
407
  widget_class->size_allocate = gtk_toolbar_size_allocate;
408
  widget_class->style_updated = gtk_toolbar_style_updated;
409
  widget_class->focus = gtk_toolbar_focus;
410

411 412
  gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_BAR);

413
  /* need to override the base class function via override_class_handler,
414 415
   * because the signal slot is not available in GtkWidgetClass
   */
416
  g_signal_override_class_handler ("move-focus",
417
                                   GTK_TYPE_TOOLBAR,
418
                                   G_CALLBACK (gtk_toolbar_move_focus));
419

420
  widget_class->screen_changed = gtk_toolbar_screen_changed;
421 422 423 424
  widget_class->realize = gtk_toolbar_realize;
  widget_class->unrealize = gtk_toolbar_unrealize;
  widget_class->map = gtk_toolbar_map;
  widget_class->unmap = gtk_toolbar_unmap;
425
  widget_class->popup_menu = gtk_toolbar_popup_menu;
426
  widget_class->show_all = gtk_toolbar_show_all;
427
  widget_class->direction_changed = gtk_toolbar_direction_changed;
Havoc Pennington's avatar
Havoc Pennington committed
428
  
429
  container_class->add    = gtk_toolbar_add;
430
  container_class->remove = gtk_toolbar_remove;
431
  container_class->forall = gtk_toolbar_forall;
432 433 434
  container_class->child_type = gtk_toolbar_child_type;
  container_class->get_child_property = gtk_toolbar_get_child_property;
  container_class->set_child_property = gtk_toolbar_set_child_property;
435

436 437
  gtk_container_class_handle_border_width (container_class);

438
  klass->orientation_changed = gtk_toolbar_orientation_changed;
439
  klass->style_changed = gtk_toolbar_real_style_changed;
440
  
441 442 443 444 445 446 447
  /**
   * GtkToolbar::orientation-changed:
   * @toolbar: the object which emitted the signal
   * @orientation: the new #GtkOrientation of the toolbar
   *
   * Emitted when the orientation of the toolbar changes.
   */
448
  toolbar_signals[ORIENTATION_CHANGED] =
449
    g_signal_new (I_("orientation-changed"),
450
		  G_OBJECT_CLASS_TYPE (klass),
Manish Singh's avatar
Manish Singh committed
451 452 453
		  G_SIGNAL_RUN_FIRST,
		  G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
		  NULL, NULL,
454
		  g_cclosure_marshal_VOID__ENUM,
Manish Singh's avatar
Manish Singh committed
455 456
		  G_TYPE_NONE, 1,
		  GTK_TYPE_ORIENTATION);
457 458 459 460 461 462 463
  /**
   * GtkToolbar::style-changed:
   * @toolbar: The #GtkToolbar which emitted the signal
   * @style: the new #GtkToolbarStyle of the toolbar
   *
   * Emitted when the style of the toolbar changes. 
   */
464
  toolbar_signals[STYLE_CHANGED] =
465
    g_signal_new (I_("style-changed"),
466
		  G_OBJECT_CLASS_TYPE (klass),
Manish Singh's avatar
Manish Singh committed
467 468 469
		  G_SIGNAL_RUN_FIRST,
		  G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
		  NULL, NULL,
470
		  g_cclosure_marshal_VOID__ENUM,
Manish Singh's avatar
Manish Singh committed
471 472
		  G_TYPE_NONE, 1,
		  GTK_TYPE_TOOLBAR_STYLE);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
  /**
   * GtkToolbar::popup-context-menu:
   * @toolbar: the #GtkToolbar which emitted the signal
   * @x: the x coordinate of the point where the menu should appear
   * @y: the y coordinate of the point where the menu should appear
   * @button: the mouse button the user pressed, or -1
   *
   * Emitted when the user right-clicks the toolbar or uses the
   * keybinding to display a popup menu.
   *
   * Application developers should handle this signal if they want
   * to display a context menu on the toolbar. The context-menu should
   * appear at the coordinates given by @x and @y. The mouse button
   * number is given by the @button parameter. If the menu was popped
   * up using the keybaord, @button is -1.
   *
489
   * Returns: return %TRUE if the signal was handled, %FALSE if not
490
   */
491
  toolbar_signals[POPUP_CONTEXT_MENU] =
492
    g_signal_new (I_("popup-context-menu"),
493
		  G_OBJECT_CLASS_TYPE (klass),
494
		  G_SIGNAL_RUN_LAST,
495
		  G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
496 497 498 499 500
		  _gtk_boolean_handled_accumulator, NULL,
		  _gtk_marshal_BOOLEAN__INT_INT_INT,
		  G_TYPE_BOOLEAN, 3,
		  G_TYPE_INT, G_TYPE_INT,
		  G_TYPE_INT);
501

502 503 504 505 506 507 508 509
  /**
   * GtkToolbar::focus-home-or-end:
   * @toolbar: the #GtkToolbar which emitted the signal
   * @focus_home: %TRUE if the first item should be focused
   *
   * A keybinding signal used internally by GTK+. This signal can't
   * be used in application code
   *
510
   * Returns: %TRUE if the signal was handled, %FALSE if not
511
   */
512
  toolbar_signals[FOCUS_HOME_OR_END] =
513
    g_signal_new_class_handler (I_("focus-home-or-end"),
514 515 516 517 518 519 520 521
                                G_OBJECT_CLASS_TYPE (klass),
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                G_CALLBACK (gtk_toolbar_focus_home_or_end),
                                NULL, NULL,
                                _gtk_marshal_BOOLEAN__BOOLEAN,
                                G_TYPE_BOOLEAN, 1,
                                G_TYPE_BOOLEAN);

522
  /* properties */
523 524 525 526
  g_object_class_override_property (gobject_class,
                                    PROP_ORIENTATION,
                                    "orientation");

527 528
  g_object_class_install_property (gobject_class,
				   PROP_TOOLBAR_STYLE,
529
				   g_param_spec_enum ("toolbar-style",
530 531
 						      P_("Toolbar Style"),
 						      P_("How to draw the toolbar"),
532
 						      GTK_TYPE_TOOLBAR_STYLE,
533
 						      DEFAULT_TOOLBAR_STYLE,
534
 						      GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
535 536
  g_object_class_install_property (gobject_class,
				   PROP_SHOW_ARROW,
537
				   g_param_spec_boolean ("show-arrow",
538 539
							 P_("Show Arrow"),
							 P_("If an arrow should be shown if the toolbar doesn't fit"),
540
							 TRUE,
541
							 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557

  /**
   * GtkToolbar:icon-size:
   *
   * The size of the icons in a toolbar is normally determined by
   * the toolbar-icon-size setting. When this property is set, it 
   * overrides the setting. 
   * 
   * This should only be used for special-purpose toolbars, normal
   * application toolbars should respect the user preferences for the
   * size of icons.
   *
   * Since: 2.10
   */
  g_object_class_install_property (gobject_class,
				   PROP_ICON_SIZE,
558 559 560 561 562
				   g_param_spec_enum ("icon-size",
                                                      P_("Icon size"),
                                                      P_("Size of icons in this toolbar"),
                                                      GTK_TYPE_ICON_SIZE,
                                                      DEFAULT_ICON_SIZE,
563
                                                      GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579

  /**
   * GtkToolbar:icon-size-set:
   *
   * Is %TRUE if the icon-size property has been set.
   *
   * Since: 2.10
   */
  g_object_class_install_property (gobject_class,
				   PROP_ICON_SIZE_SET,
				   g_param_spec_boolean ("icon-size-set",
							 P_("Icon size set"),
							 P_("Whether the icon-size property has been set"),
							 FALSE,
							 GTK_PARAM_READWRITE));  

580 581 582 583
  /* child properties */
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_EXPAND,
					      g_param_spec_boolean ("expand", 
584 585
								    P_("Expand"), 
								    P_("Whether the item should receive extra space when the toolbar grows"),
586
								    FALSE,
587
								    GTK_PARAM_READWRITE));
588
  
589 590 591
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_HOMOGENEOUS,
					      g_param_spec_boolean ("homogeneous", 
592 593
								    P_("Homogeneous"), 
								    P_("Whether the item should be the same size as other homogeneous items"),
594
								    FALSE,
595
								    GTK_PARAM_READWRITE));
596
  
597 598 599 600 601 602 603 604
  /**
   * GtkToolbar:space-size:
   *
   * Size of toolbar spacers.
   *
   * Deprecated: 3.20: Use the standard margin/padding CSS properties on the
   *   separator elements; the value of this style property is ignored.
   */
Havoc Pennington's avatar
Havoc Pennington committed
605
  gtk_widget_class_install_style_property (widget_class,
606
					   g_param_spec_int ("space-size",
607 608
							     P_("Spacer size"),
							     P_("Size of spacers"),
Havoc Pennington's avatar
Havoc Pennington committed
609 610 611
							     0,
							     G_MAXINT,
                                                             DEFAULT_SPACE_SIZE,
612
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
613
  
614 615 616 617 618 619 620 621 622
  /**
   * GtkToolbar:internal-padding:
   *
   * Amount of border space between the toolbar shadow and the buttons.
   *
   * Deprecated: 3.6: Use the standard padding CSS property
   *   (through objects like #GtkStyleContext and #GtkCssProvider); the value
   *   of this style property is ignored.
   */
623
  gtk_widget_class_install_style_property (widget_class,
624
					   g_param_spec_int ("internal-padding",
625 626
							     P_("Internal padding"),
							     P_("Amount of border space between the toolbar shadow and the buttons"),
627 628
							     0,
							     G_MAXINT,
629
                                                             0,
630
                                                             GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
631 632 633

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("max-child-expand",
634 635
                                                             P_("Maximum child expand"),
                                                             P_("Maximum amount of space an expandable item will be given"),
636 637 638 639 640
                                                             0,
                                                             G_MAXINT,
                                                             G_MAXINT,
                                                             GTK_PARAM_READABLE));

641 642 643 644 645 646 647 648
  /**
   * GtkToolbar:space-style:
   *
   * Style of toolbar spacers.
   *
   * Deprecated: 3.20: Use CSS properties on the separator elements to style
   *   toolbar spacers; the value of this style property is ignored.
   */
Havoc Pennington's avatar
Havoc Pennington committed
649
  gtk_widget_class_install_style_property (widget_class,
650
					   g_param_spec_enum ("space-style",
651 652
							      P_("Space style"),
							      P_("Whether spacers are vertical lines or just blank"),
Havoc Pennington's avatar
Havoc Pennington committed
653 654
                                                              GTK_TYPE_TOOLBAR_SPACE_STYLE,
                                                              DEFAULT_SPACE_STYLE,
655
                                                              GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
656
  
Havoc Pennington's avatar
Havoc Pennington committed
657
  gtk_widget_class_install_style_property (widget_class,
658
					   g_param_spec_enum ("button-relief",
659 660
							      P_("Button relief"),
							      P_("Type of bevel around toolbar buttons"),
Havoc Pennington's avatar
Havoc Pennington committed
661
                                                              GTK_TYPE_RELIEF_STYLE,
662
                                                              GTK_RELIEF_NONE,
663
                                                              GTK_PARAM_READABLE));
664 665 666 667 668 669 670 671 672
  /**
   * GtkToolbar:shadow-type:
   *
   * Style of bevel around the toolbar.
   *
   * Deprecated: 3.6: Use the standard border CSS property
   *   (through objects like #GtkStyleContext and #GtkCssProvider); the value
   *   of this style property is ignored.
   */
673
  gtk_widget_class_install_style_property (widget_class,
674
                                           g_param_spec_enum ("shadow-type",
675 676
                                                              P_("Shadow type"),
                                                              P_("Style of bevel around the toolbar"),
677 678
                                                              GTK_TYPE_SHADOW_TYPE,
                                                              GTK_SHADOW_OUT,
679
                                                              GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
680

681
  binding_set = gtk_binding_set_by_class (klass);
682
  
683 684 685 686
  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
687
  
688
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Home, 0,
689
                                "focus-home-or-end", 1,
690
				G_TYPE_BOOLEAN, TRUE);
691
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Home, 0,
692
                                "focus-home-or-end", 1,
693
				G_TYPE_BOOLEAN, TRUE);
694
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_End, 0,
695
                                "focus-home-or-end", 1,
696
				G_TYPE_BOOLEAN, FALSE);
697
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_End, 0,
698
                                "focus-home-or-end", 1,
699
				G_TYPE_BOOLEAN, FALSE);
700
  
701 702
  add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
  add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
703 704

  gtk_widget_class_set_css_name (widget_class, "toolbar");
705 706
}

707 708 709 710 711 712 713 714 715 716
static void
toolbar_tool_shell_iface_init (GtkToolShellIface *iface)
{
  iface->get_icon_size    = toolbar_get_icon_size;
  iface->get_orientation  = toolbar_get_orientation;
  iface->get_style        = toolbar_get_style;
  iface->get_relief_style = toolbar_get_relief_style;
  iface->rebuild_menu     = toolbar_rebuild_menu;
}

717
static void
718
gtk_toolbar_init (GtkToolbar *toolbar)
719
{
720
  GtkToolbarPrivate *priv;
721
  GtkWidget *widget;
722
  GtkCssNode *widget_node;
723

724
  widget = GTK_WIDGET (toolbar);
725
  toolbar->priv = gtk_toolbar_get_instance_private (toolbar);
726 727
  priv = toolbar->priv;

728 729
  gtk_widget_set_can_focus (widget, FALSE);
  gtk_widget_set_has_window (widget, FALSE);
730 731 732 733

  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
  priv->style = DEFAULT_TOOLBAR_STYLE;
  priv->icon_size = DEFAULT_ICON_SIZE;
734
  priv->animation = DEFAULT_ANIMATION_STATE;
735

736 737
  _gtk_orientable_set_style_classes (GTK_ORIENTABLE (toolbar));

738 739 740 741 742 743 744 745
  widget_node = gtk_widget_get_css_node (widget);
  priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
                                                     widget,
                                                     gtk_toolbar_measure,
                                                     gtk_toolbar_allocate,
                                                     gtk_toolbar_render,
                                                     NULL, NULL);

746
  priv->arrow_button = gtk_toggle_button_new ();
747
  g_signal_connect (priv->arrow_button, "button-press-event",
748 749 750 751 752
		    G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
  g_signal_connect (priv->arrow_button, "clicked",
		    G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
  gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
			 get_button_relief (toolbar));
753

754
  gtk_widget_set_focus_on_click (priv->arrow_button, FALSE);
755

756
  priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
757
  gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
758 759 760
  gtk_widget_show (priv->arrow);
  gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
  
761
  gtk_widget_set_parent (priv->arrow_button, widget);
762
  
763 764
  /* which child position a drop will occur at */
  priv->menu = NULL;
765
  priv->show_arrow = TRUE;
766
  priv->settings = NULL;
767
  
768 769
  priv->max_homogeneous_pixels = -1;
  
770
  priv->timer = g_timer_new ();
771 772
}

773
static void
774 775
gtk_toolbar_set_property (GObject      *object,
			  guint         prop_id,
776 777
			  const GValue *value,
			  GParamSpec   *pspec)
778 779
{
  GtkToolbar *toolbar = GTK_TOOLBAR (object);
780
  GtkToolbarPrivate *priv = toolbar->priv;
781

782
  switch (prop_id)
783
    {
784
    case PROP_ORIENTATION:
785 786
      g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0,
                     g_value_get_enum (value));
787
      break;
788 789
    case PROP_TOOLBAR_STYLE:
      gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
790
      break;
791 792 793
    case PROP_SHOW_ARROW:
      gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
      break;
794
    case PROP_ICON_SIZE:
795
      gtk_toolbar_set_icon_size (toolbar, g_value_get_enum (value));
796 797 798
      break;
    case PROP_ICON_SIZE_SET:
      if (g_value_get_boolean (value))
799
	priv->icon_size_set = TRUE;
800 801 802
      else
	gtk_toolbar_unset_icon_size (toolbar);
      break;
803 804 805
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
806 807 808 809
    }
}

static void
810 811 812 813
gtk_toolbar_get_property (GObject    *object,
			  guint       prop_id,
			  GValue     *value,
			  GParamSpec *pspec)
814 815
{
  GtkToolbar *toolbar = GTK_TOOLBAR (object);
816
  GtkToolbarPrivate *priv = toolbar->priv;
817

818
  switch (prop_id)
819
    {
820
    case PROP_ORIENTATION:
821
      g_value_set_enum (value, priv->orientation);
822
      break;
823
    case PROP_TOOLBAR_STYLE:
824
      g_value_set_enum (value, priv->style);
825
      break;
826 827 828
    case PROP_SHOW_ARROW:
      g_value_set_boolean (value, priv->show_arrow);
      break;
829
    case PROP_ICON_SIZE:
830
      g_value_set_enum (value, gtk_toolbar_get_icon_size (toolbar));
831 832
      break;
    case PROP_ICON_SIZE_SET:
833
      g_value_set_boolean (value, priv->icon_size_set);
834
      break;
835
    default:
836
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
837 838 839 840
      break;
    }
}

841 842
static void
gtk_toolbar_map (GtkWidget *widget)
843
{
844
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
845
  GtkToolbarPrivate *priv = toolbar->priv;
846

Matthias Clasen's avatar
Matthias Clasen committed
847
  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->map (widget);
848

849 850
  if (priv->event_window)
    gdk_window_show_unraised (priv->event_window);
851 852 853
}

static void
854
gtk_toolbar_unmap (GtkWidget *widget)
855
{
856
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
857
  GtkToolbarPrivate *priv = toolbar->priv;
858

859 860
  if (priv->event_window)
    gdk_window_hide (priv->event_window);
861
  
Matthias Clasen's avatar
Matthias Clasen committed
862
  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unmap (widget);
863 864
}

865 866 867
static void
gtk_toolbar_realize (GtkWidget *widget)
{
868
  GtkAllocation allocation;
869
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
870
  GtkToolbarPrivate *priv = toolbar->priv;
871
  GdkWindow *window;
872 873
  GdkWindowAttr attributes;
  gint attributes_mask;
874

875
  gtk_widget_set_realized (widget, TRUE);
876

877
  gtk_widget_get_allocation (widget, &allocation);
878

879 880
  attributes.wclass = GDK_INPUT_ONLY;
  attributes.window_type = GDK_WINDOW_CHILD;
881 882 883 884
  attributes.x = allocation.x;
  attributes.y = allocation.y;
  attributes.width = allocation.width;
  attributes.height = allocation.height;
885
  attributes.event_mask = gtk_widget_get_events (widget);
886
  attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
887
			    GDK_BUTTON_RELEASE_MASK |
888
			    GDK_POINTER_MOTION_MASK |
889 890
			    GDK_ENTER_NOTIFY_MASK |
			    GDK_LEAVE_NOTIFY_MASK);
891

892
  attributes_mask = GDK_WA_X | GDK_WA_Y;
893

894 895 896 897
  window = gtk_widget_get_parent_window (widget);
  gtk_widget_set_window (widget, window);
  g_object_ref (window);

898 899
  priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
				       &attributes, attributes_mask);
900
  gtk_widget_register_window (widget, priv->event_window);
901 902 903 904 905
}

static void
gtk_toolbar_unrealize (GtkWidget *widget)
{
906
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
907
  GtkToolbarPrivate *priv = toolbar->priv;
908

909 910
  if (priv->event_window)
    {
911
      gtk_widget_unregister_window (widget, priv->event_window);
912 913 914
      gdk_window_destroy (priv->event_window);
      priv->event_window = NULL;
    }
915 916

  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unrealize (widget);
917 918
}

919 920 921 922 923 924 925 926 927 928
static gboolean
gtk_toolbar_render (GtkCssGadget *gadget,
                    cairo_t      *cr,
                    int           x,
                    int           y,
                    int           width,
                    int           height,
                    gpointer      data)
{
  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
929
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
930
  GtkToolbarPrivate *priv = toolbar->priv;
931
  GList *list;
932

933
  for (list = priv->content; list != NULL; list = list->next)
934
    {
935
      ToolbarContent *content = list->data;
936
      
937
      toolbar_content_draw (content, GTK_CONTAINER (widget), cr);
938
    }
939
  
940 941 942
  gtk_container_propagate_draw (GTK_CONTAINER (widget),
				priv->arrow_button,
				cr);
943

944
  return FALSE;
945 946
}

947 948 949
static gint
gtk_toolbar_draw (GtkWidget *widget,
                  cairo_t   *cr)
950
{
951 952
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
  GtkToolbarPrivate *priv = toolbar->priv;
953

954
  gtk_css_gadget_draw (priv->gadget, cr);
955

956
  return FALSE;
957 958
}

959
static void
960 961 962 963 964 965 966 967 968 969
gtk_toolbar_measure (GtkCssGadget   *gadget,
                     GtkOrientation  orientation,
                     int             for_size,
                     int            *minimum,
                     int            *natural,
                     int            *minimum_baseline,
                     int            *natural_baseline,
                     gpointer        data)
{
  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
970
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
971
  GtkToolbarPrivate *priv = toolbar->priv;
972 973 974 975 976 977 978
  GList *list;
  gint max_child_height;
  gint max_child_width;
  gint max_homogeneous_child_width;
  gint max_homogeneous_child_height;
  gint homogeneous_size;
  gint pack_front_size;
979 980
  GtkRequisition arrow_requisition, min_requisition, nat_requisition;

981 982 983 984
  max_homogeneous_child_width = 0;
  max_homogeneous_child_height = 0;
  max_child_width = 0;
  max_child_height = 0;
985
  for (list = priv->content; list != NULL; list = list->next)
986
    {
987
      GtkRequisition requisition;
988
      ToolbarContent *content = list->data;
989
      
990
      if (!toolbar_content_visible (content, toolbar))
991
	continue;
992
      
993
      toolbar_content_size_request (content, toolbar, &requisition);
994

995 996
      max_child_width = MAX (max_child_width, requisition.width);
      max_child_height = MAX (max_child_height, requisition.height);
997
      
998
      if (toolbar_content_is_homogeneous (content, toolbar))
999 1000 1001
	{
	  max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
	  max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
1002
	}
1003
    }
1004
  
1005
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1006
    homogeneous_size = max_homogeneous_child_width;
1007
  else
1008 1009 1010
    homogeneous_size = max_homogeneous_child_height;
  
  pack_front_size = 0;
1011
  for (list = priv->content; list != NULL; list = list->next)
1012
    {
1013
      ToolbarContent *content = list->data;
1014
      guint size;
1015
      
1016
      if (!toolbar_content_visible (content, toolbar))
1017
	continue;
1018

1019
      if (toolbar_content_is_homogeneous (content, toolbar))
1020 1021 1022 1023 1024 1025 1026
	{
	  size = homogeneous_size;
	}
      else
	{
	  GtkRequisition requisition;
	  
1027
	  toolbar_content_size_request (content, toolbar, &requisition);
1028
	  
1029
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1030 1031 1032 1033
	    size = requisition.width;
	  else
	    size = requisition.height;
	}
1034

1035
      pack_front_size += size;
1036
    }
1037 1038 1039

  arrow_requisition.height = 0;
  arrow_requisition.width = 0;
1040
  
1041
  if (priv->show_arrow)
1042
    gtk_widget_get_preferred_size (priv->arrow_button,
1043
                                     &arrow_requisition, NULL);
1044
  
1045
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1046
    {
1047 1048
      nat_requisition.width = pack_front_size;
      nat_requisition.height = MAX (max_child_height, arrow_requisition.height);
1049

1050 1051
      min_requisition.width = priv->show_arrow ? arrow_requisition.width : nat_requisition.width;
      min_requisition.height = nat_requisition.height;
1052 1053 1054
    }
  else
    {
1055 1056
      nat_requisition.width = MAX (max_child_width, arrow_requisition.width);
      nat_requisition.height = pack_front_size;
1057

1058 1059
      min_requisition.width = nat_requisition.width;
      min_requisition.height = priv->show_arrow ? arrow_requisition.height : nat_requisition.height;
1060
    }
1061

1062 1063
  priv->button_maxw = max_homogeneous_child_width;
  priv->button_maxh = max_homogeneous_child_height;
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074

  if (orientation == GTK_ORIENTATION_HORIZONTAL)
    {
      *minimum = min_requisition.width;
      *natural = nat_requisition.width;
    }
  else
    {
      *minimum = min_requisition.height;
      *natural = nat_requisition.height;
    }
1075 1076
}

1077 1078 1079 1080 1081
static void
gtk_toolbar_get_preferred_width (GtkWidget *widget,
                                 gint      *minimum,
                                 gint      *natural)
{
1082 1083
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
  GtkToolbarPrivate *priv = toolbar->priv;
1084

1085 1086 1087 1088 1089
  gtk_css_gadget_get_preferred_size (priv->gadget,
                                     GTK_ORIENTATION_HORIZONTAL,
                                     -1,
                                     minimum, natural,
                                     NULL, NULL);
1090 1091 1092 1093 1094 1095 1096
}

static void
gtk_toolbar_get_preferred_height (GtkWidget *widget,
                                  gint      *minimum,
                                  gint      *natural)
{
1097 1098
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
  GtkToolbarPrivate *priv = toolbar->priv;
1099

1100 1101 1102 1103 1104
  gtk_css_gadget_get_preferred_size (priv->gadget,
                                     GTK_ORIENTATION_VERTICAL,
                                     -1,
                                     minimum, natural,
                                     NULL, NULL);
1105 1106
}

1107
static gint
1108 1109 1110 1111
position (GtkToolbar *toolbar,
          gint        from,
          gint        to,
          gdouble     elapsed)
1112
{
1113
  GtkToolbarPrivate *priv = toolbar->priv;
1114 1115
  gint n_pixels;

1116
  if (!priv->animation)
1117 1118
    return to;

1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
  if (elapsed <= ACCEL_THRESHOLD)
    {
      n_pixels = SLIDE_SPEED * elapsed;
    }
  else
    {
      /* The formula is a second degree polynomial in
       * @elapsed that has the line SLIDE_SPEED * @elapsed
       * as tangent for @elapsed == ACCEL_THRESHOLD.
       * This makes @n_pixels a smooth function of elapsed time.
       */
      n_pixels = (SLIDE_SPEED / ACCEL_THRESHOLD) * elapsed * elapsed -
	SLIDE_SPEED * elapsed + SLIDE_SPEED * ACCEL_THRESHOLD;
    }
1133

1134
  if (to > from)
1135
    return MIN (from + n_pixels, to);
1136
  else
1137
    return MAX (from - n_pixels, to);
1138 1139 1140 1141 1142 1143 1144 1145
}

static void
compute_intermediate_allocation (GtkToolbar          *toolbar,
				 const GtkAllocation *start,
				 const GtkAllocation *goal,
				 GtkAllocation       *intermediate)
{
1146
  GtkToolbarPrivate *priv = toolbar->priv;
1147
  gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1148 1149 1150 1151 1152 1153 1154 1155 1156

  intermediate->x      = position (toolbar, start->x, goal->x, elapsed);
  intermediate->y      = position (toolbar, start->y, goal->y, elapsed);
  intermediate->width  = position (toolbar, start->x + start->width,
                                   goal->x + goal->width,
                                   elapsed) - intermediate->x;
  intermediate->height = position (toolbar, start->y + start->height,
                                   goal->y + goal->height,
                                   elapsed) - intermediate->y;
1157 1158
}

1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
static void
fixup_allocation_for_rtl (gint           total_size,
			  GtkAllocation *allocation)
{
  allocation->x += (total_size - (2 * allocation->x + allocation->width));
}

static void
fixup_allocation_for_vertical (GtkAllocation *allocation)
{
  gint tmp;
1170
  
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
  tmp = allocation->x;
  allocation->x = allocation->y;
  allocation->y = tmp;
  
  tmp = allocation->width;
  allocation->width = allocation->height;
  allocation->height = tmp;
}

static gint
1181 1182
get_item_size (GtkToolbar     *toolbar,
	       ToolbarContent *content)
1183
{
1184
  GtkToolbarPrivate *priv = toolbar->priv;
1185
  GtkRequisition requisition;
1186
  
1187
  toolbar_content_size_request (content, toolbar, &requisition);
Javier Jardón's avatar