gtktoolbar.c 106 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 "gtkcssnodeprivate.h"
43
#include "gtkimage.h"
44
#include "gtkintl.h"
45
#include "gtklabel.h"
46
#include "gtkmain.h"
47 48 49
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkorientable.h"
50
#include "gtkorientableprivate.h"
51
#include "gtkprivate.h"
52 53
#include "gtkradiobutton.h"
#include "gtkradiotoolbutton.h"
54
#include "gtkrender.h"
55 56 57
#include "gtkseparatormenuitem.h"
#include "gtkseparatortoolitem.h"
#include "gtktoolshell.h"
58
#include "gtktypebuiltins.h"
59
#include "gtkwidgetpath.h"
60
#include "gtkwidgetprivate.h"
61
#include "gtkwindowprivate.h"
62

63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
/**
 * 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
79
 * “expand” is #TRUE and the property #GtkSeparatorToolItem:draw is set to
80 81 82 83
 * #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.
84 85 86 87
 *
 * # CSS nodes
 *
 * GtkToolbar has a single CSS node with name toolbar.
88 89 90
 */


91 92
typedef struct _ToolbarContent ToolbarContent;

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

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

103 104
#define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
				    * in the homogeneous game. In units of
105 106
				    * pango_font_get_estimated_char_width().
				    */
107 108
#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 */
109

110

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

  GtkIconSize      icon_size;
117
  GtkToolbarStyle  style;
118

119 120 121 122 123 124 125 126 127 128
  GtkToolItem     *highlight_tool_item;
  GtkWidget       *arrow;
  GtkWidget       *arrow_button;

  GdkWindow       *event_window;

  GList           *content;

  GTimer          *timer;

129 130
  gulong           settings_connection;

131 132 133 134 135 136
  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;

137
  GtkOrientation   orientation;
138 139 140 141 142 143 144 145 146 147

  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;
};

148
/* Properties */
149
enum {
150 151
  PROP_0,
  PROP_ORIENTATION,
152
  PROP_TOOLBAR_STYLE,
153
  PROP_SHOW_ARROW,
154 155 156
  PROP_TOOLTIPS,
  PROP_ICON_SIZE,
  PROP_ICON_SIZE_SET
157 158
};

159
/* Child properties */
160 161 162
enum {
  CHILD_PROP_0,
  CHILD_PROP_EXPAND,
163
  CHILD_PROP_HOMOGENEOUS
164 165
};

166
/* Signals */
167
enum {
168 169
  ORIENTATION_CHANGED,
  STYLE_CHANGED,
170
  POPUP_CONTEXT_MENU,
171
  FOCUS_HOME_OR_END,
172
  LAST_SIGNAL
173 174
};

175 176 177 178
typedef enum {
  NOT_ALLOCATED,
  NORMAL,
  HIDDEN,
179
  OVERFLOWN
180
} ItemState;
Matthias Clasen's avatar
Matthias Clasen committed
181

182

183 184 185 186 187 188 189 190
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);
191 192
static gint       gtk_toolbar_draw                 (GtkWidget           *widget,
                                                    cairo_t             *cr);
193 194
static void       gtk_toolbar_realize              (GtkWidget           *widget);
static void       gtk_toolbar_unrealize            (GtkWidget           *widget);
195 196 197 198 199 200 201
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);

202 203
static void       gtk_toolbar_size_allocate        (GtkWidget           *widget,
						    GtkAllocation       *allocation);
204
static void       gtk_toolbar_style_updated        (GtkWidget           *widget);
205 206
static gboolean   gtk_toolbar_focus                (GtkWidget           *widget,
						    GtkDirectionType     dir);
207 208
static void       gtk_toolbar_move_focus           (GtkWidget           *widget,
						    GtkDirectionType     dir);
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
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);
224
static void       gtk_toolbar_dispose              (GObject             *object);
225 226 227 228 229 230 231 232 233 234
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);
235

