15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/defaults.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/search.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_properties.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/elide_url.h"
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/omnibox/omnibox_view.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/view_ids.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h"
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h"
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/event_utils.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
48558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/url_constants.h"
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h"
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/metrics/metrics_service.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/page_navigator.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/browser/extension_registry.h"
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/extension.h"
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/extension_set.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_utils.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/page_transition_types.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/theme_provider.h"
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h"
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gfx/text_constants.h"
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/text_elider.h"
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/button_drag_utils.h"
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/views/controls/button/label_button.h"
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/views/controls/button/label_button_border.h"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/menu_button.h"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/drag_utils.h"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/metrics.h"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_constants.h"
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/tooltip_manager.h"
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/window/non_client_view.h"
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction;
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using bookmarks::BookmarkNodeData;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PageNavigator;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::Referrer;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::DropTargetEvent;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using views::CustomButton;
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using views::LabelButtonBorder;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::MenuButton;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::View;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Margins around the content.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDetachedTopMargin = 1;  // When attached, we use 0 and let the
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          // toolbar above serve as the margin.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBottomMargin = 2;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kLeftMargin = 1;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRightMargin = 1;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char BookmarkBarView::kViewClassName[] = "BookmarkBarView";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding between buttons.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kButtonPadding = 0;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Icon to display when one isn't found for the page.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static gfx::ImageSkia* kDefaultFavicon = NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Icon used for folders.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static gfx::ImageSkia* kFolderIcon = NULL;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Color of the drop indicator.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SkColor kDropIndicatorColor = SK_ColorBLACK;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width of the drop indicator.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDropIndicatorWidth = 2;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Distance between the bottom of the bar and the separator.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSeparatorMargin = 1;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width of the separator between the recently bookmarked button and the
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overflow indicator.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSeparatorWidth = 4;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Starting x-coordinate of the separator line within a separator.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSeparatorStartX = 2;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Left-padding for the instructional text.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kInstructionsPadding = 6;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tag for the 'Other bookmarks' button.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kOtherFolderButtonTag = 1;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tag for the 'Apps Shortcut' button.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kAppsShortcutButtonTag = 2;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Preferred padding between text and edge.
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static const int kButtonPaddingHorizontal = 6;
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static const int kButtonPaddingVertical = 4;
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Tag for the 'Managed bookmarks' button.
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static const int kManagedFolderButtonTag = 3;
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(OS_WIN)
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic const gfx::ElideBehavior kElideBehavior = gfx::FADE_TAIL;
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Windows fade eliding causes text to darken; see http://crbug.com/388084
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic const gfx::ElideBehavior kElideBehavior = gfx::ELIDE_TAIL;
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To enable/disable BookmarkBar animations during testing. In production
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// animations are enabled by default.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool animations_enabled = true;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// BookmarkButtonBase -----------------------------------------------
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Base class for buttons used on the bookmark bar.
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class BookmarkButtonBase : public views::LabelButton {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BookmarkButtonBase(views::ButtonListener* listener,
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const base::string16& title)
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : LabelButton(listener, title) {
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SetElideBehavior(kElideBehavior);
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    show_animation_.reset(new gfx::SlideAnimation(this));
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!animations_enabled) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // For some reason during testing the events generated by animating
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // throw off the test. So, don't animate while testing.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      show_animation_->Reset(1);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      show_animation_->Show();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE {
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return HitTestPoint(point) && CanProcessEventsWithinSubtree() ? this : NULL;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual scoped_ptr<LabelButtonBorder> CreateDefaultBorder() const OVERRIDE {
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<LabelButtonBorder> border = LabelButton::CreateDefaultBorder();
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    border->set_insets(gfx::Insets(kButtonPaddingVertical,
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   kButtonPaddingHorizontal,
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   kButtonPaddingVertical,
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   kButtonPaddingHorizontal));
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return border.Pass();
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual bool IsTriggerableEvent(const ui::Event& e) OVERRIDE {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return e.type() == ui::ET_GESTURE_TAP ||
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           e.type() == ui::ET_GESTURE_TAP_DOWN ||
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           event_utils::IsPossibleDispositionEvent(e);
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<gfx::SlideAnimation> show_animation_;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BookmarkButtonBase);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BookmarkButton -------------------------------------------------------------
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Buttons used for the bookmarks on the bookmark bar.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BookmarkButton : public BookmarkButtonBase {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The internal view class name.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kViewClassName[];
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkButton(views::ButtonListener* listener,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const GURL& url,
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 const base::string16& title,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 Profile* profile)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : BookmarkButtonBase(listener, title),
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_(url),
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        profile_(profile) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetTooltipText(const gfx::Point& p,
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              base::string16* tooltip) const OVERRIDE {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point location(p);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertPointToScreen(this, &location);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *tooltip = BookmarkBarView::CreateToolTipForURLAndTitle(
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        GetWidget(), location, url_, GetText(), profile_);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !tooltip->empty();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual const char* GetClassName() const OVERRIDE {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kViewClassName;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url_;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile_;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BookmarkButton);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char BookmarkButton::kViewClassName[] = "BookmarkButton";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ShortcutButton -------------------------------------------------------------
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Buttons used for the shortcuts on the bookmark bar.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ShortcutButton : public BookmarkButtonBase {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The internal view class name.
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const char kViewClassName[];
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShortcutButton(views::ButtonListener* listener,
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 const base::string16& title)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : BookmarkButtonBase(listener, title) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual const char* GetClassName() const OVERRIDE {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kViewClassName;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ShortcutButton);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char ShortcutButton::kViewClassName[] = "ShortcutButton";
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BookmarkFolderButton -------------------------------------------------------
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Buttons used for folders on the bookmark bar, including the 'other folders'
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// button.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkFolderButton : public views::MenuButton {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkFolderButton(views::ButtonListener* listener,
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       const base::string16& title,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       views::MenuButtonListener* menu_button_listener,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       bool show_menu_marker)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : MenuButton(listener, title, menu_button_listener, show_menu_marker) {
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SetElideBehavior(kElideBehavior);
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    show_animation_.reset(new gfx::SlideAnimation(this));
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!animations_enabled) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For some reason during testing the events generated by animating
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // throw off the test. So, don't animate while testing.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_animation_->Reset(1);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      show_animation_->Show();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetTooltipText(const gfx::Point& p,
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              base::string16* tooltip) const OVERRIDE {
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (label()->GetPreferredSize().width() > label()->size().width())
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *tooltip = GetText();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !tooltip->empty();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsTriggerableEvent(const ui::Event& e) OVERRIDE {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Left clicks and taps should show the menu contents and right clicks
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should show the context menu. They should not trigger the opening of
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // underlying urls.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (e.type() == ui::ET_GESTURE_TAP ||
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (e.IsMouseEvent() && (e.flags() &
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON))))
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (e.IsMouseEvent())
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ui::DispositionFromEventFlags(e.flags()) != CURRENT_TAB;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<gfx::SlideAnimation> show_animation_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BookmarkFolderButton);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OverFlowButton (chevron) --------------------------------------------------
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OverFlowButton : public views::MenuButton {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit OverFlowButton(BookmarkBarView* owner)
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : MenuButton(NULL, base::string16(), owner, false),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        owner_(owner) {}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMousePressed(const ui::MouseEvent& e) OVERRIDE {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owner_->StopThrobbing(true);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return views::MenuButton::OnMousePressed(e);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkBarView* owner_;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OverFlowButton);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecordAppLaunch(Profile* profile, GURL url) {
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const extensions::Extension* extension =
348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      extensions::ExtensionRegistry::Get(profile)
349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ->enabled_extensions().GetAppByURL(url);
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!extension)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
353558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CoreAppLauncherHandler::RecordAppLaunchType(
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension_misc::APP_LAUNCH_BOOKMARK_BAR,
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension->GetType());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DropLocation ---------------------------------------------------------------
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BookmarkBarView::DropLocation {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DropLocation()
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : index(-1),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        operation(ui::DragDropTypes::DRAG_NONE),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        on(false),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        button_type(DROP_BOOKMARK) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Equals(const DropLocation& other) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ((other.index == index) && (other.on == on) &&
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (other.button_type == button_type));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Index into the model the drop is over. This is relative to the root node.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Drop constants.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int operation;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true, the user is dropping on a folder.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool on;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Type of button.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DropButtonType button_type;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DropInfo -------------------------------------------------------------------
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tracks drops on the BookmarkBarView.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BookmarkBarView::DropInfo {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DropInfo()
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : valid(false),
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is_menu_showing(false),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x(0),
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        y(0) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the data is valid.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool valid;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If true, the menu is being shown.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_menu_showing;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Coordinates of the drag (in terms of the BookmarkBarView).
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DropData for the drop.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeData data;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DropLocation location;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ButtonSeparatorView  --------------------------------------------------------
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkBarView::ButtonSeparatorView : public views::View {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ButtonSeparatorView() {}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ButtonSeparatorView() {}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DetachableToolbarView::PaintVerticalDivider(
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        canvas, kSeparatorStartX, height(), 1,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DetachableToolbarView::kEdgeDividerColor,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DetachableToolbarView::kMiddleDividerColor,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We get the full height of the bookmark bar, so that the height returned
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // here doesn't matter.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Size(kSeparatorWidth, 1);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR);
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    state->role = ui::AX_ROLE_SPLITTER;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ButtonSeparatorView);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BookmarkBarView ------------------------------------------------------------
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int BookmarkBarView::kMaxButtonWidth = 150;
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int BookmarkBarView::kNewtabHorizontalPadding = 2;
451a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const int BookmarkBarView::kToolbarAttachedBookmarkBarOverlap = 3;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const gfx::ImageSkia& GetDefaultFavicon() {
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!kDefaultFavicon) {
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    kDefaultFavicon = rb->GetImageSkiaNamed(IDR_DEFAULT_FAVICON);
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return *kDefaultFavicon;
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const gfx::ImageSkia& GetFolderIcon() {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!kFolderIcon) {
463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    kFolderIcon = rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_FOLDER);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *kFolderIcon;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkBarView::BookmarkBarView(Browser* browser, BrowserView* browser_view)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : page_navigator_(NULL),
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      client_(NULL),
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmark_menu_(NULL),
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmark_drop_menu_(NULL),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_bookmarked_button_(NULL),
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      managed_bookmarks_button_(NULL),
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      apps_page_shortcut_(NULL),
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overflow_button_(NULL),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instructions_(NULL),
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks_separator_view_(NULL),
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(browser),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_view_(browser_view),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      infobar_visible_(false),
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throbbing_view_(NULL),
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmark_bar_state_(BookmarkBar::SHOW),
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      animating_detached_(false),
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      show_folder_method_factory_(this) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_id(VIEW_ID_BOOKMARK_BAR);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_animation_->Reset(1);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkBarView::~BookmarkBarView() {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->RemoveObserver(this);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible for the menu to outlive us, reset the observer to make sure
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it doesn't have a reference to us.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bookmark_menu_) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_menu_->set_observer(NULL);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_menu_->SetPageNavigator(NULL);
502424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bookmark_menu_->clear_bookmark_bar();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_menu_.get())
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_menu_->SetPageNavigator(NULL);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopShowFolderDropMenuTimer();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkBarView::DisableAnimationsForTesting(bool disabled) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  animations_enabled = !disabled;
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BookmarkBarView::AddObserver(BookmarkBarViewObserver* observer) {
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  observers_.AddObserver(observer);
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BookmarkBarView::RemoveObserver(BookmarkBarViewObserver* observer) {
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  observers_.RemoveObserver(observer);
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::SetPageNavigator(PageNavigator* navigator) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  page_navigator_ = navigator;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bookmark_menu_)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_menu_->SetPageNavigator(navigator);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_menu_.get())
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_menu_->SetPageNavigator(navigator);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::SetBookmarkBarState(
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkBar::State state,
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BookmarkBar::AnimateChangeType animate_type) {
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE &&
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      animations_enabled) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    animating_detached_ = (state == BookmarkBar::DETACHED ||
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bookmark_bar_state_ == BookmarkBar::DETACHED);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state == BookmarkBar::SHOW)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_animation_->Show();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_animation_->Hide();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_animation_->Reset(state == BookmarkBar::SHOW ? 1 : 0);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmark_bar_state_ = state;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint BookmarkBarView::GetFullyDetachedToolbarOverlap() const {
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!infobar_visible_ && browser_->window()->IsFullscreen()) {
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // There is no client edge to overlap when detached in fullscreen with no
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // infobars visible.
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return views::NonClientFrameView::kClientEdgeThickness;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::is_animating() {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_animation_->is_animating();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* BookmarkBarView::GetNodeForButtonAtModelIndex(
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& loc,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* model_start_index) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *model_start_index = 0;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loc.x() < 0 || loc.x() >= width() || loc.y() < 0 || loc.y() >= height())
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point adjusted_loc(GetMirroredXInView(loc.x()), loc.y());
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check the managed button first.
572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (managed_bookmarks_button_->visible() &&
573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      managed_bookmarks_button_->bounds().Contains(adjusted_loc)) {
574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return client_->managed_node();
575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Then check the bookmark buttons.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* child = child_at(i);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!child->visible())
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child->bounds().Contains(adjusted_loc))
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return model_->bookmark_bar_node()->GetChild(i);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Then the overflow button.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overflow_button_->visible() &&
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overflow_button_->bounds().Contains(adjusted_loc)) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *model_start_index = GetFirstHiddenNodeIndex();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return model_->bookmark_bar_node();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And finally the other folder.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (other_bookmarked_button_->visible() &&
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_bookmarked_button_->bounds().Contains(adjusted_loc)) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return model_->other_node();
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::MenuButton* BookmarkBarView::GetMenuButtonForNode(
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* node) {
604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (node == client_->managed_node())
605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return managed_bookmarks_button_;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node == model_->other_node())
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return other_bookmarked_button_;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node == model_->bookmark_bar_node())
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return overflow_button_;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = model_->bookmark_bar_node()->GetIndexOf(node);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index == -1 || !node->is_folder())
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<views::MenuButton*>(child_at(index));
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::GetAnchorPositionForButton(
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::MenuButton* button,
6185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    views::MenuAnchorPosition* anchor) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (button == other_bookmarked_button_ || button == overflow_button_)
6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *anchor = views::MENU_ANCHOR_TOPRIGHT;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *anchor = views::MENU_ANCHOR_TOPLEFT;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::MenuItemView* BookmarkBarView::GetMenu() {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bookmark_menu_ ? bookmark_menu_->menu() : NULL;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::MenuItemView* BookmarkBarView::GetContextMenu() {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bookmark_menu_ ? bookmark_menu_->context_menu() : NULL;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::MenuItemView* BookmarkBarView::GetDropMenu() {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bookmark_drop_menu_ ? bookmark_drop_menu_->menu() : NULL;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::StopThrobbing(bool immediate) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!throbbing_view_)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not immediate, cycle through 2 more complete cycles.
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  throbbing_view_->StartThrobbing(immediate ? 0 : 4);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  throbbing_view_ = NULL;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 BookmarkBarView::CreateToolTipForURLAndTitle(
6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const views::Widget* widget,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& screen_loc,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Profile* profile) {
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int max_width = views::TooltipManager::GetMaxWidth(
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      screen_loc.x(),
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      screen_loc.y(),
6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      widget->GetNativeView());
6574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::FontList tt_fonts = widget->GetTooltipManager()->GetFontList();
658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 result;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First the title.
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!title.empty()) {
662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 localized_title = title;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::i18n::AdjustStringForLocaleDirection(&localized_title);
66446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    result.append(gfx::ElideText(localized_title, tt_fonts, max_width,
66546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 gfx::ELIDE_TAIL));
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only show the URL if the url and title differ.
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (title != base::UTF8ToUTF16(url.spec())) {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.empty())
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.push_back('\n');
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to explicitly specify the directionality of the URL's text to
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // make sure it is treated as an LTR string when the context is RTL. For
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // example, the URL "http://www.yahoo.com/" appears as
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "/http://www.yahoo.com" when rendered, as is, in an RTL context since
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the Unicode BiDi algorithm puts certain characters on the left by
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // default.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string languages = profile->GetPrefs()->GetString(
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefs::kAcceptLanguages);
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 elided_url(ElideUrl(url, tt_fonts, max_width, languages));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elided_url = base::i18n::GetDisplayStringInLTRDirectionality(elided_url);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append(elided_url);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::IsDetached() const {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (bookmark_bar_state_ == BookmarkBar::DETACHED) ||
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (animating_detached_ && size_animation_->is_animating());
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double BookmarkBarView::GetAnimationValue() const {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return size_animation_->GetCurrentValue();
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkBarView::GetToolbarOverlap() const {
698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int attached_overlap = kToolbarAttachedBookmarkBarOverlap +
699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      views::NonClientFrameView::kClientEdgeThickness;
700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!IsDetached())
701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return attached_overlap;
702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int detached_overlap = GetFullyDetachedToolbarOverlap();
704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Do not animate the overlap when the infobar is above us (i.e. when we're
706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // detached), since drawing over the infobar looks weird.
707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (infobar_visible_)
708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return detached_overlap;
709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // When detached with no infobar, animate the overlap between the attached and
711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // detached states.
712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return detached_overlap + static_cast<int>(
713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (attached_overlap - detached_overlap) *
714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          size_animation_->GetCurrentValue());
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BookmarkBarView::GetPreferredSize() const {
718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::Size prefsize;
719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (IsDetached()) {
720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    prefsize.set_height(
721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        chrome::kBookmarkBarHeight +
722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        static_cast<int>(
723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            (chrome::kNTPBookmarkBarHeight - chrome::kBookmarkBarHeight) *
724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            (1 - size_animation_->GetCurrentValue())));
725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    prefsize.set_height(static_cast<int>(chrome::kBookmarkBarHeight *
727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         size_animation_->GetCurrentValue()));
728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return prefsize;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool BookmarkBarView::CanProcessEventsWithinSubtree() const {
73346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the bookmark bar is attached and the omnibox popup is open (on top of
73446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // the bar), prevent events from targeting the bookmark bar or any of its
73546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // descendants. This will prevent hovers/clicks just above the omnibox popup
73646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // from activating the top few pixels of items on the bookmark bar.
7377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!IsDetached() && browser_view_ &&
738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      browser_view_->GetLocationBar()->GetOmniboxView()->model()->
7397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          popup_model()->IsOpen()) {
7407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
7417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
74246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return true;
7437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BookmarkBarView::GetMinimumSize() const {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The minimum width of the bookmark bar should at least contain the overflow
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // button, by which one can access all the Bookmark Bar items, and the "Other
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bookmarks" folder, along with appropriate margins and button padding.
749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // It should also contain the Managed Bookmarks folder, if it's visible.
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = kLeftMargin;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int height = chrome::kBookmarkBarHeight;
753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (IsDetached()) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double current_state = 1 - size_animation_->GetCurrentValue();
755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    width += 2 * static_cast<int>(kNewtabHorizontalPadding * current_state);
756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    height += static_cast<int>(
75758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (chrome::kNTPBookmarkBarHeight - chrome::kBookmarkBarHeight) *
758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            current_state);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (managed_bookmarks_button_->visible()) {
762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size size = managed_bookmarks_button_->GetPreferredSize();
763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    width += size.width() + kButtonPadding;
764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (other_bookmarked_button_->visible()) {
766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size size = other_bookmarked_button_->GetPreferredSize();
767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    width += size.width() + kButtonPadding;
768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (overflow_button_->visible()) {
770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size size = overflow_button_->GetPreferredSize();
771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    width += size.width() + kButtonPadding;
772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (bookmarks_separator_view_->visible()) {
774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size size = bookmarks_separator_view_->GetPreferredSize();
775f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    width += size.width();
776f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (apps_page_shortcut_->visible()) {
778f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size size = apps_page_shortcut_->GetPreferredSize();
779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    width += size.width() + kButtonPadding;
780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return gfx::Size(width, height);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::Layout() {
786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  LayoutItems();
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
789a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void BookmarkBarView::ViewHierarchyChanged(
790a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const ViewHierarchyChangedDetails& details) {
791a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (details.is_add && details.child == this) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We may get inserted into a hierarchy with a profile - this typically
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // occurs when the bar's contents get populated fast enough that the
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buttons are created before the bar is attached to a frame.
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateColors();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (height() > 0) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We only layout while parented. When we become parented, if our bounds
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // haven't changed, OnBoundsChanged() won't get invoked and we won't
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // layout. Therefore we always force a layout when added.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Layout();
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BookmarkBarView::PaintChildren(gfx::Canvas* canvas,
807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    const views::CullSet& cull_set) {
808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  View::PaintChildren(canvas, cull_set);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_.get() && drop_info_->valid &&
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drop_info_->location.operation != 0 && drop_info_->location.index != -1 &&
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drop_info_->location.button_type != DROP_OVERFLOW &&
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !drop_info_->location.on) {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = drop_info_->location.index;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(index <= GetBookmarkButtonCount());
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x = 0;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int y = 0;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int h = height();
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index == GetBookmarkButtonCount()) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index == 0) {
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        x = kLeftMargin;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x = GetBookmarkButton(index - 1)->x() +
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetBookmarkButton(index - 1)->width();
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x = GetBookmarkButton(index)->x();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetBookmarkButtonCount() > 0 && GetBookmarkButton(0)->visible()) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y = GetBookmarkButton(0)->y();
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      h = GetBookmarkButton(0)->height();
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since the drop indicator is painted directly onto the canvas, we must
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // make sure it is painted in the right location if the locale is RTL.
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect indicator_bounds(x - kDropIndicatorWidth / 2,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               y,
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               kDropIndicatorWidth,
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               h);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    indicator_bounds.set_x(GetMirroredXForRect(indicator_bounds));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sky/glen): make me pretty!
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->FillRect(indicator_bounds, kDropIndicatorColor);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::GetDropFormats(
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int* formats,
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
850b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!model_ || !model_->loaded())
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *formats = ui::OSExchangeData::URL;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat());
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::AreDropTypesRequired() {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::CanDrop(const ui::OSExchangeData& data) {
862b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!model_ || !model_->loaded() ||
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !browser_->profile()->GetPrefs()->GetBoolean(
8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          bookmarks::prefs::kEditBookmarksEnabled))
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!drop_info_.get())
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drop_info_.reset(new DropInfo());
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only accept drops of 1 node, which is the case for all data dragged from
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bookmark bar and menus.
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return drop_info_->data.Read(data) && drop_info_->data.size() == 1;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::OnDragEntered(const DropTargetEvent& event) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkBarView::OnDragUpdated(const DropTargetEvent& event) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!drop_info_.get())
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_->valid &&
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (drop_info_->x == event.x() && drop_info_->y == event.y())) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The location of the mouse didn't change, return the last operation.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return drop_info_->location.operation;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->x = event.x();
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->y = event.y();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DropLocation location;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateDropLocation(event, drop_info_->data, &location);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_->valid && drop_info_->location.Equals(location)) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The position we're going to drop didn't change, return the last drag
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // operation we calculated. Copy of the operation in case it changed.
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drop_info_->location.operation = location.operation;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return drop_info_->location.operation;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopShowFolderDropMenuTimer();
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sky): Optimize paint region.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->location = location;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->valid = true;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_->is_menu_showing) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bookmark_drop_menu_)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmark_drop_menu_->Cancel();
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drop_info_->is_menu_showing = false;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (location.on || location.button_type == DROP_OVERFLOW ||
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      location.button_type == DROP_OTHER_FOLDER) {
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* node;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (location.button_type == DROP_OTHER_FOLDER)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node = model_->other_node();
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (location.button_type == DROP_OVERFLOW)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node = model_->bookmark_bar_node();
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node = model_->bookmark_bar_node()->GetChild(location.index);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartShowFolderDropMenuTimer(node);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return drop_info_->location.operation;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::OnDragExited() {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopShowFolderDropMenuTimer();
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: we don't hide the menu on exit as it's possible the user moved the
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mouse over the menu, which triggers an exit on us.
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->valid = false;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_->location.index != -1) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sky): optimize the paint region.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_.reset();
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkBarView::OnPerformDrop(const DropTargetEvent& event) {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopShowFolderDropMenuTimer();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bookmark_drop_menu_)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_drop_menu_->Cancel();
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!drop_info_.get() || !drop_info_->location.operation)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::DragDropTypes::DRAG_NONE;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* root =
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (drop_info_->location.button_type == DROP_OTHER_FOLDER) ?
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      model_->other_node() : model_->bookmark_bar_node();
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = drop_info_->location.index;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index != -1) {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sky): optimize the SchedulePaint region.
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* parent_node;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drop_info_->location.button_type == DROP_OTHER_FOLDER) {
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent_node = root;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = parent_node->child_count();
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (drop_info_->location.on) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent_node = root->GetChild(index);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = parent_node->child_count();
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent_node = root;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNodeData data = drop_info_->data;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data.is_valid());
975f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool copy = drop_info_->location.operation == ui::DragDropTypes::DRAG_COPY;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_.reset();
977f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return chrome::DropBookmarks(
978f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      browser_->profile(), data, parent_node, index, copy);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::OnThemeChanged() {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColors();
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* BookmarkBarView::GetClassName() const {
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BookmarkBarView::SetVisible(bool v) {
9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (v == visible())
9911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
9921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  View::SetVisible(v);
9941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FOR_EACH_OBSERVER(BookmarkBarViewObserver, observers_,
9951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    OnBookmarkBarVisibilityChanged());
9961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
998a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BookmarkBarView::GetAccessibleState(ui::AXViewState* state) {
999a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_TOOLBAR;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1003d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BookmarkBarView::AnimationProgressed(const gfx::Animation* animation) {
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |browser_view_| can be NULL during tests.
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_view_)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_view_->ToolbarSizeChanged(true);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1009d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BookmarkBarView::AnimationEnded(const gfx::Animation* animation) {
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |browser_view_| can be NULL during tests.
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_view_) {
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser_view_->ToolbarSizeChanged(false);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1017424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void BookmarkBarView::BookmarkMenuControllerDeleted(
1018424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    BookmarkMenuController* controller) {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller == bookmark_menu_)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_menu_ = NULL;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (controller == bookmark_drop_menu_)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_drop_menu_ = NULL;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::ShowImportDialog() {
1026116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int64 install_time = g_browser_process->metrics_service()->GetInstallDate();
1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 time_from_install = base::Time::Now().ToTimeT() - install_time;
1028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (bookmark_bar_state_ == BookmarkBar::SHOW) {
102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromBookmarkBarView",
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         time_from_install);
1031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromFloatingBookmarkBarView",
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         time_from_install);
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::ShowImportDialog(browser_);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkBarView::OnBookmarkBubbleShown(const GURL& url) {
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StopThrobbing(true);
104146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const BookmarkNode* node = model_->GetMostRecentlyAddedUserNodeForURL(url);
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!node)
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // Generally shouldn't happen.
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartThrobbing(node, false);
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkBarView::OnBookmarkBubbleHidden() {
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StopThrobbing(false);
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BookmarkBarView::BookmarkModelLoaded(BookmarkModel* model,
10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          bool ids_reassigned) {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There should be no buttons. If non-zero it means Load was invoked more than
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // once, or we didn't properly clear things. Either of which shouldn't happen.
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0, GetBookmarkButtonCount());
1056f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const BookmarkNode* node = model->bookmark_bar_node();
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(node);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a button for each of the children on the bookmark bar.
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0, child_count = node->child_count(); i < child_count; ++i)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
1061f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(model->other_node());
1062f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  other_bookmarked_button_->SetAccessibleName(model->other_node()->GetTitle());
1063f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  other_bookmarked_button_->SetText(model->other_node()->GetTitle());
1064f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  managed_bookmarks_button_->SetAccessibleName(
1065f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      client_->managed_node()->GetTitle());
1066f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  managed_bookmarks_button_->SetText(client_->managed_node()->GetTitle());
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColors();
1068f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateButtonsVisibility();
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other_bookmarked_button_->SetEnabled(true);
1070f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  managed_bookmarks_button_->SetEnabled(true);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkModelBeingDeleted(BookmarkModel* model) {
1077effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  NOTREACHED();
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do minimal cleanup, presumably we'll be deleted shortly.
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->RemoveObserver(this);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_ = NULL;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeMoved(BookmarkModel* model,
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const BookmarkNode* old_parent,
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int old_index,
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const BookmarkNode* new_parent,
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int new_index) {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_throbbing = throbbing_view_ &&
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throbbing_view_ == DetermineViewToThrobFromRemove(old_parent, old_index);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (was_throbbing)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    throbbing_view_->StopThrobbing();
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeRemovedImpl(model, old_parent, old_index);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeAddedImpl(model, new_parent, new_index);
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (was_throbbing)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartThrobbing(new_parent->GetChild(new_index), false);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeAdded(BookmarkModel* model,
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const BookmarkNode* parent,
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int index) {
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeAddedImpl(model, parent, index);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeRemoved(BookmarkModel* model,
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const BookmarkNode* parent,
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int old_index,
1107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          const BookmarkNode* node,
1108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          const std::set<GURL>& removed_urls) {
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Close the menu if the menu is showing for the deleted node.
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bookmark_menu_ && bookmark_menu_->node() == node)
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bookmark_menu_->Cancel();
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeRemovedImpl(model, parent, old_index);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BookmarkBarView::BookmarkAllUserNodesRemoved(
1116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BookmarkModel* model,
1117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::set<GURL>& removed_urls) {
1118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateButtonsVisibility();
1119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StopThrobbing(true);
1121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Remove the existing buttons.
1123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (GetBookmarkButtonCount()) {
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delete GetBookmarkButton(0);
1125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Layout();
1128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SchedulePaint();
1129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeChanged(BookmarkModel* model,
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const BookmarkNode* node) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeChangedImpl(model, node);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeChildrenReordered(BookmarkModel* model,
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    const BookmarkNode* node) {
1138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (node != model->bookmark_bar_node())
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // We only care about reordering of the bookmark bar node.
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the existing buttons.
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (GetBookmarkButtonCount()) {
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* button = child_at(0);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RemoveChildView(button);
1145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->DeleteSoon(FROM_HERE, button);
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the new buttons.
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0, child_count = node->child_count(); i < child_count; ++i)
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColors();
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeFaviconChanged(BookmarkModel* model,
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const BookmarkNode* node) {
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeChangedImpl(model, node);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::WriteDragDataForView(View* sender,
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const gfx::Point& press_pt,
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ui::OSExchangeData* data) {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RecordAction(UserMetricsAction("BookmarkBar_DragButton"));
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sender == GetBookmarkButton(i)) {
1169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      views::LabelButton* button = GetBookmarkButton(i);
1170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(i);
1171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const gfx::Image& image_from_model = model_->GetFavicon(node);
1173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const gfx::ImageSkia& icon = image_from_model.IsEmpty() ?
1174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          (node->is_folder() ? GetFolderIcon() : GetDefaultFavicon()) :
1175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          *image_from_model.ToImageSkia();
1176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      button_drag_utils::SetDragImage(
1178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          node->url(),
1179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          node->GetTitle(),
1180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          icon,
1181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &press_pt,
1182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          data,
1183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          button->GetWidget());
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteBookmarkDragData(model_->bookmark_bar_node()->GetChild(i), data);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkBarView::GetDragOperationsForView(View* sender,
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const gfx::Point& p) {
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size_animation_->is_animating() ||
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (size_animation_->GetCurrentValue() == 0 &&
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       bookmark_bar_state_ != BookmarkBar::DETACHED)) {
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't let the user drag while animating open or we're closed (and not
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // detached, when detached size_animation_ is always 0). This typically is
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // only hit if the user does something to inadvertently trigger DnD such as
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pressing the mouse and hitting control-b.
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::DragDropTypes::DRAG_NONE;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sender == GetBookmarkButton(i)) {
12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return chrome::GetBookmarkDragOperation(
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          browser_->profile(), model_->bookmark_bar_node()->GetChild(i));
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::DragDropTypes::DRAG_NONE;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkBarView::CanStartDragForView(views::View* sender,
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const gfx::Point& press_pt,
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const gfx::Point& p) {
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we have not moved enough horizontally but we have moved downward
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // vertically - downward drag.
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Vector2d move_offset = p - press_pt;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Vector2d horizontal_offset(move_offset.x(), 0);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!View::ExceededDragThreshold(horizontal_offset) && move_offset.y() > 0) {
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sender == GetBookmarkButton(i)) {
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(i);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the folder button was dragged, show the menu instead.
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (node && node->is_folder()) {
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          views::MenuButton* menu_button =
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<views::MenuButton*>(sender);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          menu_button->Activate();
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::OnMenuButtonClicked(views::View* view,
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const gfx::Point& point) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node;
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start_index = 0;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view == other_bookmarked_button_) {
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = model_->other_node();
1245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (view == managed_bookmarks_button_) {
1246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    node = client_->managed_node();
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (view == overflow_button_) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = model_->bookmark_bar_node();
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start_index = GetFirstHiddenNodeIndex();
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int button_index = GetIndexOf(view);
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(-1, button_index);
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = model_->bookmark_bar_node()->GetChild(button_index);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
1257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bookmark_menu_ = new BookmarkMenuController(
1258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      browser_, page_navigator_, GetWidget(), node, start_index, false);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmark_menu_->set_observer(this);
1260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bookmark_menu_->RunMenuAt(this);
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::ButtonPressed(views::Button* sender,
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const ui::Event& event) {
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowOpenDisposition disposition_from_event_flags =
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::DispositionFromEventFlags(event.flags());
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (sender->tag() == kAppsShortcutButtonTag) {
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OpenURLParams params(GURL(chrome::kChromeUIAppsURL),
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         Referrer(),
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         disposition_from_event_flags,
12721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         ui::PAGE_TRANSITION_AUTO_BOOKMARK,
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         false);
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    page_navigator_->OpenURL(params);
127568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RecordBookmarkAppsPageOpen(GetBookmarkLaunchLocation());
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
12772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node;
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sender->tag() == kOtherFolderButtonTag) {
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = model_->other_node();
1282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (sender->tag() == kManagedFolderButtonTag) {
1283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    node = client_->managed_node();
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = GetIndexOf(sender);
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(-1, index);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node = model_->bookmark_bar_node()->GetChild(index);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(page_navigator_);
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node->is_url()) {
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RecordAppLaunch(browser_->profile(), node->url());
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenURLParams params(
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node->url(), Referrer(), disposition_from_event_flags,
12951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ui::PAGE_TRANSITION_AUTO_BOOKMARK, false);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    page_navigator_->OpenURL(params);
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome::OpenAll(GetWidget()->GetNativeWindow(), page_navigator_, node,
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    disposition_from_event_flags, browser_->profile());
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  RecordBookmarkLaunch(node, GetBookmarkLaunchLocation());
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::ShowContextMenuForView(views::View* source,
13067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                             const gfx::Point& point,
13077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                             ui::MenuSourceType source_type) {
1308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!model_->loaded()) {
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't do anything if the model isn't loaded.
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* parent = NULL;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source == other_bookmarked_button_) {
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = model_->other_node();
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do this so the user can open all bookmarks. BookmarkContextMenu makes
13182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // sure the user can't edit/delete the node in this case.
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodes.push_back(parent);
1320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (source == managed_bookmarks_button_) {
1321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    parent = client_->managed_node();
1322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    nodes.push_back(parent);
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (source != this && source != apps_page_shortcut_) {
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // User clicked on one of the bookmark buttons, find which one they
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // clicked on, except for the apps page shortcut, which must behave as if
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the user clicked on the bookmark bar background.
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bookmark_button_index = GetIndexOf(source);
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(bookmark_button_index != -1 &&
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           bookmark_button_index < GetBookmarkButtonCount());
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* node =
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        model_->bookmark_bar_node()->GetChild(bookmark_button_index);
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodes.push_back(node);
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = node->parent();
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = model_->bookmark_bar_node();
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodes.push_back(parent);
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool close_on_remove =
1339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (parent == model_->other_node()) && (parent->child_count() == 1);
1340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context_menu_.reset(new BookmarkContextMenu(
1342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetWidget(), browser_, browser_->profile(),
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser_->tab_strip_model()->GetActiveWebContents(),
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      parent, nodes, close_on_remove));
13457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  context_menu_->RunMenuAt(point, source_type);
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::Init() {
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that at this point we're not in a hierarchy so GetThemeProvider() will
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return NULL.  When we're inserted into a hierarchy, we'll call
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UpdateColors(), which will set the appropriate colors for all the objects
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // added in this function.
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Child views are traversed in the order they are added. Make sure the order
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they are added matches the visual order.
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_ = CreateOverflowButton();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(overflow_button_);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other_bookmarked_button_ = CreateOtherBookmarkedButton();
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll re-enable when the model is loaded.
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  other_bookmarked_button_->SetEnabled(false);
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(other_bookmarked_button_);
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  managed_bookmarks_button_ = CreateManagedBookmarksButton();
1365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Also re-enabled when the model is loaded.
1366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  managed_bookmarks_button_->SetEnabled(false);
1367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AddChildView(managed_bookmarks_button_);
1368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apps_page_shortcut_ = CreateAppsPageShortcutButton();
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddChildView(apps_page_shortcut_);
13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_pref_registrar_.Add(
13731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bookmarks::prefs::kShowAppsShortcutInBookmarkBar,
1374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&BookmarkBarView::OnAppsPageShortcutVisibilityPrefChanged,
1375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
1376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  profile_pref_registrar_.Add(
13771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bookmarks::prefs::kShowManagedBookmarksInBookmarkBar,
1378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&BookmarkBarView::UpdateButtonsVisibility,
1379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 base::Unretained(this)));
1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  apps_page_shortcut_->SetVisible(
1381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      chrome::ShouldShowAppsShortcutInBookmarkBar(
1382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          browser_->profile(), browser_->host_desktop_type()));
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmarks_separator_view_ = new ButtonSeparatorView();
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(bookmarks_separator_view_);
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBookmarksSeparatorVisibility();
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instructions_ = new BookmarkBarInstructionsView(this);
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(instructions_);
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_context_menu_controller(this);
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  size_animation_.reset(new gfx::SlideAnimation(this));
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  model_ = BookmarkModelFactory::GetForProfile(browser_->profile());
1396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  client_ = ChromeBookmarkClientFactory::GetForProfile(browser_->profile());
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_) {
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->AddObserver(this);
1399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (model_->loaded())
14005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BookmarkModelLoaded(model_, false);
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // else case: we'll receive notification back from the BookmarkModel when
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // done loading, then we'll populate the bar.
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BookmarkBarView::GetBookmarkButtonCount() const {
1407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // We contain six non-bookmark button views: managed bookmarks,
1408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // other bookmarks, bookmarks separator, chevrons (for overflow), apps page,
1409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // and the instruction label.
1410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return child_count() - 6;
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)views::LabelButton* BookmarkBarView::GetBookmarkButton(int index) {
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < GetBookmarkButtonCount());
1415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return static_cast<views::LabelButton*>(child_at(index));
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)BookmarkLaunchLocation BookmarkBarView::GetBookmarkLaunchLocation() const {
141968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsDetached() ? BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
142068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BookmarkBarView::GetFirstHiddenNodeIndex() {
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bb_count = GetBookmarkButtonCount();
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bb_count; ++i) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetBookmarkButton(i)->visible())
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bb_count;
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuButton* BookmarkBarView::CreateOtherBookmarkedButton() {
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Title is set in Loaded.
1434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MenuButton* button =
1435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new BookmarkFolderButton(this, base::string16(), this, false);
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_id(VIEW_ID_OTHER_BOOKMARKS);
1437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->SetImage(views::Button::STATE_NORMAL, GetFolderIcon());
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_context_menu_controller(this);
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_tag(kOtherFolderButtonTag);
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return button;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)MenuButton* BookmarkBarView::CreateManagedBookmarksButton() {
1444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Title is set in Loaded.
1445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MenuButton* button =
1446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      new BookmarkFolderButton(this, base::string16(), this, false);
1447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->set_id(VIEW_ID_MANAGED_BOOKMARKS);
14486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
14496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  gfx::ImageSkia* image =
14506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_FOLDER_MANAGED);
14516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  button->SetImage(views::Button::STATE_NORMAL, *image);
1452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->set_context_menu_controller(this);
1453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->set_tag(kManagedFolderButtonTag);
1454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return button;
1455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
1456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuButton* BookmarkBarView::CreateOverflowButton() {
1458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MenuButton* button = new OverFlowButton(this);
1460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->SetImage(views::Button::STATE_NORMAL,
1461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                   *rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_CHEVRONS));
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The overflow button's image contains an arrow and therefore it is a
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // direction sensitive image and we need to flip it if the UI layout is
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // right-to-left.
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, menu buttons are not flipped because they generally contain
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // text and flipping the gfx::Canvas object will break text rendering. Since
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the overflow button does not contain text, we can safely flip it.
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->EnableCanvasFlippingForRTLUI(true);
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make visible as necessary.
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->SetVisible(false);
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set accessibility name.
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->SetAccessibleName(
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS_CHEVRON));
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return button;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* BookmarkBarView::CreateBookmarkButton(const BookmarkNode* node) {
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node->is_url()) {
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BookmarkButton* button = new BookmarkButton(
14832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this, node->url(), node->GetTitle(), browser_->profile());
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureButton(node, button);
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return button;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::MenuButton* button = new BookmarkFolderButton(
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this, node->GetTitle(), this, false);
1489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    button->SetImage(views::Button::STATE_NORMAL, GetFolderIcon());
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureButton(node, button);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return button;
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)views::LabelButton* BookmarkBarView::CreateAppsPageShortcutButton() {
1496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  views::LabelButton* button = new ShortcutButton(
14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_APPS_SHORTCUT_NAME));
14982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  button->SetTooltipText(l10n_util::GetStringUTF16(
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      IDS_BOOKMARK_BAR_APPS_SHORTCUT_TOOLTIP));
15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  button->set_id(VIEW_ID_BOOKMARK_BAR_ELEMENT);
1501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
1502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  button->SetImage(views::Button::STATE_NORMAL,
1503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                   *rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_APPS_SHORTCUT));
15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  button->set_context_menu_controller(this);
15052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  button->set_tag(kAppsShortcutButtonTag);
15062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return button;
15072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
15082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::ConfigureButton(const BookmarkNode* node,
1510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      views::LabelButton* button) {
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->SetText(node->GetTitle());
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->SetAccessibleName(node->GetTitle());
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_id(VIEW_ID_BOOKMARK_BAR_ELEMENT);
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't always have a theme provider (ui tests, for example).
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetThemeProvider()) {
1516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    button->SetTextColor(
1517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        views::Button::STATE_NORMAL,
1518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  button->SetMinSize(gfx::Size());
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_context_menu_controller(this);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button->set_drag_controller(this);
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node->is_url()) {
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Image& favicon = model_->GetFavicon(node);
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!favicon.IsEmpty())
1527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      button->SetImage(views::Button::STATE_NORMAL, *favicon.ToImageSkia());
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      button->SetImage(views::Button::STATE_NORMAL, GetDefaultFavicon());
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  button->SetMaxSize(gfx::Size(kMaxButtonWidth, 0));
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeAddedImpl(BookmarkModel* model,
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const BookmarkNode* parent,
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int index) {
1537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateButtonsVisibility();
1538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (parent != model->bookmark_bar_node()) {
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only care about nodes on the bookmark bar.
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node = parent->GetChild(index);
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService* sync_service(ProfileSyncServiceFactory::
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetInstance()->GetForProfile(browser_->profile()));
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!throbbing_view_ && sync_service && sync_service->FirstSetupInProgress())
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartThrobbing(node, true);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildViewAt(CreateBookmarkButton(node), index);
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateColors();
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeRemovedImpl(BookmarkModel* model,
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const BookmarkNode* parent,
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int index) {
1557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateButtonsVisibility();
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopThrobbing(true);
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to start throbbing again as the bookmark bubble can't be up at
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the same time as the user reorders.
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (parent != model->bookmark_bar_node()) {
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only care about nodes on the bookmark bar.
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < GetBookmarkButtonCount());
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* button = child_at(index);
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveChildView(button);
1570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->DeleteSoon(FROM_HERE, button);
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchedulePaint();
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::BookmarkNodeChangedImpl(BookmarkModel* model,
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const BookmarkNode* node) {
1577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (node == client_->managed_node()) {
1578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // The managed node may have its title updated.
1579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    managed_bookmarks_button_->SetAccessibleName(
1580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        client_->managed_node()->GetTitle());
1581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    managed_bookmarks_button_->SetText(client_->managed_node()->GetTitle());
1582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
1583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (node->parent() != model->bookmark_bar_node()) {
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only care about nodes on the bookmark bar.
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int index = model->bookmark_bar_node()->GetIndexOf(node);
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(-1, index);
1591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  views::LabelButton* button = GetBookmarkButton(index);
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size old_pref = button->GetPreferredSize();
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureButton(node, button);
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size new_pref = button->GetPreferredSize();
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_pref.width() != new_pref.width()) {
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Layout();
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (button->visible()) {
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button->SchedulePaint();
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::ShowDropFolderForNode(const BookmarkNode* node) {
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bookmark_drop_menu_) {
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bookmark_drop_menu_->node() == node) {
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Already showing for the specified node.
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bookmark_drop_menu_->Cancel();
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::MenuButton* menu_button = GetMenuButtonForNode(node);
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!menu_button)
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start_index = 0;
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (node == model_->bookmark_bar_node())
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start_index = GetFirstHiddenNodeIndex();
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drop_info_->is_menu_showing = true;
1621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bookmark_drop_menu_ = new BookmarkMenuController(
1622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      browser_, page_navigator_, GetWidget(), node, start_index, true);
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmark_drop_menu_->set_observer(this);
1624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bookmark_drop_menu_->RunMenuAt(this);
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::StopShowFolderDropMenuTimer() {
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_folder_method_factory_.InvalidateWeakPtrs();
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::StartShowFolderDropMenuTimer(const BookmarkNode* node) {
16322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!animations_enabled) {
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // So that tests can run as fast as possible disable the delay during
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // testing.
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowDropFolderForNode(node);
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_folder_method_factory_.InvalidateWeakPtrs();
1639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BookmarkBarView::ShowDropFolderForNode,
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 show_folder_method_factory_.GetWeakPtr(),
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 node),
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay()));
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::CalculateDropLocation(const DropTargetEvent& event,
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const BookmarkNodeData& data,
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            DropLocation* location) {
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(model_);
1651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(model_->loaded());
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data.is_valid());
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *location = DropLocation();
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The drop event uses the screen coordinates while the child Views are
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // always laid out from left to right (even though they are rendered from
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // right-to-left on RTL locales). Thus, in order to make sure the drop
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinates calculation works, we mirror the event's X coordinate if the
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // locale is RTL.
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int mirrored_x = GetMirroredXInView(event.x());
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found = false;
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int other_delta_x = mirrored_x - other_bookmarked_button_->x();
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = browser_->profile();
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (other_bookmarked_button_->visible() && other_delta_x >= 0 &&
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_delta_x < other_bookmarked_button_->width()) {
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mouse is over 'other' folder.
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    location->button_type = DROP_OTHER_FOLDER;
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    location->on = true;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = true;
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!GetBookmarkButtonCount()) {
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No bookmarks, accept the drop.
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    location->index = 0;
1675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const BookmarkNode* node = data.GetFirstNode(model_, profile->GetPath());
1676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int ops = node && client_->CanBeEditedByUser(node) ?
16770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        ui::DragDropTypes::DRAG_MOVE :
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK;
16792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    location->operation = chrome::GetPreferredBookmarkDropOperation(
16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        event.source_operations(), ops);
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetBookmarkButtonCount() &&
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       GetBookmarkButton(i)->visible() && !found; i++) {
1686f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    views::LabelButton* button = GetBookmarkButton(i);
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int button_x = mirrored_x - button->x();
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int button_w = button->width();
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (button_x < button_w) {
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = true;
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(i);
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (node->is_folder()) {
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (button_x <= views::kDropBetweenPixels) {
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location->index = i;
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (button_x < button_w - views::kDropBetweenPixels) {
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location->index = i;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location->on = true;
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          location->index = i + 1;
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (button_x < button_w / 2) {
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location->index = i;
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location->index = i + 1;
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!found) {
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (overflow_button_->visible()) {
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Are we over the overflow button?
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int overflow_delta_x = mirrored_x - overflow_button_->x();
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (overflow_delta_x >= 0 &&
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          overflow_delta_x < overflow_button_->width()) {
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Mouse is over overflow button.
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location->index = GetFirstHiddenNodeIndex();
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location->button_type = DROP_OVERFLOW;
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (overflow_delta_x < 0) {
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Mouse is after the last visible button but before overflow button;
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // use the last visible index.
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        location->index = GetFirstHiddenNodeIndex();
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (!other_bookmarked_button_->visible() ||
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               mirrored_x < other_bookmarked_button_->x()) {
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Mouse is after the last visible button but before more recently
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // bookmarked; use the last visible index.
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      location->index = GetFirstHiddenNodeIndex();
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (location->on) {
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* parent = (location->button_type == DROP_OTHER_FOLDER) ?
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        model_->other_node() :
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        model_->bookmark_bar_node()->GetChild(location->index);
17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    location->operation = chrome::GetBookmarkDropOperation(
17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        profile, event, data, parent, parent->child_count());
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!location->operation && !data.has_single_url() &&
17430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        data.GetFirstNode(model_, profile->GetPath()) == parent) {
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't open a menu if the node being dragged is the menu to open.
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      location->on = false;
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    location->operation = chrome::GetBookmarkDropOperation(
17490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        profile, event, data, model_->bookmark_bar_node(), location->index);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::WriteBookmarkDragData(const BookmarkNode* node,
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            ui::OSExchangeData* data) {
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(node && data);
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkNodeData drag_data(node);
17570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  drag_data.Write(browser_->profile()->GetPath(), data);
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::StartThrobbing(const BookmarkNode* node,
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     bool overflow_only) {
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!throbbing_view_);
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine which visible button is showing the bookmark (or is an ancestor
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the bookmark).
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* bbn = model_->bookmark_bar_node();
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* parent_on_bb = node;
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (parent_on_bb) {
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* parent = parent_on_bb->parent();
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parent == bbn)
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent_on_bb = parent;
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parent_on_bb) {
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = bbn->GetIndexOf(parent_on_bb);
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index >= GetFirstHiddenNodeIndex()) {
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Node is hidden, animate the overflow button.
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throbbing_view_ = overflow_button_;
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (!overflow_only) {
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throbbing_view_ = static_cast<CustomButton*>(child_at(index));
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1782f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (client_->IsDescendantOfManagedNode(node)) {
1783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    throbbing_view_ = managed_bookmarks_button_;
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!overflow_only) {
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    throbbing_view_ = other_bookmarked_button_;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a large number so that the button continues to throb.
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throbbing_view_)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    throbbing_view_->StartThrobbing(std::numeric_limits<int>::max());
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::CustomButton* BookmarkBarView::DetermineViewToThrobFromRemove(
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* parent,
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int old_index) {
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* bbn = model_->bookmark_bar_node();
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* old_node = parent;
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_index_on_bb = old_index;
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (old_node && old_node != bbn) {
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* parent = old_node->parent();
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parent == bbn) {
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_index_on_bb = bbn->GetIndexOf(old_node);
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_node = parent;
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_node) {
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (old_index_on_bb >= GetFirstHiddenNodeIndex()) {
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Node is hidden, animate the overflow button.
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return overflow_button_;
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<CustomButton*>(child_at(old_index_on_bb));
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1814f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (client_->IsDescendantOfManagedNode(parent))
1815f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return managed_bookmarks_button_;
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Node wasn't on the bookmark bar, use the other bookmark button.
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return other_bookmarked_button_;
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkBarView::UpdateColors() {
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't always have a theme provider (ui tests, for example).
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ui::ThemeProvider* theme_provider = GetThemeProvider();
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!theme_provider)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1825f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SkColor color =
18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      theme_provider->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GetBookmarkButtonCount(); ++i)
1828f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    GetBookmarkButton(i)->SetTextColor(views::Button::STATE_NORMAL, color);
1829f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  other_bookmarked_button_->SetTextColor(views::Button::STATE_NORMAL, color);
1830f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  managed_bookmarks_button_->SetTextColor(views::Button::STATE_NORMAL, color);
18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (apps_page_shortcut_->visible())
1832f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    apps_page_shortcut_->SetTextColor(views::Button::STATE_NORMAL, color);
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BookmarkBarView::UpdateButtonsVisibility() {
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_other_children = !model_->other_node()->empty();
1837f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool update_other = has_other_children != other_bookmarked_button_->visible();
1838f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (update_other) {
1839f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    other_bookmarked_button_->SetVisible(has_other_children);
1840f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    UpdateBookmarksSeparatorVisibility();
1841f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1842f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1843f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool show_managed = !client_->managed_node()->empty() &&
1844f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      browser_->profile()->GetPrefs()->GetBoolean(
18451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          bookmarks::prefs::kShowManagedBookmarksInBookmarkBar);
1846f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool update_managed = show_managed != managed_bookmarks_button_->visible();
1847f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (update_managed)
1848f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    managed_bookmarks_button_->SetVisible(show_managed);
1849f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1850f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (update_other || update_managed) {
1851f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Layout();
1852f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SchedulePaint();
1853f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkBarView::UpdateBookmarksSeparatorVisibility() {
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ash does not paint the bookmarks separator line because it looks odd on
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the flat background.  We keep it present for layout, but don't draw it.
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bookmarks_separator_view_->SetVisible(
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser_->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH &&
1861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      other_bookmarked_button_->visible());
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BookmarkBarView::LayoutItems() {
1865cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!parent())
1866cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x = kLeftMargin;
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int top_margin = IsDetached() ? kDetachedTopMargin : 0;
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y = top_margin;
18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = View::width() - kRightMargin - kLeftMargin;
187258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int height = chrome::kBookmarkBarHeight - kBottomMargin;
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int separator_margin = kSeparatorMargin;
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDetached()) {
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double current_state = 1 - size_animation_->GetCurrentValue();
1877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    x += static_cast<int>(kNewtabHorizontalPadding * current_state);
187858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    y += (View::height() - chrome::kBookmarkBarHeight) / 2;
1879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    width -= static_cast<int>(kNewtabHorizontalPadding * current_state);
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    separator_margin -= static_cast<int>(kSeparatorMargin * current_state);
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For the attached appearance, pin the content to the bottom of the bar
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when animating in/out, as shrinking its height instead looks weird.  This
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // also matches how we layout infobars.
188558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    y += View::height() - chrome::kBookmarkBarHeight;
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size other_bookmarked_pref = other_bookmarked_button_->visible() ?
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_bookmarked_button_->GetPreferredSize() : gfx::Size();
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size overflow_pref = overflow_button_->GetPreferredSize();
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size bookmarks_separator_pref =
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks_separator_view_->GetPreferredSize();
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size apps_page_shortcut_pref = apps_page_shortcut_->visible() ?
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      apps_page_shortcut_->GetPreferredSize() : gfx::Size();
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_x = width - overflow_pref.width() - kButtonPadding -
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks_separator_pref.width();
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (other_bookmarked_button_->visible())
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_x -= other_bookmarked_pref.width() + kButtonPadding;
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next, layout out the buttons. Any buttons that are placed beyond the
1902f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // visible region are made invisible.
1903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Start with the apps page shortcut button.
1905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (apps_page_shortcut_->visible()) {
1906cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    apps_page_shortcut_->SetBounds(x, y, apps_page_shortcut_pref.width(),
1907cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   height);
1908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    x += apps_page_shortcut_pref.width() + kButtonPadding;
1909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1911f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Then comes the managed bookmarks folder, if visible.
1912f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (managed_bookmarks_button_->visible()) {
1913f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Size managed_bookmarks_pref = managed_bookmarks_button_->visible() ?
1914f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        managed_bookmarks_button_->GetPreferredSize() : gfx::Size();
1915f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    managed_bookmarks_button_->SetBounds(x, y, managed_bookmarks_pref.width(),
1916f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         height);
1917f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    x += managed_bookmarks_pref.width() + kButtonPadding;
1918f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1919f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Then go through the bookmark buttons.
1921b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (GetBookmarkButtonCount() == 0 && model_ && model_->loaded()) {
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Size pref = instructions_->GetPreferredSize();
1923cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    instructions_->SetBounds(
1924cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        x + kInstructionsPadding, y,
1925cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        std::min(static_cast<int>(pref.width()),
1926cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 max_x - x),
1927cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        height);
1928cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    instructions_->SetVisible(true);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1930cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    instructions_->SetVisible(false);
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      views::View* child = child_at(i);
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Size pref = child->GetPreferredSize();
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int next_x = x + pref.width() + kButtonPadding;
1936cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      child->SetVisible(next_x < max_x);
1937cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      child->SetBounds(x, y, pref.width(), height);
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x = next_x;
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Layout the right side of the bar.
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool all_visible = (GetBookmarkButtonCount() == 0 ||
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            child_at(GetBookmarkButtonCount() - 1)->visible());
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Layout the right side buttons.
1947cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  x = max_x + kButtonPadding;
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The overflow button.
1950cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  overflow_button_->SetBounds(x, y, overflow_pref.width(), height);
1951cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  overflow_button_->SetVisible(!all_visible);
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  x += overflow_pref.width();
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Separator.
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bookmarks_separator_view_->visible()) {
1956cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bookmarks_separator_view_->SetBounds(x,
1957cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         y - top_margin,
1958cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         bookmarks_separator_pref.width(),
1959cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         height + top_margin + kBottomMargin -
1960cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         separator_margin);
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x += bookmarks_separator_pref.width();
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The other bookmarks button.
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (other_bookmarked_button_->visible()) {
1967cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    other_bookmarked_button_->SetBounds(x, y, other_bookmarked_pref.width(),
1968cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        height);
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x += other_bookmarked_pref.width() + kButtonPadding;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BookmarkBarView::OnAppsPageShortcutVisibilityPrefChanged() {
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(apps_page_shortcut_);
1975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only perform layout if required.
1976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool visible = chrome::ShouldShowAppsShortcutInBookmarkBar(
1977f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      browser_->profile(), browser_->host_desktop_type());
1978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (apps_page_shortcut_->visible() == visible)
1979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  apps_page_shortcut_->SetVisible(visible);
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBookmarksSeparatorVisibility();
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Layout();
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1984