summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 01:17:26 +0000
committerfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 01:17:26 +0000
commit44ec9b3b965335d661a144e11894da3cea999bf3 (patch)
tree549ce1740dda62e2014a75a7f3a6cff430dde45e /chrome
parent993e6ea820a8b71c8f7767822de3b66bd2bb3c6f (diff)
downloadchromium_src-44ec9b3b965335d661a144e11894da3cea999bf3.zip
chromium_src-44ec9b3b965335d661a144e11894da3cea999bf3.tar.gz
chromium_src-44ec9b3b965335d661a144e11894da3cea999bf3.tar.bz2
Support reordering of Browser Actions within the container. Currently does not support dragging to/from the chevron menu.
Also fixed two bugs in the same code: - the container would be 0 width if a value for it hasn't been saved (part of bug 32101). - the default icon was not used when a tab specific icon was not found (bug 34317). BUG=http://crbug.com/26990, http://crbug.com/32101, http://crbug.com/34317 TEST=In both LTR and RTL locale, try reordering the browser actions and make sure to test dragging to the ends with and without a chevron visible. Install Send to Gmail extension and make sure it has an icon while in the overflow menu. Review URL: http://codereview.chromium.org/549224 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37922 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.cc24
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.h9
-rw-r--r--chrome/browser/extensions/extension_toolbar_model.h6
-rw-r--r--chrome/browser/views/browser_actions_container.cc210
-rw-r--r--chrome/browser/views/browser_actions_container.h43
-rw-r--r--chrome/browser/views/extensions/browser_action_drag_data.cc93
-rw-r--r--chrome/browser/views/extensions/browser_action_drag_data.h62
-rw-r--r--chrome/browser/views/extensions/browser_action_drag_data_unittest.cc54
-rw-r--r--chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc6
-rwxr-xr-xchrome/chrome_browser.gypi4
-rwxr-xr-xchrome/chrome_tests.gypi2
11 files changed, 465 insertions, 48 deletions
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.cc b/chrome/browser/bookmarks/bookmark_drag_data.cc
index a22f60c..e1897b2 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.cc
+++ b/chrome/browser/bookmarks/bookmark_drag_data.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -190,16 +190,8 @@ bool BookmarkDragData::Read(const OSExchangeData& data) {
#endif
void BookmarkDragData::WriteToPickle(Profile* profile, Pickle* pickle) const {
-#if defined(WCHAR_T_IS_UTF16)
- pickle->WriteWString(
- profile ? profile->GetPath().ToWStringHack() : std::wstring());
-#elif defined(WCHAR_T_IS_UTF32)
- pickle->WriteString(
- profile ? profile->GetPath().value() : std::string());
-#else
- NOTIMPLEMENTED() << "Impossible encoding situation!";
-#endif
-
+ FilePath path = profile ? profile->GetPath() : FilePath();
+ FilePath::WriteStringTypeToPickle(pickle, path.value());
pickle->WriteSize(elements.size());
for (size_t i = 0; i < elements.size(); ++i)
@@ -209,14 +201,8 @@ void BookmarkDragData::WriteToPickle(Profile* profile, Pickle* pickle) const {
bool BookmarkDragData::ReadFromPickle(Pickle* pickle) {
void* data_iterator = NULL;
size_t element_count;
-#if defined(WCHAR_T_IS_UTF16)
- if (pickle->ReadWString(&data_iterator, &profile_path_) &&
-#elif defined(WCHAR_T_IS_UTF32)
- if (pickle->ReadString(&data_iterator, &profile_path_) &&
-#else
- NOTIMPLEMENTED() << "Impossible encoding situation!";
- if (false &&
-#endif
+ if (FilePath::ReadStringTypeFromPickle(pickle, &data_iterator,
+ &profile_path_) &&
pickle->ReadSize(&data_iterator, &element_count)) {
std::vector<Element> tmp_elements;
tmp_elements.resize(element_count);
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.h b/chrome/browser/bookmarks/bookmark_drag_data.h
index 2078bfa..32bf60d 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.h
+++ b/chrome/browser/bookmarks/bookmark_drag_data.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/file_path.h"
#include "base/string16.h"
#include "googleurl/src/gurl.h"
@@ -141,11 +142,7 @@ struct BookmarkDragData {
private:
// Path of the profile we originated from.
-#if defined(WCHAR_T_IS_UTF16)
- std::wstring profile_path_;
-#elif defined(WCHAR_T_IS_UTF32)
- std::string profile_path_;
-#endif
+ FilePath::StringType profile_path_;
};
#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_DATA_H_
diff --git a/chrome/browser/extensions/extension_toolbar_model.h b/chrome/browser/extensions/extension_toolbar_model.h
index 5b6a8a4..3889f3d 100644
--- a/chrome/browser/extensions/extension_toolbar_model.h
+++ b/chrome/browser/extensions/extension_toolbar_model.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -38,6 +38,10 @@ class ExtensionToolbarModel : public NotificationObserver {
void RemoveObserver(Observer* observer);
void MoveBrowserAction(Extension* extension, int index);
+ size_t size() const {
+ return toolitems_.size();
+ }
+
ExtensionList::iterator begin() {
return toolitems_.begin();
}
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc
index 7d5686c..3eb1115 100644
--- a/chrome/browser/views/browser_actions_container.cc
+++ b/chrome/browser/views/browser_actions_container.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/detachable_toolbar_view.h"
+#include "chrome/browser/views/extensions/browser_action_drag_data.h"
#include "chrome/browser/views/extensions/browser_action_overflow_menu_controller.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "chrome/browser/views/toolbar_view.h"
@@ -40,6 +41,7 @@ static const int kButtonSize = 29;
// The padding between the browser actions and the OmniBox/page menu.
static const int kHorizontalPadding = 4;
+static const int kHorizontalPaddingRtl = 8;
// The padding between browser action buttons. Visually, the actual number of
// empty (non-drawing) pixels is this value + 2 when adjacent browser icons
@@ -66,6 +68,16 @@ static const int kChevronRightMargin = 4;
// Extra hit-area for the resize gripper.
static const int kExtraResizeArea = 4;
+// Width of the drop indicator.
+static const int kDropIndicatorWidth = 2;
+
+// Color of the drop indicator.
+static const SkColor kDropIndicatorColor = SK_ColorBLACK;
+
+// The x offset for the drop indicator (how much we shift it by).
+static const int kDropIndicatorOffsetLtr = 3;
+static const int kDropIndicatorOffsetRtl = 9;
+
////////////////////////////////////////////////////////////////////////////////
// BrowserActionButton
@@ -258,6 +270,7 @@ BrowserActionView::BrowserActionView(Extension* extension,
BrowserActionsContainer* panel)
: panel_(panel) {
button_ = new BrowserActionButton(extension, panel);
+ button_->SetDragController(panel_);
AddChildView(button_);
button_->UpdateState();
}
@@ -291,6 +304,7 @@ BrowserActionsContainer::BrowserActionsContainer(
suppress_chevron_(false),
resize_amount_(0),
animation_target_size_(0),
+ drop_indicator_position_(-1),
ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR);
@@ -321,6 +335,12 @@ BrowserActionsContainer::BrowserActionsContainer(
int predefined_width =
profile_->GetPrefs()->GetInteger(prefs::kBrowserActionContainerWidth);
+ if (predefined_width == 0) {
+ // The width will never be 0 (due to container min size restriction)
+ // except when no width has been saved. So, in that case ask the model
+ // how many icons we'll show and set initial size to that.
+ predefined_width = IconCountToWidth(model_->size());
+ }
container_size_ = gfx::Size(predefined_width, kButtonSize);
}
@@ -368,6 +388,16 @@ void BrowserActionsContainer::CloseOverflowMenu() {
overflow_menu_->CancelMenu();
}
+void BrowserActionsContainer::CreateBrowserActionViews() {
+ DCHECK(browser_action_views_.empty());
+ for (ExtensionList::iterator iter = model_->begin();
+ iter != model_->end(); ++iter) {
+ BrowserActionView* view = new BrowserActionView(*iter, this);
+ browser_action_views_.push_back(view);
+ AddChildView(view);
+ }
+}
+
void BrowserActionsContainer::DeleteBrowserActionViews() {
if (!browser_action_views_.empty()) {
for (size_t i = 0; i < browser_action_views_.size(); ++i)
@@ -473,7 +503,7 @@ gfx::Size BrowserActionsContainer::GetPreferredSize() {
// other words: ContainerMinSize() < width() - resize < ClampTo(MAX).
int width = std::max(ContainerMinSize(),
container_size_.width() - resize_amount_);
- int max_width = ClampToNearestIconCount(-1); // -1 gives max width.
+ int max_width = ClampToNearestIconCount(-1, false); // -1 gives max width.
width = std::min(width, max_width);
return gfx::Size(width, kButtonSize);
@@ -498,7 +528,7 @@ void BrowserActionsContainer::Layout() {
x += sz.width();
}
- x += kHorizontalPadding;
+ x += UILayoutIsRightToLeft() ? kHorizontalPaddingRtl : kHorizontalPadding;
// Calculate if all icons fit without showing the chevron. We need to know
// this beforehand, because showing the chevron will decrease the space that
@@ -549,6 +579,21 @@ void BrowserActionsContainer::Paint(gfx::Canvas* canvas) {
DetachableToolbarView::kEdgeDividerColor,
DetachableToolbarView::kMiddleDividerColor,
GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR));
+
+ // The two-pixel width drop indicator.
+ if (drop_indicator_position_ > -1) {
+ x = drop_indicator_position_;
+ int y = kDividerVerticalPadding;
+ gfx::Rect indicator_bounds(x - kDropIndicatorWidth / 2,
+ y,
+ kDropIndicatorWidth,
+ height() - (2 * kDividerVerticalPadding));
+
+ // TODO(sky/glen): make me pretty!
+ canvas->FillRectInt(kDropIndicatorColor, indicator_bounds.x(),
+ indicator_bounds.y(), indicator_bounds.width(),
+ indicator_bounds.height());
+ }
}
void BrowserActionsContainer::ViewHierarchyChanged(bool is_add,
@@ -563,13 +608,107 @@ void BrowserActionsContainer::ViewHierarchyChanged(bool is_add,
// We do this here instead of in the constructor because AddBrowserAction
// calls Layout on the Toolbar, which needs this object to be constructed
// before its Layout function is called.
- for (ExtensionList::iterator iter = model_->begin();
- iter != model_->end(); ++iter) {
- BrowserActionView* view = new BrowserActionView(*iter, this);
- browser_action_views_.push_back(view);
- AddChildView(view);
+ CreateBrowserActionViews();
+ }
+}
+
+bool BrowserActionsContainer::GetDropFormats(
+ int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) {
+ custom_formats->insert(BrowserActionDragData::GetBrowserActionCustomFormat());
+ return true;
+}
+
+bool BrowserActionsContainer::AreDropTypesRequired() {
+ return true;
+}
+
+bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) {
+ BrowserActionDragData drop_data;
+ if (!drop_data.Read(data))
+ return false;
+ return drop_data.IsFromProfile(profile_);
+}
+
+void BrowserActionsContainer::OnDragEntered(
+ const views::DropTargetEvent& event) {
+}
+
+int BrowserActionsContainer::OnDragUpdated(
+ const views::DropTargetEvent& event) {
+ // Modifying the x value before clamping affects how far you have to drag to
+ // get the drop indicator to shift to another position. Modifying after
+ // clamping affects where the drop indicator is drawn.
+
+ // We add half a button size so that when you drag a button to the right and
+ // you are half-way dragging across a button the drop indicator moves from the
+ // left of that button to the right of that button.
+ int x = event.x() + (kButtonSize / 2) + (2 * kBrowserActionButtonPadding);
+ if (chevron_->IsVisible())
+ x += chevron_->bounds().width();
+ x = ClampToNearestIconCount(x, false);
+
+ if (!UILayoutIsRightToLeft() && chevron_->IsVisible()) {
+ // The clamping function includes the chevron width. In LTR locales, the
+ // chevron is on the right and we never want to account for its width. In
+ // RTL it is on the left and we always want to count the width.
+ x -= chevron_->width();
+ }
+
+ // Clamping gives us a value where the next button will be drawn, but we want
+ // to subtract the padding (and then some) to make it appear in-between the
+ // buttons.
+ drop_indicator_position_ = x - kBrowserActionButtonPadding -
+ (UILayoutIsRightToLeft() ? kDropIndicatorOffsetRtl :
+ kDropIndicatorOffsetLtr);
+
+ SchedulePaint();
+ return DragDropTypes::DRAG_MOVE;
+}
+
+void BrowserActionsContainer::OnDragExited() {
+ drop_indicator_position_ = -1;
+ SchedulePaint();
+}
+
+int BrowserActionsContainer::OnPerformDrop(
+ const views::DropTargetEvent& event) {
+ BrowserActionDragData data;
+ if (!data.Read(event.GetData()))
+ return DragDropTypes::DRAG_NONE;
+
+ // Make sure we have the same view as we started with.
+ DCHECK(browser_action_views_[data.index()]->button()->extension()->id() ==
+ data.id());
+
+ Extension* dragging =
+ browser_action_views_[data.index()]->button()->extension();
+
+ int target_x = drop_indicator_position_;
+
+ size_t i = 0;
+ for (; i < browser_action_views_.size(); ++i) {
+ int view_x =
+ browser_action_views_[i]->GetBounds(APPLY_MIRRORING_TRANSFORMATION).x();
+ if (!browser_action_views_[i]->IsVisible() ||
+ (UILayoutIsRightToLeft() ? view_x < target_x : view_x >= target_x)) {
+ // We have reached the end of the visible icons or found one that has a
+ // higher x position than the drop point.
+ break;
}
}
+
+ // |i| now points to the item to the right of the drop indicator*, which is
+ // correct when dragging an icon to the left. When dragging to the right,
+ // however, we want the icon being dragged to get the index of the item to
+ // the left of the drop indicator, so we subtract one.
+ // * Well, it can also point to the end, but not when dragging to the left. :)
+ if (i > data.index())
+ --i;
+
+ model_->MoveBrowserAction(dragging, i);
+
+ OnDragExited(); // Perform clean up after dragging.
+ return DragDropTypes::DRAG_MOVE;
}
void BrowserActionsContainer::Observe(NotificationType type,
@@ -639,7 +778,31 @@ void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) {
}
}
-int BrowserActionsContainer::ClampToNearestIconCount(int pixelWidth) const {
+void BrowserActionsContainer::WriteDragData(
+ View* sender, int press_x, int press_y, OSExchangeData* data) {
+ DCHECK(data);
+
+ for (size_t i = 0; i < browser_action_views_.size(); ++i) {
+ if (browser_action_views_[i]->button() == sender) {
+ BrowserActionDragData drag_data(
+ browser_action_views_[i]->button()->extension()->id(), i);
+ drag_data.Write(profile_, data);
+ break;
+ }
+ }
+}
+
+int BrowserActionsContainer::GetDragOperations(View* sender, int x, int y) {
+ return DragDropTypes::DRAG_MOVE;
+}
+
+bool BrowserActionsContainer::CanStartDrag(
+ View* sender, int press_x, int press_y, int x, int y) {
+ return true;
+}
+
+int BrowserActionsContainer::ClampToNearestIconCount(
+ int pixelWidth, bool allow_shrink_to_minimum) const {
// Calculate the width of one icon.
int icon_width = (kButtonSize + kBrowserActionButtonPadding);
@@ -660,19 +823,19 @@ int BrowserActionsContainer::ClampToNearestIconCount(int pixelWidth) const {
// Count the number of icons that fit within that area.
icon_count = icon_area / icon_width;
- // No use allowing more than what we have.
- if (icon_count > browser_action_views_.size())
- icon_count = browser_action_views_.size();
- else if (icon_count == 0)
+ if (icon_count == 0 && allow_shrink_to_minimum) {
extras = ContainerMinSize(); // Allow very narrow width if no icons.
+ } else if (icon_count > browser_action_views_.size()) {
+ // No use allowing more than what we have.
+ icon_count = browser_action_views_.size();
+ }
} else {
// A negative |pixels| count indicates caller wants to know the max width
// that fits all icons;
icon_count = browser_action_views_.size();
}
- int returning = extras + (icon_count * icon_width);
- return returning;
+ return extras + (icon_count * icon_width);
}
void BrowserActionsContainer::BrowserActionAdded(Extension* extension,
@@ -745,7 +908,7 @@ void BrowserActionsContainer::BrowserActionRemoved(Extension* extension) {
// because we want the container to stay the same size (clamping will take
// care of shrinking the container if there aren't enough icons to show).
animation_target_size_ =
- ClampToNearestIconCount(IconCountToWidth(visible_actions));
+ ClampToNearestIconCount(IconCountToWidth(visible_actions), true);
// Animate!
resize_animation_->Reset();
@@ -756,10 +919,21 @@ void BrowserActionsContainer::BrowserActionRemoved(Extension* extension) {
}
}
+void BrowserActionsContainer::BrowserActionMoved(Extension* extension,
+ int index) {
+ DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size()));
+
+ DeleteBrowserActionViews();
+ CreateBrowserActionViews();
+ Layout();
+}
+
int BrowserActionsContainer::WidthOfNonIconArea() const {
int chevron_size = (chevron_->IsVisible()) ?
chevron_->GetPreferredSize().width() : 0;
- return resize_gripper_->GetPreferredSize().width() + kHorizontalPadding +
+ int padding = UILayoutIsRightToLeft() ? kHorizontalPaddingRtl :
+ kHorizontalPadding;
+ return resize_gripper_->GetPreferredSize().width() + padding +
chevron_size + kChevronRightMargin + kDividerHorizontalMargin;
}
@@ -798,14 +972,14 @@ void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) {
// Clamp lower limit to 0 and upper limit to the amount that allows enough
// room for all icons to show.
int new_width = std::max(0, container_size_.width() - resize_amount);
- int max_width = ClampToNearestIconCount(-1);
+ int max_width = ClampToNearestIconCount(-1, false);
new_width = std::min(new_width, max_width);
// Up until now we've only been modifying the resize_amount, but now it is
// time to set the container size to the size we have resized to, but then
// animate to the nearest icon count size (or down to min size if no icon).
container_size_.set_width(new_width);
- animation_target_size_ = ClampToNearestIconCount(new_width);
+ animation_target_size_ = ClampToNearestIconCount(new_width, true);
resize_animation_->Reset();
resize_animation_->SetTweenType(SlideAnimation::EASE_OUT);
resize_animation_->Show();
diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h
index 9adb6e7..5f28823 100644
--- a/chrome/browser/views/browser_actions_container.h
+++ b/chrome/browser/views/browser_actions_container.h
@@ -19,8 +19,8 @@
#include "views/controls/resize_gripper.h"
#include "views/view.h"
-class BrowserActionsContainer;
class BrowserActionOverflowMenuController;
+class BrowserActionsContainer;
class Extension;
class ExtensionAction;
class ExtensionPopup;
@@ -49,6 +49,9 @@ class BrowserActionButton : public views::MenuButton,
// Called to update the display to match the browser action's state.
void UpdateState();
+ // Returns the default icon, if any.
+ const SkBitmap& default_icon() const { return default_icon_; }
+
// Overridden from views::View. Return a 0-inset so the icon can draw all the
// way to the edge of the view if it wants.
virtual gfx::Insets GetInsets() const;
@@ -137,6 +140,8 @@ class BrowserActionView : public views::View {
// The button this view contains.
BrowserActionButton* button_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserActionView);
};
////////////////////////////////////////////////////////////////////////////////
@@ -217,6 +222,7 @@ class BrowserActionsContainer
public NotificationObserver,
public BrowserBubble::Delegate,
public views::ViewMenuDelegate,
+ public views::DragController,
public views::ResizeGripper::ResizeGripperDelegate,
public AnimationDelegate,
public ExtensionToolbarModel::Observer {
@@ -249,6 +255,9 @@ class BrowserActionsContainer
// Update the views to reflect the state of the browser action icons.
void RefreshBrowserActionViews();
+ // Sets up the browser action view vector.
+ void CreateBrowserActionViews();
+
// Delete all browser action views.
void DeleteBrowserActionViews();
@@ -265,6 +274,14 @@ class BrowserActionsContainer
virtual void ViewHierarchyChanged(bool is_add,
views::View* parent,
views::View* child);
+ virtual bool GetDropFormats(
+ int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats);
+ virtual bool AreDropTypesRequired();
+ virtual bool CanDrop(const OSExchangeData& data);
+ virtual void OnDragEntered(const views::DropTargetEvent& event);
+ virtual int OnDragUpdated(const views::DropTargetEvent& event);
+ virtual void OnDragExited();
+ virtual int OnPerformDrop(const views::DropTargetEvent& event);
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
@@ -281,6 +298,18 @@ class BrowserActionsContainer
// Overridden from views::ViewMenuDelegate:
virtual void RunMenu(View* source, const gfx::Point& pt);
+ // Overridden from views::DragController:
+ virtual void WriteDragData(View* sender,
+ int press_x,
+ int press_y,
+ OSExchangeData* data);
+ virtual int GetDragOperations(View* sender, int x, int y);
+ virtual bool CanStartDrag(View* sender,
+ int press_x,
+ int press_y,
+ int x,
+ int y);
+
// Overridden from ResizeGripper::ResizeGripperDelegate:
virtual void OnResize(int resize_amount, bool done_resizing);
@@ -302,14 +331,19 @@ class BrowserActionsContainer
// ExtensionToolbarModel::Observer implementation.
virtual void BrowserActionAdded(Extension* extension, int index);
virtual void BrowserActionRemoved(Extension* extension);
+ virtual void BrowserActionMoved(Extension* extension, int index);
// Closes the overflow menu if open.
void CloseOverflowMenu();
// Takes a width in pixels, calculates how many icons fit within that space
// (up to the maximum number of icons in our vector) and shaves off the
- // excess pixels.
- int ClampToNearestIconCount(int pixels) const;
+ // excess pixels. |allow_shrink_to_minimum| specifies whether this function
+ // clamps the size down further (down to ContainerMinSize()) if there is not
+ // room for even one icon. When determining how large the container should be
+ // this should be |true|. When determining where to place items, such as the
+ // drop indicator, this should be |false|.
+ int ClampToNearestIconCount(int pixels, bool allow_shrink_to_minimum) const;
// Calculates the width of the container area NOT used to show the icons (the
// controls to the left and to the right of the icons).
@@ -374,6 +408,9 @@ class BrowserActionsContainer
// are done animating.
int animation_target_size_;
+ // The x position for where to draw the drop indicator. -1 if no indicator.
+ int drop_indicator_position_;
+
ScopedRunnableMethodFactory<BrowserActionsContainer> task_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserActionsContainer);
diff --git a/chrome/browser/views/extensions/browser_action_drag_data.cc b/chrome/browser/views/extensions/browser_action_drag_data.cc
new file mode 100644
index 0000000..103738f
--- /dev/null
+++ b/chrome/browser/views/extensions/browser_action_drag_data.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/extensions/browser_action_drag_data.h"
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/pickle.h"
+#include "base/string_util.h"
+#include "chrome/browser/profile.h"
+
+const char* BrowserActionDragData::kClipboardFormatString =
+ "chromium/x-browser-actions";
+
+BrowserActionDragData::BrowserActionDragData()
+ : index_(-1) {
+}
+
+BrowserActionDragData::BrowserActionDragData(
+ const std::string& id, int index)
+ : id_(id),
+ index_(index) {
+}
+
+bool BrowserActionDragData::IsFromProfile(Profile* profile) const {
+ // An empty path means the data is not associated with any profile.
+ return (!profile_path_.empty() &&
+ profile_path_ == profile->GetPath().value());
+}
+
+#if defined(TOOLKIT_VIEWS)
+void BrowserActionDragData::Write(
+ Profile* profile, OSExchangeData* data) const {
+ DCHECK(data);
+ Pickle data_pickle;
+ WriteToPickle(profile, &data_pickle);
+ data->SetPickledData(GetBrowserActionCustomFormat(), data_pickle);
+}
+
+bool BrowserActionDragData::Read(const OSExchangeData& data) {
+ if (!data.HasCustomFormat(GetBrowserActionCustomFormat()))
+ return false;
+
+ Pickle drag_data_pickle;
+ if (!data.GetPickledData(GetBrowserActionCustomFormat(), &drag_data_pickle))
+ return false;
+
+ if (!ReadFromPickle(&drag_data_pickle))
+ return false;
+
+ return true;
+}
+
+// static
+OSExchangeData::CustomFormat
+ BrowserActionDragData::GetBrowserActionCustomFormat() {
+ static OSExchangeData::CustomFormat format;
+ static bool format_valid = false;
+
+ if (!format_valid) {
+ format_valid = true;
+ format = OSExchangeData::RegisterCustomFormat(
+ BrowserActionDragData::kClipboardFormatString);
+ }
+ return format;
+}
+#endif
+
+void BrowserActionDragData::WriteToPickle(
+ Profile* profile, Pickle* pickle) const {
+ FilePath::WriteStringTypeToPickle(pickle, profile->GetPath().value());
+ pickle->WriteString(id_);
+ pickle->WriteInt(index_);
+}
+
+bool BrowserActionDragData::ReadFromPickle(Pickle* pickle) {
+ void* data_iterator = NULL;
+ if (!FilePath::ReadStringTypeFromPickle(pickle, &data_iterator,
+ &profile_path_)) {
+ return false;
+ }
+
+ if (!pickle->ReadString(&data_iterator, &id_))
+ return false;
+
+ int index;
+ if (!pickle->ReadInt(&data_iterator, &index))
+ return false;
+
+ index_ = index;
+ return true;
+}
diff --git a/chrome/browser/views/extensions/browser_action_drag_data.h b/chrome/browser/views/extensions/browser_action_drag_data.h
new file mode 100644
index 0000000..8d5d514b
--- /dev/null
+++ b/chrome/browser/views/extensions/browser_action_drag_data.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
+#define CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "app/os_exchange_data.h"
+#endif
+
+class BrowserActionButton;
+class FilePath;
+class Pickle;
+class Profile;
+
+class BrowserActionDragData {
+ public:
+ BrowserActionDragData();
+ BrowserActionDragData(const std::string& id, int index);
+
+ const std::string& id() const { return id_; }
+
+ size_t index() const { return index_; }
+
+ // Returns true if this data is from the specified profile.
+ bool IsFromProfile(Profile* profile) const;
+
+#if defined(TOOLKIT_VIEWS)
+ void Write(Profile* profile, OSExchangeData* data) const;
+
+ // Restores this data from the clipboard, returning true on success.
+ bool Read(const OSExchangeData& data);
+
+ // Returns the Custom Format this class supports (for Browser Actions).
+ static OSExchangeData::CustomFormat GetBrowserActionCustomFormat();
+#endif
+
+ private:
+ void WriteToPickle(Profile* profile, Pickle* pickle) const;
+ bool ReadFromPickle(Pickle* pickle);
+
+ // Path of the profile we originated from.
+ FilePath::StringType profile_path_;
+
+ // The id of the view being dragged.
+ std::string id_;
+
+ // The index of the view being dragged.
+ size_t index_;
+
+ // The MIME type for the clipboard format for BrowserActionDragData.
+ static const char* kClipboardFormatString;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserActionDragData);
+};
+
+#endif // CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_DRAG_DATA_H_
diff --git a/chrome/browser/views/extensions/browser_action_drag_data_unittest.cc b/chrome/browser/views/extensions/browser_action_drag_data_unittest.cc
new file mode 100644
index 0000000..7f54b0c
--- /dev/null
+++ b/chrome/browser/views/extensions/browser_action_drag_data_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/os_exchange_data.h"
+#include "app/os_exchange_data_provider_win.h"
+#include "base/pickle.h"
+#include "chrome/browser/views/extensions/browser_action_drag_data.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+OSExchangeData::Provider* CloneProvider(const OSExchangeData& data) {
+ return new OSExchangeDataProviderWin(
+ OSExchangeDataProviderWin::GetIDataObject(data));
+}
+
+} // namespace
+
+typedef testing::Test BrowserActionDragDataTest;
+
+TEST_F(BrowserActionDragDataTest, ArbitraryFormat) {
+ TestingProfile profile;
+ profile.SetID(L"id");
+
+ OSExchangeData data;
+ data.SetURL(GURL("http://www.google.com"), L"Title");
+
+ // We only support our format, so this should not succeed.
+ BrowserActionDragData drag_data;
+ EXPECT_FALSE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+}
+
+TEST_F(BrowserActionDragDataTest, BrowserActionDragDataFormat) {
+ TestingProfile profile;
+ profile.SetID(L"id");
+
+ const std::string extension_id = "42";
+ Pickle pickle;
+ pickle.WriteWString(profile.GetPath().ToWStringHack());
+ pickle.WriteString(extension_id);
+ pickle.WriteInt(42);
+
+ OSExchangeData data;
+ data.SetPickledData(BrowserActionDragData::GetBrowserActionCustomFormat(),
+ pickle);
+
+ BrowserActionDragData drag_data;
+ EXPECT_TRUE(drag_data.Read(OSExchangeData(CloneProvider(data))));
+ ASSERT_TRUE(drag_data.IsFromProfile(profile.GetOriginalProfile()));
+ ASSERT_STREQ(extension_id.c_str(), drag_data.id().c_str());
+ ASSERT_EQ(42, drag_data.index());
+}
diff --git a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc
index 66b209c..6cb56d8 100644
--- a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc
+++ b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc
@@ -29,10 +29,14 @@ BrowserActionOverflowMenuController::BrowserActionOverflowMenuController(
size_t command_id = 0;
for (size_t i = start_index; i < views_->size(); ++i) {
BrowserActionView* view = (*views_)[i];
+ SkBitmap icon =
+ view->button()->extension()->browser_action()->GetIcon(tab_id);
+ if (icon.isNull())
+ icon = view->button()->default_icon();
menu_->AppendMenuItemWithIcon(
command_id,
UTF8ToWide(view->button()->extension()->name()),
- view->button()->extension()->browser_action()->GetIcon(tab_id));
+ icon);
++command_id;
}
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d8bbd9a..d6146c8 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1786,6 +1786,8 @@
'browser/views/edit_search_engine_dialog.h',
'browser/views/event_utils.cc',
'browser/views/event_utils.h',
+ 'browser/views/extensions/browser_action_drag_data.cc',
+ 'browser/views/extensions/browser_action_drag_data.h',
'browser/views/extensions/browser_action_overflow_menu_controller.cc',
'browser/views/extensions/browser_action_overflow_menu_controller.h',
'browser/views/extensions/extension_action_context_menu.cc',
@@ -2358,6 +2360,8 @@
['include', '^browser/views/dropdown_bar_view.h'],
['include', '^browser/views/event_utils.cc'],
['include', '^browser/views/event_utils.h'],
+ ['include', '^browser/views/extensions/browser_action_drag_data.cc'],
+ ['include', '^browser/views/extensions/browser_action_drag_data.h'],
['include', '^browser/views/extensions/browser_action_overflow_menu_controller.cc'],
['include', '^browser/views/extensions/browser_action_overflow_menu_controller.h'],
['include', '^browser/views/extensions/extension_action_context_menu.cc'],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 76b02dc..d7d338f 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -812,6 +812,7 @@
'browser/theme_resources_util_unittest.cc',
'browser/views/bookmark_context_menu_test.cc',
'browser/views/bookmark_editor_view_unittest.cc',
+ 'browser/views/extensions/browser_action_drag_data_unittest.cc',
'browser/visitedlink_unittest.cc',
'browser/webdata/web_data_service_unittest.cc',
'browser/webdata/web_database_unittest.cc',
@@ -1031,6 +1032,7 @@
'browser/safe_browsing/safe_browsing_blocking_page_unittest.cc',
'browser/search_engines/template_url_scraper_unittest.cc',
'browser/views/bookmark_editor_view_unittest.cc',
+ 'browser/views/extensions/browser_action_drag_data_unittest.cc',
'browser/views/find_bar_host_unittest.cc',
'browser/views/keyword_editor_view_unittest.cc',
'common/chrome_plugin_unittest.cc',