236 237
static void       gtk_toolbar_direction_changed    (GtkWidget           *widget,
                                                    GtkTextDirection     previous_direction);
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
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);
254 255

static GtkReliefStyle       get_button_relief    (GtkToolbar *toolbar);
256
static gint                 get_max_child_expand (GtkToolbar *toolbar);
257

258 259 260 261 262 263 264 265
/* 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);
266
static void            toolbar_content_draw                 (ToolbarContent      *content,
267
							     GtkContainer        *container,
268
                                                             cairo_t             *cr);
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
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);
307
static gboolean        toolbar_content_has_proxy_menu_item  (ToolbarContent	 *content);
308 309
static gboolean        toolbar_content_is_separator         (ToolbarContent      *content);
static void            toolbar_content_show_all             (ToolbarContent      *content);
310 311
static void	       toolbar_content_set_expand	    (ToolbarContent      *content,
							     gboolean		  expand);
312

313 314 315 316 317 318 319
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);

320

321
G_DEFINE_TYPE_WITH_CODE (GtkToolbar, gtk_toolbar, GTK_TYPE_CONTAINER,
322
                         G_ADD_PRIVATE (GtkToolbar)
323 324 325 326 327 328 329
                         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 };

330 331 332 333 334 335

static void
add_arrow_bindings (GtkBindingSet   *binding_set,
		    guint            keysym,
		    GtkDirectionType dir)
{
336
  guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
337 338
  
  gtk_binding_entry_add_signal (binding_set, keysym, 0,
339
                                "move-focus", 1,
340 341
                                GTK_TYPE_DIRECTION_TYPE, dir);
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
342
                                "move-focus", 1,
343 344
                                GTK_TYPE_DIRECTION_TYPE, dir);
}
345

346 347 348 349 350 351
static void
add_ctrl_tab_bindings (GtkBindingSet    *binding_set,
		       GdkModifierType   modifiers,
		       GtkDirectionType  direction)
{
  gtk_binding_entry_add_signal (binding_set,
352
				GDK_KEY_Tab, GDK_CONTROL_MASK | modifiers,
353
				"move-focus", 1,
354 355
				GTK_TYPE_DIRECTION_TYPE, direction);
  gtk_binding_entry_add_signal (binding_set,
356
				GDK_KEY_KP_Tab, GDK_CONTROL_MASK | modifiers,
357
				"move-focus", 1,
358
				GTK_TYPE_DIRECTION_TYPE, direction);
359 360 361
}

static void
362
gtk_toolbar_class_init (GtkToolbarClass *klass)
363
{
364
  GObjectClass *gobject_class;
365 366
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;
367
  GtkBindingSet *binding_set;
368
  
369 370 371 372
  gobject_class = (GObjectClass *)klass;
  widget_class = (GtkWidgetClass *)klass;
  container_class = (GtkContainerClass *)klass;
  
373 374
  gobject_class->set_property = gtk_toolbar_set_property;
  gobject_class->get_property = gtk_toolbar_get_property;
375
  gobject_class->finalize = gtk_toolbar_finalize;
376
  gobject_class->dispose = gtk_toolbar_dispose;
377
  
378
  widget_class->button_press_event = gtk_toolbar_button_press;
379
  widget_class->draw = gtk_toolbar_draw;
380 381
  widget_class->get_preferred_width = gtk_toolbar_get_preferred_width;
  widget_class->get_preferred_height = gtk_toolbar_get_preferred_height;
382
  widget_class->size_allocate = gtk_toolbar_size_allocate;
383
  widget_class->style_updated = gtk_toolbar_style_updated;
384
  widget_class->focus = gtk_toolbar_focus;
385

386 387
  gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_BAR);

388
  /* need to override the base class function via override_class_handler,
389 390
   * because the signal slot is not available in GtkWidgetClass
   */
391
  g_signal_override_class_handler ("move-focus",
392
                                   GTK_TYPE_TOOLBAR,
393
                                   G_CALLBACK (gtk_toolbar_move_focus));
