This source file includes following definitions.
- IsTriggerableEvent
- profile_
- GetTooltipText
- GetClassName
- GetClassName
- GetTooltipText
- IsTriggerableEvent
- OnPaint
- owner_
- OnMousePressed
- RecordAppLaunch
- ButtonSeparatorView
- ButtonSeparatorView
- OnPaint
- GetPreferredSize
- GetAccessibleState
- GetDefaultFavicon
- GetFolderIcon
- animating_detached_
- DisableAnimationsForTesting
- SetPageNavigator
- SetBookmarkBarState
- GetFullyDetachedToolbarOverlap
- is_animating
- GetNodeForButtonAtModelIndex
- GetMenuButtonForNode
- GetAnchorPositionForButton
- GetMenu
- GetContextMenu
- GetDropMenu
- StopThrobbing
- CreateToolTipForURLAndTitle
- IsDetached
- GetAnimationValue
- GetToolbarOverlap
- GetPreferredSize
- HitTestRect
- GetMinimumSize
- Layout
- ViewHierarchyChanged
- PaintChildren
- GetDropFormats
- AreDropTypesRequired
- CanDrop
- OnDragEntered
- OnDragUpdated
- OnDragExited
- OnPerformDrop
- OnThemeChanged
- GetClassName
- GetAccessibleState
- AnimationProgressed
- AnimationEnded
- BookmarkMenuControllerDeleted
- ShowImportDialog
- OnBookmarkBubbleShown
- OnBookmarkBubbleHidden
- BookmarkModelLoaded
- BookmarkModelBeingDeleted
- BookmarkNodeMoved
- BookmarkNodeAdded
- BookmarkNodeRemoved
- BookmarkAllNodesRemoved
- BookmarkNodeChanged
- BookmarkNodeChildrenReordered
- BookmarkNodeFaviconChanged
- WriteDragDataForView
- GetDragOperationsForView
- CanStartDragForView
- OnMenuButtonClicked
- ButtonPressed
- ShowContextMenuForView
- Init
- GetBookmarkButtonCount
- GetBookmarkButton
- GetBookmarkLaunchLocation
- GetFirstHiddenNodeIndex
- CreateOtherBookmarkedButton
- CreateOverflowButton
- CreateBookmarkButton
- CreateAppsPageShortcutButton
- ConfigureButton
- BookmarkNodeAddedImpl
- BookmarkNodeRemovedImpl
- BookmarkNodeChangedImpl
- ShowDropFolderForNode
- StopShowFolderDropMenuTimer
- StartShowFolderDropMenuTimer
- CalculateDropLocation
- WriteBookmarkDragData
- StartThrobbing
- DetermineViewToThrobFromRemove
- UpdateColors
- UpdateOtherBookmarksVisibility
- UpdateBookmarksSeparatorVisibility
- LayoutItems
- OnAppsPageShortcutVisibilityPrefChanged
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#include <algorithm>
#include <limits>
#include <set>
#include <vector>
#include "base/bind.h"
#include "base/i18n/rtl.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/elide_url.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
#include "chrome/browser/ui/views/event_utils.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/page_transition_types.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/theme_provider.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/text_elider.h"
#include "ui/views/button_drag_utils.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/drag_utils.h"
#include "ui/views/metrics.h"
#include "ui/views/view_constants.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/non_client_view.h"
using base::UserMetricsAction;
using content::OpenURLParams;
using content::PageNavigator;
using content::Referrer;
using ui::DropTargetEvent;
using views::CustomButton;
using views::MenuButton;
using views::MenuItemView;
using views::View;
static const int kDetachedTopMargin = 1;
static const int kBottomMargin = 2;
static const int kLeftMargin = 1;
static const int kRightMargin = 1;
const char BookmarkBarView::kViewClassName[] = "BookmarkBarView";
static const int kButtonPadding = 0;
static gfx::ImageSkia* kDefaultFavicon = NULL;
static gfx::ImageSkia* kFolderIcon = NULL;
static const SkColor kDropIndicatorColor = SK_ColorBLACK;
static const int kDropIndicatorWidth = 2;
static const int kSeparatorMargin = 1;
static const int kSeparatorWidth = 4;
static const int kSeparatorStartX = 2;
static const int kInstructionsPadding = 6;
static const int kOtherFolderButtonTag = 1;
static const int kAppsShortcutButtonTag = 2;
namespace {
bool animations_enabled = true;
class BookmarkButtonBase : public views::TextButton {
public:
BookmarkButtonBase(views::ButtonListener* listener,
const base::string16& title)
: TextButton(listener, title) {
show_animation_.reset(new gfx::SlideAnimation(this));
if (!animations_enabled) {
show_animation_->Reset(1);
} else {
show_animation_->Show();
}
}
virtual bool IsTriggerableEvent(const ui::Event& e) OVERRIDE {
return e.type() == ui::ET_GESTURE_TAP ||
e.type() == ui::ET_GESTURE_TAP_DOWN ||
event_utils::IsPossibleDispositionEvent(e);
}
private:
scoped_ptr<gfx::SlideAnimation> show_animation_;
DISALLOW_COPY_AND_ASSIGN(BookmarkButtonBase);
};
class BookmarkButton : public BookmarkButtonBase {
public:
static const char kViewClassName[];
BookmarkButton(views::ButtonListener* listener,
const GURL& url,
const base::string16& title,
Profile* profile)
: BookmarkButtonBase(listener, title),
url_(url),
profile_(profile) {
}
virtual bool GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const OVERRIDE {
gfx::Point location(p);
ConvertPointToScreen(this, &location);
*tooltip = BookmarkBarView::CreateToolTipForURLAndTitle(
GetWidget(), location, url_, text(), profile_);
return !tooltip->empty();
}
virtual const char* GetClassName() const OVERRIDE {
return kViewClassName;
}
private:
const GURL& url_;
Profile* profile_;
DISALLOW_COPY_AND_ASSIGN(BookmarkButton);
};
const char BookmarkButton::kViewClassName[] = "BookmarkButton";
class ShortcutButton : public BookmarkButtonBase {
public:
static const char kViewClassName[];
ShortcutButton(views::ButtonListener* listener,
const base::string16& title)
: BookmarkButtonBase(listener, title) {
}
virtual const char* GetClassName() const OVERRIDE {
return kViewClassName;
}
private:
DISALLOW_COPY_AND_ASSIGN(ShortcutButton);
};
const char ShortcutButton::kViewClassName[] = "ShortcutButton";
class BookmarkFolderButton : public views::MenuButton {
public:
BookmarkFolderButton(views::ButtonListener* listener,
const base::string16& title,
views::MenuButtonListener* menu_button_listener,
bool show_menu_marker)
: MenuButton(listener, title, menu_button_listener, show_menu_marker) {
show_animation_.reset(new gfx::SlideAnimation(this));
if (!animations_enabled) {
show_animation_->Reset(1);
} else {
show_animation_->Show();
}
}
virtual bool GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const OVERRIDE {
if (text_size_.width() > GetTextBounds().width())
*tooltip = text_;
return !tooltip->empty();
}
virtual bool IsTriggerableEvent(const ui::Event& e) OVERRIDE {
if (e.type() == ui::ET_GESTURE_TAP ||
(e.IsMouseEvent() && (e.flags() &
(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON))))
return false;
if (e.IsMouseEvent())
return ui::DispositionFromEventFlags(e.flags()) != CURRENT_TAB;
return false;
}
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
views::MenuButton::PaintButton(canvas, views::MenuButton::PB_NORMAL);
}
private:
scoped_ptr<gfx::SlideAnimation> show_animation_;
DISALLOW_COPY_AND_ASSIGN(BookmarkFolderButton);
};
class OverFlowButton : public views::MenuButton {
public:
explicit OverFlowButton(BookmarkBarView* owner)
: MenuButton(NULL, base::string16(), owner, false),
owner_(owner) {}
virtual bool OnMousePressed(const ui::MouseEvent& e) OVERRIDE {
owner_->StopThrobbing(true);
return views::MenuButton::OnMousePressed(e);
}
private:
BookmarkBarView* owner_;
DISALLOW_COPY_AND_ASSIGN(OverFlowButton);
};
void RecordAppLaunch(Profile* profile, GURL url) {
DCHECK(profile->GetExtensionService());
const extensions::Extension* extension =
profile->GetExtensionService()->GetInstalledApp(url);
if (!extension)
return;
CoreAppLauncherHandler::RecordAppLaunchType(
extension_misc::APP_LAUNCH_BOOKMARK_BAR,
extension->GetType());
}
}
struct BookmarkBarView::DropLocation {
DropLocation()
: index(-1),
operation(ui::DragDropTypes::DRAG_NONE),
on(false),
button_type(DROP_BOOKMARK) {
}
bool Equals(const DropLocation& other) {
return ((other.index == index) && (other.on == on) &&
(other.button_type == button_type));
}
int index;
int operation;
bool on;
DropButtonType button_type;
};
struct BookmarkBarView::DropInfo {
DropInfo()
: valid(false),
is_menu_showing(false),
x(0),
y(0) {
}
bool valid;
bool is_menu_showing;
int x;
int y;
BookmarkNodeData data;
DropLocation location;
};
class BookmarkBarView::ButtonSeparatorView : public views::View {
public:
ButtonSeparatorView() {}
virtual ~ButtonSeparatorView() {}
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
DetachableToolbarView::PaintVerticalDivider(
canvas, kSeparatorStartX, height(), 1,
DetachableToolbarView::kEdgeDividerColor,
DetachableToolbarView::kMiddleDividerColor,
GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR));
}
virtual gfx::Size GetPreferredSize() OVERRIDE {
return gfx::Size(kSeparatorWidth, 1);
}
virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_SEPARATOR);
state->role = ui::AX_ROLE_SPLITTER;
}
private:
DISALLOW_COPY_AND_ASSIGN(ButtonSeparatorView);
};
const int BookmarkBarView::kMaxButtonWidth = 150;
const int BookmarkBarView::kNewtabHorizontalPadding = 2;
const int BookmarkBarView::kToolbarAttachedBookmarkBarOverlap = 3;
static const gfx::ImageSkia& GetDefaultFavicon() {
if (!kDefaultFavicon) {
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
kDefaultFavicon = rb->GetImageSkiaNamed(IDR_DEFAULT_FAVICON);
}
return *kDefaultFavicon;
}
static const gfx::ImageSkia& GetFolderIcon() {
if (!kFolderIcon) {
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
kFolderIcon = rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_FOLDER);
}
return *kFolderIcon;
}
BookmarkBarView::BookmarkBarView(Browser* browser, BrowserView* browser_view)
: page_navigator_(NULL),
model_(NULL),
bookmark_menu_(NULL),
bookmark_drop_menu_(NULL),
other_bookmarked_button_(NULL),
apps_page_shortcut_(NULL),
show_folder_method_factory_(this),
overflow_button_(NULL),
instructions_(NULL),
bookmarks_separator_view_(NULL),
browser_(browser),
browser_view_(browser_view),
infobar_visible_(false),
throbbing_view_(NULL),
bookmark_bar_state_(BookmarkBar::SHOW),
animating_detached_(false) {
set_id(VIEW_ID_BOOKMARK_BAR);
Init();
size_animation_->Reset(1);
}
BookmarkBarView::~BookmarkBarView() {
if (model_)
model_->RemoveObserver(this);
if (bookmark_menu_) {
bookmark_menu_->set_observer(NULL);
bookmark_menu_->SetPageNavigator(NULL);
bookmark_menu_->clear_bookmark_bar();
}
if (context_menu_.get())
context_menu_->SetPageNavigator(NULL);
StopShowFolderDropMenuTimer();
}
void BookmarkBarView::DisableAnimationsForTesting(bool disabled) {
animations_enabled = !disabled;
}
void BookmarkBarView::SetPageNavigator(PageNavigator* navigator) {
page_navigator_ = navigator;
if (bookmark_menu_)
bookmark_menu_->SetPageNavigator(navigator);
if (context_menu_.get())
context_menu_->SetPageNavigator(navigator);
}
void BookmarkBarView::SetBookmarkBarState(
BookmarkBar::State state,
BookmarkBar::AnimateChangeType animate_type) {
if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE &&
animations_enabled) {
animating_detached_ = (state == BookmarkBar::DETACHED ||
bookmark_bar_state_ == BookmarkBar::DETACHED);
if (state == BookmarkBar::SHOW)
size_animation_->Show();
else
size_animation_->Hide();
} else {
size_animation_->Reset(state == BookmarkBar::SHOW ? 1 : 0);
}
bookmark_bar_state_ = state;
}
int BookmarkBarView::GetFullyDetachedToolbarOverlap() const {
if (!infobar_visible_ && browser_->window()->IsFullscreen()) {
return 0;
}
return views::NonClientFrameView::kClientEdgeThickness;
}
bool BookmarkBarView::is_animating() {
return size_animation_->is_animating();
}
const BookmarkNode* BookmarkBarView::GetNodeForButtonAtModelIndex(
const gfx::Point& loc,
int* model_start_index) {
*model_start_index = 0;
if (loc.x() < 0 || loc.x() >= width() || loc.y() < 0 || loc.y() >= height())
return NULL;
gfx::Point adjusted_loc(GetMirroredXInView(loc.x()), loc.y());
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
views::View* child = child_at(i);
if (!child->visible())
break;
if (child->bounds().Contains(adjusted_loc))
return model_->bookmark_bar_node()->GetChild(i);
}
if (overflow_button_->visible() &&
overflow_button_->bounds().Contains(adjusted_loc)) {
*model_start_index = GetFirstHiddenNodeIndex();
return model_->bookmark_bar_node();
}
if (other_bookmarked_button_->visible() &&
other_bookmarked_button_->bounds().Contains(adjusted_loc)) {
return model_->other_node();
}
return NULL;
}
views::MenuButton* BookmarkBarView::GetMenuButtonForNode(
const BookmarkNode* node) {
if (node == model_->other_node())
return other_bookmarked_button_;
if (node == model_->bookmark_bar_node())
return overflow_button_;
int index = model_->bookmark_bar_node()->GetIndexOf(node);
if (index == -1 || !node->is_folder())
return NULL;
return static_cast<views::MenuButton*>(child_at(index));
}
void BookmarkBarView::GetAnchorPositionForButton(
views::MenuButton* button,
MenuItemView::AnchorPosition* anchor) {
if (button == other_bookmarked_button_ || button == overflow_button_)
*anchor = MenuItemView::TOPRIGHT;
else
*anchor = MenuItemView::TOPLEFT;
}
views::MenuItemView* BookmarkBarView::GetMenu() {
return bookmark_menu_ ? bookmark_menu_->menu() : NULL;
}
views::MenuItemView* BookmarkBarView::GetContextMenu() {
return bookmark_menu_ ? bookmark_menu_->context_menu() : NULL;
}
views::MenuItemView* BookmarkBarView::GetDropMenu() {
return bookmark_drop_menu_ ? bookmark_drop_menu_->menu() : NULL;
}
void BookmarkBarView::StopThrobbing(bool immediate) {
if (!throbbing_view_)
return;
throbbing_view_->StartThrobbing(immediate ? 0 : 4);
throbbing_view_ = NULL;
}
base::string16 BookmarkBarView::CreateToolTipForURLAndTitle(
const views::Widget* widget,
const gfx::Point& screen_loc,
const GURL& url,
const base::string16& title,
Profile* profile) {
int max_width = views::TooltipManager::GetMaxWidth(
screen_loc.x(),
screen_loc.y(),
widget->GetNativeView());
const gfx::FontList tt_fonts = widget->GetTooltipManager()->GetFontList();
base::string16 result;
if (!title.empty()) {
base::string16 localized_title = title;
base::i18n::AdjustStringForLocaleDirection(&localized_title);
result.append(ElideText(localized_title, tt_fonts, max_width,
gfx::ELIDE_AT_END));
}
if (title != base::UTF8ToUTF16(url.spec())) {
if (!result.empty())
result.push_back('\n');
std::string languages = profile->GetPrefs()->GetString(
prefs::kAcceptLanguages);
base::string16 elided_url(ElideUrl(url, tt_fonts, max_width, languages));
elided_url = base::i18n::GetDisplayStringInLTRDirectionality(elided_url);
result.append(elided_url);
}
return result;
}
bool BookmarkBarView::IsDetached() const {
return (bookmark_bar_state_ == BookmarkBar::DETACHED) ||
(animating_detached_ && size_animation_->is_animating());
}
double BookmarkBarView::GetAnimationValue() const {
return size_animation_->GetCurrentValue();
}
int BookmarkBarView::GetToolbarOverlap() const {
int attached_overlap = kToolbarAttachedBookmarkBarOverlap +
views::NonClientFrameView::kClientEdgeThickness;
if (!IsDetached())
return attached_overlap;
int detached_overlap = GetFullyDetachedToolbarOverlap();
if (infobar_visible_)
return detached_overlap;
return detached_overlap + static_cast<int>(
(attached_overlap - detached_overlap) *
size_animation_->GetCurrentValue());
}
gfx::Size BookmarkBarView::GetPreferredSize() {
return LayoutItems(true);
}
bool BookmarkBarView::HitTestRect(const gfx::Rect& rect) const {
if (!IsDetached() && browser_view_ &&
browser_view_->GetLocationBar()->GetOmniboxView()->model()->
popup_model()->IsOpen()) {
return false;
}
return DetachableToolbarView::HitTestRect(rect);
}
gfx::Size BookmarkBarView::GetMinimumSize() {
int width = kLeftMargin;
int height = chrome::kBookmarkBarHeight;
if (IsDetached()) {
double current_state = 1 - size_animation_->GetCurrentValue();
width += 2 * static_cast<int>(kNewtabHorizontalPadding * current_state);
height += static_cast<int>(
(chrome::kNTPBookmarkBarHeight - chrome::kBookmarkBarHeight) *
current_state);
}
gfx::Size other_bookmarked_pref;
if (other_bookmarked_button_->visible())
other_bookmarked_pref = other_bookmarked_button_->GetPreferredSize();
gfx::Size overflow_pref;
if (overflow_button_->visible())
overflow_pref = overflow_button_->GetPreferredSize();
gfx::Size bookmarks_separator_pref;
if (bookmarks_separator_view_->visible())
bookmarks_separator_pref = bookmarks_separator_view_->GetPreferredSize();
gfx::Size apps_page_shortcut_pref;
if (apps_page_shortcut_->visible())
apps_page_shortcut_pref = apps_page_shortcut_->GetPreferredSize();
width += other_bookmarked_pref.width() + kButtonPadding +
apps_page_shortcut_pref.width() + kButtonPadding +
overflow_pref.width() + kButtonPadding +
bookmarks_separator_pref.width();
return gfx::Size(width, height);
}
void BookmarkBarView::Layout() {
LayoutItems(false);
}
void BookmarkBarView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
if (details.is_add && details.child == this) {
UpdateColors();
if (height() > 0) {
Layout();
}
}
}
void BookmarkBarView::PaintChildren(gfx::Canvas* canvas) {
View::PaintChildren(canvas);
if (drop_info_.get() && drop_info_->valid &&
drop_info_->location.operation != 0 && drop_info_->location.index != -1 &&
drop_info_->location.button_type != DROP_OVERFLOW &&
!drop_info_->location.on) {
int index = drop_info_->location.index;
DCHECK(index <= GetBookmarkButtonCount());
int x = 0;
int y = 0;
int h = height();
if (index == GetBookmarkButtonCount()) {
if (index == 0) {
x = kLeftMargin;
} else {
x = GetBookmarkButton(index - 1)->x() +
GetBookmarkButton(index - 1)->width();
}
} else {
x = GetBookmarkButton(index)->x();
}
if (GetBookmarkButtonCount() > 0 && GetBookmarkButton(0)->visible()) {
y = GetBookmarkButton(0)->y();
h = GetBookmarkButton(0)->height();
}
gfx::Rect indicator_bounds(x - kDropIndicatorWidth / 2,
y,
kDropIndicatorWidth,
h);
indicator_bounds.set_x(GetMirroredXForRect(indicator_bounds));
canvas->FillRect(indicator_bounds, kDropIndicatorColor);
}
}
bool BookmarkBarView::GetDropFormats(
int* formats,
std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
if (!model_ || !model_->loaded())
return false;
*formats = ui::OSExchangeData::URL;
custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat());
return true;
}
bool BookmarkBarView::AreDropTypesRequired() {
return true;
}
bool BookmarkBarView::CanDrop(const ui::OSExchangeData& data) {
if (!model_ || !model_->loaded() ||
!browser_->profile()->GetPrefs()->GetBoolean(
prefs::kEditBookmarksEnabled))
return false;
if (!drop_info_.get())
drop_info_.reset(new DropInfo());
return drop_info_->data.Read(data) && drop_info_->data.size() == 1;
}
void BookmarkBarView::OnDragEntered(const DropTargetEvent& event) {
}
int BookmarkBarView::OnDragUpdated(const DropTargetEvent& event) {
if (!drop_info_.get())
return 0;
if (drop_info_->valid &&
(drop_info_->x == event.x() && drop_info_->y == event.y())) {
return drop_info_->location.operation;
}
drop_info_->x = event.x();
drop_info_->y = event.y();
DropLocation location;
CalculateDropLocation(event, drop_info_->data, &location);
if (drop_info_->valid && drop_info_->location.Equals(location)) {
drop_info_->location.operation = location.operation;
return drop_info_->location.operation;
}
StopShowFolderDropMenuTimer();
SchedulePaint();
drop_info_->location = location;
drop_info_->valid = true;
if (drop_info_->is_menu_showing) {
if (bookmark_drop_menu_)
bookmark_drop_menu_->Cancel();
drop_info_->is_menu_showing = false;
}
if (location.on || location.button_type == DROP_OVERFLOW ||
location.button_type == DROP_OTHER_FOLDER) {
const BookmarkNode* node;
if (location.button_type == DROP_OTHER_FOLDER)
node = model_->other_node();
else if (location.button_type == DROP_OVERFLOW)
node = model_->bookmark_bar_node();
else
node = model_->bookmark_bar_node()->GetChild(location.index);
StartShowFolderDropMenuTimer(node);
}
return drop_info_->location.operation;
}
void BookmarkBarView::OnDragExited() {
StopShowFolderDropMenuTimer();
drop_info_->valid = false;
if (drop_info_->location.index != -1) {
SchedulePaint();
}
drop_info_.reset();
}
int BookmarkBarView::OnPerformDrop(const DropTargetEvent& event) {
StopShowFolderDropMenuTimer();
if (bookmark_drop_menu_)
bookmark_drop_menu_->Cancel();
if (!drop_info_.get() || !drop_info_->location.operation)
return ui::DragDropTypes::DRAG_NONE;
const BookmarkNode* root =
(drop_info_->location.button_type == DROP_OTHER_FOLDER) ?
model_->other_node() : model_->bookmark_bar_node();
int index = drop_info_->location.index;
if (index != -1) {
SchedulePaint();
}
const BookmarkNode* parent_node;
if (drop_info_->location.button_type == DROP_OTHER_FOLDER) {
parent_node = root;
index = parent_node->child_count();
} else if (drop_info_->location.on) {
parent_node = root->GetChild(index);
index = parent_node->child_count();
} else {
parent_node = root;
}
const BookmarkNodeData data = drop_info_->data;
DCHECK(data.is_valid());
drop_info_.reset();
return chrome::DropBookmarks(browser_->profile(), data, parent_node, index);
}
void BookmarkBarView::OnThemeChanged() {
UpdateColors();
}
const char* BookmarkBarView::GetClassName() const {
return kViewClassName;
}
void BookmarkBarView::GetAccessibleState(ui::AXViewState* state) {
state->role = ui::AX_ROLE_TOOLBAR;
state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS);
}
void BookmarkBarView::AnimationProgressed(const gfx::Animation* animation) {
if (browser_view_)
browser_view_->ToolbarSizeChanged(true);
}
void BookmarkBarView::AnimationEnded(const gfx::Animation* animation) {
if (browser_view_) {
browser_view_->ToolbarSizeChanged(false);
SchedulePaint();
}
}
void BookmarkBarView::BookmarkMenuControllerDeleted(
BookmarkMenuController* controller) {
if (controller == bookmark_menu_)
bookmark_menu_ = NULL;
else if (controller == bookmark_drop_menu_)
bookmark_drop_menu_ = NULL;
}
void BookmarkBarView::ShowImportDialog() {
int64 install_time =
g_browser_process->local_state()->GetInt64(prefs::kInstallDate);
int64 time_from_install = base::Time::Now().ToTimeT() - install_time;
if (bookmark_bar_state_ == BookmarkBar::SHOW) {
UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromBookmarkBarView",
time_from_install);
} else if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
UMA_HISTOGRAM_COUNTS("Import.ShowDialog.FromFloatingBookmarkBarView",
time_from_install);
}
chrome::ShowImportDialog(browser_);
}
void BookmarkBarView::OnBookmarkBubbleShown(const GURL& url) {
StopThrobbing(true);
const BookmarkNode* node = model_->GetMostRecentlyAddedNodeForURL(url);
if (!node)
return;
StartThrobbing(node, false);
}
void BookmarkBarView::OnBookmarkBubbleHidden() {
StopThrobbing(false);
}
void BookmarkBarView::BookmarkModelLoaded(BookmarkModel* model,
bool ids_reassigned) {
DCHECK_EQ(0, GetBookmarkButtonCount());
const BookmarkNode* node = model_->bookmark_bar_node();
DCHECK(node);
for (int i = 0, child_count = node->child_count(); i < child_count; ++i)
AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
DCHECK(model_->other_node());
other_bookmarked_button_->SetAccessibleName(model_->other_node()->GetTitle());
other_bookmarked_button_->SetText(model_->other_node()->GetTitle());
UpdateColors();
UpdateOtherBookmarksVisibility();
other_bookmarked_button_->SetEnabled(true);
Layout();
SchedulePaint();
}
void BookmarkBarView::BookmarkModelBeingDeleted(BookmarkModel* model) {
NOTREACHED();
model_->RemoveObserver(this);
model_ = NULL;
}
void BookmarkBarView::BookmarkNodeMoved(BookmarkModel* model,
const BookmarkNode* old_parent,
int old_index,
const BookmarkNode* new_parent,
int new_index) {
bool was_throbbing = throbbing_view_ &&
throbbing_view_ == DetermineViewToThrobFromRemove(old_parent, old_index);
if (was_throbbing)
throbbing_view_->StopThrobbing();
BookmarkNodeRemovedImpl(model, old_parent, old_index);
BookmarkNodeAddedImpl(model, new_parent, new_index);
if (was_throbbing)
StartThrobbing(new_parent->GetChild(new_index), false);
}
void BookmarkBarView::BookmarkNodeAdded(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
BookmarkNodeAddedImpl(model, parent, index);
}
void BookmarkBarView::BookmarkNodeRemoved(BookmarkModel* model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node) {
if (bookmark_menu_ && bookmark_menu_->node() == node)
bookmark_menu_->Cancel();
BookmarkNodeRemovedImpl(model, parent, old_index);
}
void BookmarkBarView::BookmarkAllNodesRemoved(BookmarkModel* model) {
UpdateOtherBookmarksVisibility();
StopThrobbing(true);
while (GetBookmarkButtonCount()) {
delete GetBookmarkButton(0);
}
Layout();
SchedulePaint();
}
void BookmarkBarView::BookmarkNodeChanged(BookmarkModel* model,
const BookmarkNode* node) {
BookmarkNodeChangedImpl(model, node);
}
void BookmarkBarView::BookmarkNodeChildrenReordered(BookmarkModel* model,
const BookmarkNode* node) {
if (node != model_->bookmark_bar_node())
return;
while (GetBookmarkButtonCount()) {
views::View* button = child_at(0);
RemoveChildView(button);
base::MessageLoop::current()->DeleteSoon(FROM_HERE, button);
}
for (int i = 0, child_count = node->child_count(); i < child_count; ++i)
AddChildViewAt(CreateBookmarkButton(node->GetChild(i)), i);
UpdateColors();
Layout();
SchedulePaint();
}
void BookmarkBarView::BookmarkNodeFaviconChanged(BookmarkModel* model,
const BookmarkNode* node) {
BookmarkNodeChangedImpl(model, node);
}
void BookmarkBarView::WriteDragDataForView(View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) {
content::RecordAction(UserMetricsAction("BookmarkBar_DragButton"));
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
if (sender == GetBookmarkButton(i)) {
views::TextButton* button = GetBookmarkButton(i);
scoped_ptr<gfx::Canvas> canvas(
views::GetCanvasForDragImage(button->GetWidget(), button->size()));
button->PaintButton(canvas.get(), views::TextButton::PB_FOR_DRAG);
drag_utils::SetDragImageOnDataObject(*canvas, button->size(),
press_pt.OffsetFromOrigin(),
data);
WriteBookmarkDragData(model_->bookmark_bar_node()->GetChild(i), data);
return;
}
}
NOTREACHED();
}
int BookmarkBarView::GetDragOperationsForView(View* sender,
const gfx::Point& p) {
if (size_animation_->is_animating() ||
(size_animation_->GetCurrentValue() == 0 &&
bookmark_bar_state_ != BookmarkBar::DETACHED)) {
return ui::DragDropTypes::DRAG_NONE;
}
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
if (sender == GetBookmarkButton(i)) {
return chrome::GetBookmarkDragOperation(
browser_->profile(), model_->bookmark_bar_node()->GetChild(i));
}
}
NOTREACHED();
return ui::DragDropTypes::DRAG_NONE;
}
bool BookmarkBarView::CanStartDragForView(views::View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) {
gfx::Vector2d move_offset = p - press_pt;
gfx::Vector2d horizontal_offset(move_offset.x(), 0);
if (!View::ExceededDragThreshold(horizontal_offset) && move_offset.y() > 0) {
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
if (sender == GetBookmarkButton(i)) {
const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(i);
if (node && node->is_folder()) {
views::MenuButton* menu_button =
static_cast<views::MenuButton*>(sender);
menu_button->Activate();
return false;
}
break;
}
}
}
return true;
}
void BookmarkBarView::OnMenuButtonClicked(views::View* view,
const gfx::Point& point) {
const BookmarkNode* node;
int start_index = 0;
if (view == other_bookmarked_button_) {
node = model_->other_node();
} else if (view == overflow_button_) {
node = model_->bookmark_bar_node();
start_index = GetFirstHiddenNodeIndex();
} else {
int button_index = GetIndexOf(view);
DCHECK_NE(-1, button_index);
node = model_->bookmark_bar_node()->GetChild(button_index);
}
RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
bookmark_menu_ = new BookmarkMenuController(
browser_, page_navigator_, GetWidget(), node, start_index);
bookmark_menu_->set_observer(this);
bookmark_menu_->RunMenuAt(this, false);
}
void BookmarkBarView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
WindowOpenDisposition disposition_from_event_flags =
ui::DispositionFromEventFlags(event.flags());
if (sender->tag() == kAppsShortcutButtonTag) {
OpenURLParams params(GURL(chrome::kChromeUIAppsURL),
Referrer(),
disposition_from_event_flags,
content::PAGE_TRANSITION_AUTO_BOOKMARK,
false);
page_navigator_->OpenURL(params);
RecordBookmarkAppsPageOpen(GetBookmarkLaunchLocation());
return;
}
const BookmarkNode* node;
if (sender->tag() == kOtherFolderButtonTag) {
node = model_->other_node();
} else {
int index = GetIndexOf(sender);
DCHECK_NE(-1, index);
node = model_->bookmark_bar_node()->GetChild(index);
}
DCHECK(page_navigator_);
if (node->is_url()) {
RecordAppLaunch(browser_->profile(), node->url());
OpenURLParams params(
node->url(), Referrer(), disposition_from_event_flags,
content::PAGE_TRANSITION_AUTO_BOOKMARK, false);
page_navigator_->OpenURL(params);
} else {
chrome::OpenAll(GetWidget()->GetNativeWindow(), page_navigator_, node,
disposition_from_event_flags, browser_->profile());
}
RecordBookmarkLaunch(node, GetBookmarkLaunchLocation());
}
void BookmarkBarView::ShowContextMenuForView(views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) {
if (!model_->loaded()) {
return;
}
const BookmarkNode* parent = NULL;
std::vector<const BookmarkNode*> nodes;
if (source == other_bookmarked_button_) {
parent = model_->other_node();
nodes.push_back(parent);
} else if (source != this && source != apps_page_shortcut_) {
int bookmark_button_index = GetIndexOf(source);
DCHECK(bookmark_button_index != -1 &&
bookmark_button_index < GetBookmarkButtonCount());
const BookmarkNode* node =
model_->bookmark_bar_node()->GetChild(bookmark_button_index);
nodes.push_back(node);
parent = node->parent();
} else {
parent = model_->bookmark_bar_node();
nodes.push_back(parent);
}
bool close_on_remove =
(parent == model_->other_node()) && (parent->child_count() == 1);
context_menu_.reset(new BookmarkContextMenu(
GetWidget(), browser_, browser_->profile(),
browser_->tab_strip_model()->GetActiveWebContents(),
parent, nodes, close_on_remove));
context_menu_->RunMenuAt(point, source_type);
}
void BookmarkBarView::Init() {
overflow_button_ = CreateOverflowButton();
AddChildView(overflow_button_);
other_bookmarked_button_ = CreateOtherBookmarkedButton();
other_bookmarked_button_->SetEnabled(false);
AddChildView(other_bookmarked_button_);
apps_page_shortcut_ = CreateAppsPageShortcutButton();
AddChildView(apps_page_shortcut_);
profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
profile_pref_registrar_.Add(
prefs::kShowAppsShortcutInBookmarkBar,
base::Bind(&BookmarkBarView::OnAppsPageShortcutVisibilityPrefChanged,
base::Unretained(this)));
apps_page_shortcut_->SetVisible(
chrome::ShouldShowAppsShortcutInBookmarkBar(
browser_->profile(), browser_->host_desktop_type()));
bookmarks_separator_view_ = new ButtonSeparatorView();
AddChildView(bookmarks_separator_view_);
UpdateBookmarksSeparatorVisibility();
instructions_ = new BookmarkBarInstructionsView(this);
AddChildView(instructions_);
set_context_menu_controller(this);
size_animation_.reset(new gfx::SlideAnimation(this));
model_ = BookmarkModelFactory::GetForProfile(browser_->profile());
if (model_) {
model_->AddObserver(this);
if (model_->loaded())
BookmarkModelLoaded(model_, false);
}
}
int BookmarkBarView::GetBookmarkButtonCount() {
return child_count() - 5;
}
views::TextButton* BookmarkBarView::GetBookmarkButton(int index) {
DCHECK(index >= 0 && index < GetBookmarkButtonCount());
return static_cast<views::TextButton*>(child_at(index));
}
BookmarkLaunchLocation BookmarkBarView::GetBookmarkLaunchLocation() const {
return IsDetached() ? BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
}
int BookmarkBarView::GetFirstHiddenNodeIndex() {
const int bb_count = GetBookmarkButtonCount();
for (int i = 0; i < bb_count; ++i) {
if (!GetBookmarkButton(i)->visible())
return i;
}
return bb_count;
}
MenuButton* BookmarkBarView::CreateOtherBookmarkedButton() {
MenuButton* button =
new BookmarkFolderButton(this, base::string16(), this, false);
button->set_id(VIEW_ID_OTHER_BOOKMARKS);
button->SetIcon(GetFolderIcon());
button->set_context_menu_controller(this);
button->set_tag(kOtherFolderButtonTag);
return button;
}
MenuButton* BookmarkBarView::CreateOverflowButton() {
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
MenuButton* button = new OverFlowButton(this);
button->SetIcon(*rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_CHEVRONS));
button->EnableCanvasFlippingForRTLUI(true);
button->SetVisible(false);
button->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ACCNAME_BOOKMARKS_CHEVRON));
return button;
}
views::View* BookmarkBarView::CreateBookmarkButton(const BookmarkNode* node) {
if (node->is_url()) {
BookmarkButton* button = new BookmarkButton(
this, node->url(), node->GetTitle(), browser_->profile());
ConfigureButton(node, button);
return button;
} else {
views::MenuButton* button = new BookmarkFolderButton(
this, node->GetTitle(), this, false);
button->SetIcon(GetFolderIcon());
ConfigureButton(node, button);
return button;
}
}
views::TextButton* BookmarkBarView::CreateAppsPageShortcutButton() {
views::TextButton* button = new ShortcutButton(
this, l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_APPS_SHORTCUT_NAME));
button->SetTooltipText(l10n_util::GetStringUTF16(
IDS_BOOKMARK_BAR_APPS_SHORTCUT_TOOLTIP));
button->set_id(VIEW_ID_BOOKMARK_BAR_ELEMENT);
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
button->SetIcon(*rb->GetImageSkiaNamed(IDR_BOOKMARK_BAR_APPS_SHORTCUT));
button->set_context_menu_controller(this);
button->set_tag(kAppsShortcutButtonTag);
return button;
}
void BookmarkBarView::ConfigureButton(const BookmarkNode* node,
views::TextButton* button) {
button->SetText(node->GetTitle());
button->SetAccessibleName(node->GetTitle());
button->set_id(VIEW_ID_BOOKMARK_BAR_ELEMENT);
if (GetThemeProvider()) {
button->SetEnabledColor(GetThemeProvider()->GetColor(
ThemeProperties::COLOR_BOOKMARK_TEXT));
}
button->ClearMaxTextSize();
button->set_context_menu_controller(this);
button->set_drag_controller(this);
if (node->is_url()) {
const gfx::Image& favicon = model_->GetFavicon(node);
if (!favicon.IsEmpty())
button->SetIcon(*favicon.ToImageSkia());
else
button->SetIcon(GetDefaultFavicon());
}
button->set_max_width(kMaxButtonWidth);
}
void BookmarkBarView::BookmarkNodeAddedImpl(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
UpdateOtherBookmarksVisibility();
if (parent != model_->bookmark_bar_node()) {
return;
}
DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
const BookmarkNode* node = parent->GetChild(index);
ProfileSyncService* sync_service(ProfileSyncServiceFactory::
GetInstance()->GetForProfile(browser_->profile()));
if (!throbbing_view_ && sync_service && sync_service->FirstSetupInProgress())
StartThrobbing(node, true);
AddChildViewAt(CreateBookmarkButton(node), index);
UpdateColors();
Layout();
SchedulePaint();
}
void BookmarkBarView::BookmarkNodeRemovedImpl(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
UpdateOtherBookmarksVisibility();
StopThrobbing(true);
if (parent != model_->bookmark_bar_node()) {
return;
}
DCHECK(index >= 0 && index < GetBookmarkButtonCount());
views::View* button = child_at(index);
RemoveChildView(button);
base::MessageLoop::current()->DeleteSoon(FROM_HERE, button);
Layout();
SchedulePaint();
}
void BookmarkBarView::BookmarkNodeChangedImpl(BookmarkModel* model,
const BookmarkNode* node) {
if (node->parent() != model_->bookmark_bar_node()) {
return;
}
int index = model_->bookmark_bar_node()->GetIndexOf(node);
DCHECK_NE(-1, index);
views::TextButton* button = GetBookmarkButton(index);
gfx::Size old_pref = button->GetPreferredSize();
ConfigureButton(node, button);
gfx::Size new_pref = button->GetPreferredSize();
if (old_pref.width() != new_pref.width()) {
Layout();
SchedulePaint();
} else if (button->visible()) {
button->SchedulePaint();
}
}
void BookmarkBarView::ShowDropFolderForNode(const BookmarkNode* node) {
if (bookmark_drop_menu_) {
if (bookmark_drop_menu_->node() == node) {
return;
}
bookmark_drop_menu_->Cancel();
}
views::MenuButton* menu_button = GetMenuButtonForNode(node);
if (!menu_button)
return;
int start_index = 0;
if (node == model_->bookmark_bar_node())
start_index = GetFirstHiddenNodeIndex();
drop_info_->is_menu_showing = true;
bookmark_drop_menu_ = new BookmarkMenuController(browser_,
page_navigator_, GetWidget(), node, start_index);
bookmark_drop_menu_->set_observer(this);
bookmark_drop_menu_->RunMenuAt(this, true);
}
void BookmarkBarView::StopShowFolderDropMenuTimer() {
show_folder_method_factory_.InvalidateWeakPtrs();
}
void BookmarkBarView::StartShowFolderDropMenuTimer(const BookmarkNode* node) {
if (!animations_enabled) {
ShowDropFolderForNode(node);
return;
}
show_folder_method_factory_.InvalidateWeakPtrs();
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&BookmarkBarView::ShowDropFolderForNode,
show_folder_method_factory_.GetWeakPtr(),
node),
base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay()));
}
void BookmarkBarView::CalculateDropLocation(const DropTargetEvent& event,
const BookmarkNodeData& data,
DropLocation* location) {
DCHECK(model_);
DCHECK(model_->loaded());
DCHECK(data.is_valid());
*location = DropLocation();
int mirrored_x = GetMirroredXInView(event.x());
bool found = false;
const int other_delta_x = mirrored_x - other_bookmarked_button_->x();
Profile* profile = browser_->profile();
if (other_bookmarked_button_->visible() && other_delta_x >= 0 &&
other_delta_x < other_bookmarked_button_->width()) {
location->button_type = DROP_OTHER_FOLDER;
location->on = true;
found = true;
} else if (!GetBookmarkButtonCount()) {
location->index = 0;
int ops = data.GetFirstNode(profile) ? ui::DragDropTypes::DRAG_MOVE :
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK;
location->operation = chrome::GetPreferredBookmarkDropOperation(
event.source_operations(), ops);
return;
}
for (int i = 0; i < GetBookmarkButtonCount() &&
GetBookmarkButton(i)->visible() && !found; i++) {
views::TextButton* button = GetBookmarkButton(i);
int button_x = mirrored_x - button->x();
int button_w = button->width();
if (button_x < button_w) {
found = true;
const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(i);
if (node->is_folder()) {
if (button_x <= views::kDropBetweenPixels) {
location->index = i;
} else if (button_x < button_w - views::kDropBetweenPixels) {
location->index = i;
location->on = true;
} else {
location->index = i + 1;
}
} else if (button_x < button_w / 2) {
location->index = i;
} else {
location->index = i + 1;
}
break;
}
}
if (!found) {
if (overflow_button_->visible()) {
int overflow_delta_x = mirrored_x - overflow_button_->x();
if (overflow_delta_x >= 0 &&
overflow_delta_x < overflow_button_->width()) {
location->index = GetFirstHiddenNodeIndex();
location->button_type = DROP_OVERFLOW;
} else if (overflow_delta_x < 0) {
location->index = GetFirstHiddenNodeIndex();
} else {
return;
}
} else if (!other_bookmarked_button_->visible() ||
mirrored_x < other_bookmarked_button_->x()) {
location->index = GetFirstHiddenNodeIndex();
} else {
return;
}
}
if (location->on) {
const BookmarkNode* parent = (location->button_type == DROP_OTHER_FOLDER) ?
model_->other_node() :
model_->bookmark_bar_node()->GetChild(location->index);
location->operation = chrome::GetBookmarkDropOperation(
profile, event, data, parent, parent->child_count());
if (!location->operation && !data.has_single_url() &&
data.GetFirstNode(profile) == parent) {
location->on = false;
}
} else {
location->operation = chrome::GetBookmarkDropOperation(profile, event,
data, model_->bookmark_bar_node(), location->index);
}
}
void BookmarkBarView::WriteBookmarkDragData(const BookmarkNode* node,
ui::OSExchangeData* data) {
DCHECK(node && data);
BookmarkNodeData drag_data(node);
drag_data.Write(browser_->profile(), data);
}
void BookmarkBarView::StartThrobbing(const BookmarkNode* node,
bool overflow_only) {
DCHECK(!throbbing_view_);
const BookmarkNode* bbn = model_->bookmark_bar_node();
const BookmarkNode* parent_on_bb = node;
while (parent_on_bb) {
const BookmarkNode* parent = parent_on_bb->parent();
if (parent == bbn)
break;
parent_on_bb = parent;
}
if (parent_on_bb) {
int index = bbn->GetIndexOf(parent_on_bb);
if (index >= GetFirstHiddenNodeIndex()) {
throbbing_view_ = overflow_button_;
} else if (!overflow_only) {
throbbing_view_ = static_cast<CustomButton*>(child_at(index));
}
} else if (!overflow_only) {
throbbing_view_ = other_bookmarked_button_;
}
if (throbbing_view_)
throbbing_view_->StartThrobbing(std::numeric_limits<int>::max());
}
views::CustomButton* BookmarkBarView::DetermineViewToThrobFromRemove(
const BookmarkNode* parent,
int old_index) {
const BookmarkNode* bbn = model_->bookmark_bar_node();
const BookmarkNode* old_node = parent;
int old_index_on_bb = old_index;
while (old_node && old_node != bbn) {
const BookmarkNode* parent = old_node->parent();
if (parent == bbn) {
old_index_on_bb = bbn->GetIndexOf(old_node);
break;
}
old_node = parent;
}
if (old_node) {
if (old_index_on_bb >= GetFirstHiddenNodeIndex()) {
return overflow_button_;
}
return static_cast<CustomButton*>(child_at(old_index_on_bb));
}
return other_bookmarked_button_;
}
void BookmarkBarView::UpdateColors() {
const ui::ThemeProvider* theme_provider = GetThemeProvider();
if (!theme_provider)
return;
SkColor text_color =
theme_provider->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
for (int i = 0; i < GetBookmarkButtonCount(); ++i)
GetBookmarkButton(i)->SetEnabledColor(text_color);
other_bookmarked_button()->SetEnabledColor(text_color);
if (apps_page_shortcut_->visible())
apps_page_shortcut_->SetEnabledColor(text_color);
}
void BookmarkBarView::UpdateOtherBookmarksVisibility() {
bool has_other_children = !model_->other_node()->empty();
if (has_other_children == other_bookmarked_button_->visible())
return;
other_bookmarked_button_->SetVisible(has_other_children);
UpdateBookmarksSeparatorVisibility();
Layout();
SchedulePaint();
}
void BookmarkBarView::UpdateBookmarksSeparatorVisibility() {
bookmarks_separator_view_->SetVisible(
browser_->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH &&
other_bookmarked_button_->visible());
}
gfx::Size BookmarkBarView::LayoutItems(bool compute_bounds_only) {
gfx::Size prefsize;
if (!parent() && !compute_bounds_only)
return prefsize;
int x = kLeftMargin;
int top_margin = IsDetached() ? kDetachedTopMargin : 0;
int y = top_margin;
int width = View::width() - kRightMargin - kLeftMargin;
int height = chrome::kBookmarkBarHeight - kBottomMargin;
int separator_margin = kSeparatorMargin;
if (IsDetached()) {
double current_state = 1 - size_animation_->GetCurrentValue();
x += static_cast<int>(kNewtabHorizontalPadding * current_state);
y += (View::height() - chrome::kBookmarkBarHeight) / 2;
width -= static_cast<int>(kNewtabHorizontalPadding * current_state);
separator_margin -= static_cast<int>(kSeparatorMargin * current_state);
} else {
y += View::height() - chrome::kBookmarkBarHeight;
}
gfx::Size other_bookmarked_pref = other_bookmarked_button_->visible() ?
other_bookmarked_button_->GetPreferredSize() : gfx::Size();
gfx::Size overflow_pref = overflow_button_->GetPreferredSize();
gfx::Size bookmarks_separator_pref =
bookmarks_separator_view_->GetPreferredSize();
gfx::Size apps_page_shortcut_pref = apps_page_shortcut_->visible() ?
apps_page_shortcut_->GetPreferredSize() : gfx::Size();
int max_x = width - overflow_pref.width() - kButtonPadding -
bookmarks_separator_pref.width();
if (other_bookmarked_button_->visible())
max_x -= other_bookmarked_pref.width() + kButtonPadding;
if (apps_page_shortcut_->visible()) {
if (!compute_bounds_only) {
apps_page_shortcut_->SetBounds(x, y, apps_page_shortcut_pref.width(),
height);
}
x += apps_page_shortcut_pref.width() + kButtonPadding;
}
if (GetBookmarkButtonCount() == 0 && model_ && model_->loaded()) {
gfx::Size pref = instructions_->GetPreferredSize();
if (!compute_bounds_only) {
instructions_->SetBounds(
x + kInstructionsPadding, y,
std::min(static_cast<int>(pref.width()),
max_x - x),
height);
instructions_->SetVisible(true);
}
} else {
if (!compute_bounds_only)
instructions_->SetVisible(false);
for (int i = 0; i < GetBookmarkButtonCount(); ++i) {
views::View* child = child_at(i);
gfx::Size pref = child->GetPreferredSize();
int next_x = x + pref.width() + kButtonPadding;
if (!compute_bounds_only) {
child->SetVisible(next_x < max_x);
child->SetBounds(x, y, pref.width(), height);
}
x = next_x;
}
}
const bool all_visible = (GetBookmarkButtonCount() == 0 ||
child_at(GetBookmarkButtonCount() - 1)->visible());
if (!compute_bounds_only)
x = max_x + kButtonPadding;
else
x += kButtonPadding;
if (!compute_bounds_only) {
overflow_button_->SetBounds(x, y, overflow_pref.width(), height);
overflow_button_->SetVisible(!all_visible);
}
x += overflow_pref.width();
if (bookmarks_separator_view_->visible()) {
if (!compute_bounds_only) {
bookmarks_separator_view_->SetBounds(x,
y - top_margin,
bookmarks_separator_pref.width(),
height + top_margin + kBottomMargin -
separator_margin);
}
x += bookmarks_separator_pref.width();
}
if (other_bookmarked_button_->visible()) {
if (!compute_bounds_only) {
other_bookmarked_button_->SetBounds(x, y, other_bookmarked_pref.width(),
height);
}
x += other_bookmarked_pref.width() + kButtonPadding;
}
if (compute_bounds_only) {
x += kRightMargin;
prefsize.set_width(x);
if (IsDetached()) {
x += static_cast<int>(kNewtabHorizontalPadding *
(1 - size_animation_->GetCurrentValue()));
prefsize.set_height(
chrome::kBookmarkBarHeight +
static_cast<int>(
(chrome::kNTPBookmarkBarHeight - chrome::kBookmarkBarHeight) *
(1 - size_animation_->GetCurrentValue())));
} else {
prefsize.set_height(static_cast<int>(chrome::kBookmarkBarHeight *
size_animation_->GetCurrentValue()));
}
}
return prefsize;
}
void BookmarkBarView::OnAppsPageShortcutVisibilityPrefChanged() {
DCHECK(apps_page_shortcut_);
bool visible = chrome::ShouldShowAppsShortcutInBookmarkBar(
browser_->profile(), browser_->host_desktop_type());
if (apps_page_shortcut_->visible() == visible)
return;
apps_page_shortcut_->SetVisible(visible);
UpdateBookmarksSeparatorVisibility();
Layout();
}