394

395
  widget_class->screen_changed = gtk_toolbar_screen_changed;
396 397 398 399
  widget_class->realize = gtk_toolbar_realize;
  widget_class->unrealize = gtk_toolbar_unrealize;
  widget_class->map = gtk_toolbar_map;
  widget_class->unmap = gtk_toolbar_unmap;
400
  widget_class->popup_menu = gtk_toolbar_popup_menu;
401
  widget_class->show_all = gtk_toolbar_show_all;
402
  widget_class->direction_changed = gtk_toolbar_direction_changed;
Havoc Pennington's avatar
Havoc Pennington committed
403
  
404
  container_class->add    = gtk_toolbar_add;
405
  container_class->remove = gtk_toolbar_remove;
406
  container_class->forall = gtk_toolbar_forall;
407 408 409
  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;
410

411
  klass->orientation_changed = gtk_toolbar_orientation_changed;
412
  klass->style_changed = gtk_toolbar_real_style_changed;
413
  
414 415 416 417 418 419 420
  /**
   * 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.
   */
421
  toolbar_signals[ORIENTATION_CHANGED] =
422
    g_signal_new (I_("orientation-changed"),
423
		  G_OBJECT_CLASS_TYPE (klass),
Manish Singh's avatar
Manish Singh committed
424 425 426
		  G_SIGNAL_RUN_FIRST,
		  G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
		  NULL, NULL,
427
		  g_cclosure_marshal_VOID__ENUM,
Manish Singh's avatar
Manish Singh committed
428 429
		  G_TYPE_NONE, 1,
		  GTK_TYPE_ORIENTATION);
430 431 432 433 434 435 436
  /**
   * 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. 
   */
437
  toolbar_signals[STYLE_CHANGED] =
438
    g_signal_new (I_("style-changed"),
439
		  G_OBJECT_CLASS_TYPE (klass),
Manish Singh's avatar
Manish Singh committed
440 441 442
		  G_SIGNAL_RUN_FIRST,
		  G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
		  NULL, NULL,
443
		  g_cclosure_marshal_VOID__ENUM,
Manish Singh's avatar
Manish Singh committed
444 445
		  G_TYPE_NONE, 1,
		  GTK_TYPE_TOOLBAR_STYLE);
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
  /**
   * 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.
   *
462
   * Returns: return %TRUE if the signal was handled, %FALSE if not
463
   */
464
  toolbar_signals[POPUP_CONTEXT_MENU] =
465
    g_signal_new (I_("popup-context-menu"),
466
		  G_OBJECT_CLASS_TYPE (klass),
467
		  G_SIGNAL_RUN_LAST,
468
		  G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
469 470 471 472 473
		  _gtk_boolean_handled_accumulator, NULL,
		  _gtk_marshal_BOOLEAN__INT_INT_INT,
		  G_TYPE_BOOLEAN, 3,
		  G_TYPE_INT, G_TYPE_INT,
		  G_TYPE_INT);
474

475 476 477 478 479 480 481 482
  /**
   * 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
   *
483
   * Returns: %TRUE if the signal was handled, %FALSE if not
484
   */
485
  toolbar_signals[FOCUS_HOME_OR_END] =
486
    g_signal_new_class_handler (I_("focus-home-or-end"),
487 488 489 490 491 492 493 494
                                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);

495
  /* properties */
496 497 498 499
  g_object_class_override_property (gobject_class,
                                    PROP_ORIENTATION,
                                    "orientation");

500 501
  g_object_class_install_property (gobject_class,
				   PROP_TOOLBAR_STYLE,
502
				   g_param_spec_enum ("toolbar-style",
503 504
 						      P_("Toolbar Style"),
 						      P_("How to draw the toolbar"),
505
 						      GTK_TYPE_TOOLBAR_STYLE,
506
 						      DEFAULT_TOOLBAR_STYLE,
507
 						      GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
508 509
  g_object_class_install_property (gobject_class,
				   PROP_SHOW_ARROW,
510
				   g_param_spec_boolean ("show-arrow",
511 512
							 P_("Show Arrow"),
							 P_("If an arrow should be shown if the toolbar doesn't fit"),
513
							 TRUE,
514
							 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530

  /**
   * 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,
531 532 533 534 535
				   g_param_spec_enum ("icon-size",
                                                      P_("Icon size"),
                                                      P_("Size of icons in this toolbar"),
                                                      GTK_TYPE_ICON_SIZE,
                                                      DEFAULT_ICON_SIZE,
536
                                                      GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552

  /**
   * 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));  

553 554 555 556
  /* child properties */
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_EXPAND,
					      g_param_spec_boolean ("expand", 
557 558
								    P_("Expand"), 
								    P_("Whether the item should receive extra space when the toolbar grows"),
559
								    FALSE,
560
								    GTK_PARAM_READWRITE));
561
  
562 563 564
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_HOMOGENEOUS,
					      g_param_spec_boolean ("homogeneous", 
565 566
								    P_("Homogeneous"), 
								    P_("Whether the item should be the same size as other homogeneous items"),
567
								    FALSE,
568
								    GTK_PARAM_READWRITE));
569
  
570
  /* style properties */
Havoc Pennington's avatar
Havoc Pennington committed
571
  gtk_widget_class_install_style_property (widget_class,
572
					   g_param_spec_int ("space-size",
573 574
							     P_("Spacer size"),
							     P_("Size of spacers"),
Havoc Pennington's avatar
Havoc Pennington committed
575 576 577
							     0,
							     G_MAXINT,
                                                             DEFAULT_SPACE_SIZE,
578
							     GTK_PARAM_READABLE));
579
  
580 581 582 583 584 585 586 587 588
  /**
   * 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.
   */
589
  gtk_widget_class_install_style_property (widget_class,
590
					   g_param_spec_int ("internal-padding",
591 592
							     P_("Internal padding"),
							     P_("Amount of border space between the toolbar shadow and the buttons"),
593 594
							     0,
							     G_MAXINT,
595
                                                             0,
596
                                                             GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
597 598 599

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("max-child-expand",
600 601
                                                             P_("Maximum child expand"),
                                                             P_("Maximum amount of space an expandable item will be given"),
602 603 604 605 606
                                                             0,
                                                             G_MAXINT,
                                                             G_MAXINT,
                                                             GTK_PARAM_READABLE));

Havoc Pennington's avatar
Havoc Pennington committed
607
  gtk_widget_class_install_style_property (widget_class,
608
					   g_param_spec_enum ("space-style",
609 610
							      P_("Space style"),
							      P_("Whether spacers are vertical lines or just blank"),
Havoc Pennington's avatar
Havoc Pennington committed
611 612
                                                              GTK_TYPE_TOOLBAR_SPACE_STYLE,
                                                              DEFAULT_SPACE_STYLE,
613
                                                              GTK_PARAM_READABLE));
614
  
Havoc Pennington's avatar
Havoc Pennington committed
615
  gtk_widget_class_install_style_property (widget_class,
616
					   g_param_spec_enum ("button-relief",
617 618
							      P_("Button relief"),
							      P_("Type of bevel around toolbar buttons"),
Havoc Pennington's avatar
Havoc Pennington committed
619
                                                              GTK_TYPE_RELIEF_STYLE,
620
                                                              GTK_RELIEF_NONE,
621
                                                              GTK_PARAM_READABLE));
622 623 624 625 626 627 628 629 630
  /**
   * 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.
   */
631
  gtk_widget_class_install_style_property (widget_class,
632
                                           g_param_spec_enum ("shadow-type",
633 634
                                                              P_("Shadow type"),
                                                              P_("Style of bevel around the toolbar"),
635 636
                                                              GTK_TYPE_SHADOW_TYPE,
                                                              GTK_SHADOW_OUT,
637
                                                              GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
638

639
  binding_set = gtk_binding_set_by_class (klass);
640
  
641 642 643 644
  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);
645
  
646
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Home, 0,
647
                                "focus-home-or-end", 1,
648
				G_TYPE_BOOLEAN, TRUE);
649
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Home, 0,
650
                                "focus-home-or-end", 1,
651
				G_TYPE_BOOLEAN, TRUE);
652
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_End, 0,
653
                                "focus-home-or-end", 1,
654
				G_TYPE_BOOLEAN, FALSE);
655
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_End, 0,
656
                                "focus-home-or-end", 1,
657
				G_TYPE_BOOLEAN, FALSE);
658
  
659 660
  add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
  add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
661 662

  gtk_widget_class_set_css_name (widget_class, "toolbar");
663 664
}

665 666 667 668 669 670 671 672 673 674
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;
}

675
static void
676
gtk_toolbar_init (GtkToolbar *toolbar)
677
{
678
  GtkToolbarPrivate *priv;
679

680
  toolbar->priv = gtk_toolbar_get_instance_private (toolbar);
681 682
  priv = toolbar->priv;

683
  gtk_widget_set_can_focus (GTK_WIDGET (toolbar), FALSE);
684
  gtk_widget_set_has_window (GTK_WIDGET (toolbar), FALSE);
685 686 687 688

  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
  priv->style = DEFAULT_TOOLBAR_STYLE;
  priv->icon_size = DEFAULT_ICON_SIZE;
689
  priv->animation = DEFAULT_ANIMATION_STATE;
690

691 692
  _gtk_orientable_set_style_classes (GTK_ORIENTABLE (toolbar));

693
  priv->arrow_button = gtk_toggle_button_new ();
694
  g_signal_connect (priv->arrow_button, "button-press-event",
695 696 697 698 699
		    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));
700

701
  gtk_widget_set_focus_on_click (priv->arrow_button, FALSE);
702

703
  priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
704
  gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
705 706 707 708
  gtk_widget_show (priv->arrow);
  gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
  
  gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
709
  
710 711
  /* which child position a drop will occur at */
  priv->menu = NULL;
712
  priv->show_arrow = TRUE;
713
  priv->settings = NULL;
714
  
715 716
  priv->max_homogeneous_pixels = -1;
  
717
  priv->timer = g_timer_new ();
718 719
}

720
static void
721 722
gtk_toolbar_set_property (GObject      *object,
			  guint         prop_id,
723 724
			  const GValue *value,
			  GParamSpec   *pspec)
725 726
{
  GtkToolbar *toolbar = GTK_TOOLBAR (object);
727
  GtkToolbarPrivate *priv = toolbar->priv;
728

729
  switch (prop_id)
730
    {
731
    case PROP_ORIENTATION:
732 733
      g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0,
                     g_value_get_enum (value));
734
      break;
735 736
    case PROP_TOOLBAR_STYLE:
      gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
737
      break;
738 739 740
    case PROP_SHOW_ARROW:
      gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
      break;
741
    case PROP_ICON_SIZE:
742
      gtk_toolbar_set_icon_size (toolbar, g_value_get_enum (value));
743 744 745
      break;
    case PROP_ICON_SIZE_SET:
      if (g_value_get_boolean (value))
746
	priv->icon_size_set = TRUE;
747 748 749
      else
	gtk_toolbar_unset_icon_size (toolbar);
      break;
750 751 752
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
753 754 755 756
    }
}

static void
757 758 759 760
gtk_toolbar_get_property (GObject    *object,
			  guint       prop_id,
			  GValue     *value,
			  GParamSpec *pspec)
761 762
{
  GtkToolbar *toolbar = GTK_TOOLBAR (object);
763
  GtkToolbarPrivate *priv = toolbar->priv;
764

765
  switch (prop_id)
766
    {
767
    case PROP_ORIENTATION:
768
      g_value_set_enum (value, priv->orientation);
769
      break;
770
    case PROP_TOOLBAR_STYLE:
771
      g_value_set_enum (value, priv->style);
772
      break;
773 774 775
    case PROP_SHOW_ARROW:
      g_value_set_boolean (value, priv->show_arrow);
      break;
776
    case PROP_ICON_SIZE:
777
      g_value_set_enum (value, gtk_toolbar_get_icon_size (toolbar));
778 779
      break;
    case PROP_ICON_SIZE_SET:
780
      g_value_set_boolean (value, priv->icon_size_set);
781
      break;
782
    default:
783
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
784 785 786 787
      break;
    }
}

788 789
static void
gtk_toolbar_map (GtkWidget *widget)
790
{
791
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
792
  GtkToolbarPrivate *priv = toolbar->priv;
793

Matthias Clasen's avatar
Matthias Clasen committed
794
  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->map (widget);
795

796 797
  if (priv->event_window)
    gdk_window_show_unraised (priv->event_window);
798 799 800
}

static void
801
gtk_toolbar_unmap (GtkWidget *widget)
802
{
803
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
804
  GtkToolbarPrivate *priv = toolbar->priv;
805

806 807
  if (priv->event_window)
    gdk_window_hide (priv->event_window);
808
  
Matthias Clasen's avatar
Matthias Clasen committed
809
  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unmap (widget);
810 811
}

812 813 814
static void
gtk_toolbar_realize (GtkWidget *widget)
{
815
  GtkAllocation allocation;
816
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
817
  GtkToolbarPrivate *priv = toolbar->priv;
818
  GdkWindow *window;
819 820
  GdkWindowAttr attributes;
  gint attributes_mask;
821 822
  guint border_width;

823
  gtk_widget_set_realized (widget, TRUE);
824

825
  gtk_widget_get_allocation (widget, &allocation);
826 827
  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));

828 829
  attributes.wclass = GDK_INPUT_ONLY;
  attributes.window_type = GDK_WINDOW_CHILD;
830 831 832 833
  attributes.x = allocation.x + border_width;
  attributes.y = allocation.y + border_width;
  attributes.width = allocation.width - border_width * 2;
  attributes.height = allocation.height - border_width * 2;
834
  attributes.event_mask = gtk_widget_get_events (widget);
835
  attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
836
			    GDK_BUTTON_RELEASE_MASK |
837
			    GDK_POINTER_MOTION_MASK |
838 839
			    GDK_ENTER_NOTIFY_MASK |
			    GDK_LEAVE_NOTIFY_MASK);
840

841
  attributes_mask = GDK_WA_X | GDK_WA_Y;
842

843 844 845 846
  window = gtk_widget_get_parent_window (widget);
  gtk_widget_set_window (widget, window);
  g_object_ref (window);

847 848
  priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
				       &attributes, attributes_mask);
849
  gtk_widget_register_window (widget, priv->event_window);
850 851 852 853 854
}

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

858 859
  if (priv->event_window)
    {
860
      gtk_widget_unregister_window (widget, priv->event_window);
861 862 863
      gdk_window_destroy (priv->event_window);
      priv->event_window = NULL;
    }
864 865

  GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unrealize (widget);
866 867
}

868
static gint
869 870
gtk_toolbar_draw (GtkWidget *widget,
                  cairo_t   *cr)
871
{
872
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
873
  GtkToolbarPrivate *priv = toolbar->priv;
874
  GtkStyleContext *context;
875
  GList *list;
876 877 878
  guint border_width;

  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
879 880 881 882 883 884 885 886
  context = gtk_widget_get_style_context (widget);

  gtk_render_background (context, cr, border_width, border_width,
                         gtk_widget_get_allocated_width (widget) - 2 * border_width,
                         gtk_widget_get_allocated_height (widget) - 2 * border_width);
  gtk_render_frame (context, cr, border_width, border_width,
                    gtk_widget_get_allocated_width (widget) - 2 * border_width,
                    gtk_widget_get_allocated_height (widget) - 2 * border_width);
887

888
  for (list = priv->content; list != NULL; list = list->next)
889
    {
890
      ToolbarContent *content = list->data;
891
      
892
      toolbar_content_draw (content, GTK_CONTAINER (widget), cr);
893
    }
894
  
895 896 897
  gtk_container_propagate_draw (GTK_CONTAINER (widget),
				priv->arrow_button,
				cr);
898

899
  return FALSE;
900 901
}

902 903 904 905 906 907 908 909 910 911 912 913 914 915
static void
get_widget_padding_and_border (GtkWidget *widget,
                               GtkBorder *padding)
{
  GtkStyleContext *context;
  GtkStateFlags state;
  GtkBorder tmp;

  context = gtk_widget_get_style_context (widget);
  state = gtk_style_context_get_state (context);

  gtk_style_context_get_padding (context, state, padding);
  gtk_style_context_get_border (context, state, &tmp);

916 917 918 919
  padding->top += tmp.top;
  padding->right += tmp.right;
  padding->bottom += tmp.bottom;
  padding->left += tmp.left;
920 921
}

922
static void
923
gtk_toolbar_size_request (GtkWidget      *widget,
924 925
			  GtkRequisition *min_requisition,
			  GtkRequisition *nat_requisition)
926
{
927
  GtkToolbar *toolbar = GTK_TOOLBAR (widget);
928
  GtkToolbarPrivate *priv = toolbar->priv;
929 930 931 932 933 934 935
  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;
936
  GtkBorder padding;
937
  guint border_width;
938
  gint extra_width, extra_height;
939
  GtkRequisition arrow_requisition;
940
  
941 942 943 944
  max_homogeneous_child_width = 0;
  max_homogeneous_child_height = 0;
  max_child_width = 0;
  max_child_height = 0;
945
  for (list = priv->content; list != NULL; list = list->next)
946
    {
947
      GtkRequisition requisition;
948
      ToolbarContent *content = list->data;
949
      
950
      if (!toolbar_content_visible (content, toolbar))
951
	continue;
952
      
953
      toolbar_content_size_request (content, toolbar, &requisition);
954

955 956
      max_child_width = MAX (max_child_width, requisition.width);
      max_child_height = MAX (max_child_height, requisition.height);
957
      
958
      if (toolbar_content_is_homogeneous (content, toolbar))
959 960 961
	{
	  max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
	  max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
962
	}
963
    }
964
  
965
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
966
    homogeneous_size = max_homogeneous_child_width;
967
  else
968 969 970
    homogeneous_size = max_homogeneous_child_height;
  
  pack_front_size = 0;
971
  for (list = priv->content; list != NULL; list = list->next)
972
    {
973
      ToolbarContent *content = list->data;
974
      guint size;
975
      
976
      if (!toolbar_content_visible (content, toolbar))
977
	continue;
978

979
      if (toolbar_content_is_homogeneous (content, toolbar))
980 981 982 983 984 985 986
	{
	  size = homogeneous_size;
	}
      else
	{
	  GtkRequisition requisition;
	  
987
	  toolbar_content_size_request (content, toolbar, &requisition);
988
	  
989
	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
990 991 992 993
	    size = requisition.width;
	  else
	    size = requisition.height;
	}
994

995
      pack_front_size += size;
996
    }
997 998 999

  arrow_requisition.height = 0;
  arrow_requisition.width = 0;
1000
  
1001
  if (priv->show_arrow)
1002
    gtk_widget_get_preferred_size (priv->arrow_button,
1003
                                     &arrow_requisition, NULL);
1004
  
1005
  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1006
    {
1007 1008 1009 1010 1011
      nat_requisition->width = pack_front_size;
      nat_requisition->height = MAX (max_child_height, arrow_requisition.height);

      min_requisition->width = priv->show_arrow ? arrow_requisition.width : nat_requisition->width;
      min_requisition->height = nat_requisition->height;
1012 1013 1014
    }
  else
    {
1015 1016 1017 1018 1019
      nat_requisition->height = pack_front_size;
      nat_requisition->width = MAX (max_child_width, arrow_requisition.width);

      min_requisition->height = priv->show_arrow ? arrow_requisition.height : nat_requisition->height;
      min_requisition->width = nat_requisition->width;
1020
    }
1021

1022
  /* Extra spacing */
1023
  border_width = gtk_container_get_border_width (GTK_CONTAINER (toolbar));
1024
  get_widget_padding_and_border (widget, &padding);
1025

1026 1027 1028 1029 1030 1031 1032 1033
  extra_width = 2 * border_width + padding.left + padding.right;
  extra_height = 2 * border_width + padding.top + padding.bottom;

  nat_requisition->width += extra_width;
  nat_requisition->height += extra_height;

  min_requisition->width += extra_width;
  min_requisition->height += extra_height;
1034
  
1035 1036
  priv->button_maxw = max_homogeneous_child_width;
  priv->button_maxh = max_homogeneous_child_height;
1037 1038
}

1039 1040 1041 1042 1043
static void
gtk_toolbar_get_preferred_width (GtkWidget *widget,
                                 gint      *minimum,
                                 gint      *natural)
{
1044
  GtkRequisition min_requisition, nat_requisition;
1045

1046
  gtk_toolbar_size_request (widget, &min_requisition, &nat_requisition);
1047

1048 1049
  *minimum = min_requisition.width;
  *natural = nat_requisition.width;
1050 1051 1052 1053 1054 1055 1056
}

static void
gtk_toolbar_get_preferred_height (GtkWidget *widget,
                                  gint      *minimum,
                                  gint      *natural)
{
1057
  GtkRequisition min_requisition, nat_requisition;
1058

1059
  gtk_toolbar_size_request (widget, &min_requisition, &nat_requisition);
1060

1061 1062
  *minimum = min_requisition.height;
  *natural = nat_requisition.height;
1063 1064
}

1065
static gint
1066 1067 1068 1069
position (GtkToolbar *toolbar,
          gint        from,
          gint        to,
          gdouble     elapsed)
1070
{
1071
  GtkToolbarPrivate *priv = toolbar->priv;
1072 1073
  gint n_pixels;

1074
  if (!priv->animation)
1075 1076
    return to;

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
  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;
    }
1091

1092
  if (to > from)
1093
    return MIN (from + n_pixels, to);
1094
  else
1095
    return MAX (from - n_pixels, to);
1096 1097 1098 1099 1100 1101 1102 1103
}

static void
compute_intermediate_allocation (GtkToolbar          *toolbar,
				 const GtkAllocation *start,
				 const GtkAllocation *goal,
				 GtkAllocation       *intermediate)
{
1104
  GtkToolbarPrivate *priv = toolbar->priv;
1105
  gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1106 1107 1108 1109 1110 1111 1112 1113 1114

  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;
1115 1116
}

1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
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;
1128
  
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
  tmp = allocation->x;
  allocation->x = allocation->y;
  allocation->y = tmp;
  
  tmp = allocation->width;
  allocation->width = allocation->height;
  allocation->height = tmp;
}

static gint
1139 1140
get_item_size (GtkToolbar     *toolbar,
	       ToolbarContent *content)
1141
{
1142
  GtkToolbarPrivate *priv = toolbar->priv;
1143
  GtkRequisition requisition;
1144
  
1145
  toolbar_content_size_request (content, toolbar, &requisition);
1146 1147

  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1148
    {
1149
      if (toolbar_content_is_homogeneous (content, toolbar))
1150
	return priv->button_maxw;
1151 1152 1153 1154 1155
      else
	return requisition.width;
    }
  else
    {
1156
      if (toolbar_content_is_homogeneous (content, toolbar))