summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 16:44:28 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 16:44:28 +0000
commitd9310e73313623e83708e0ba4e242343ddb71beb (patch)
tree4334cca622bedaa7d6dbb9fd5845ba073e6ea443
parent91043a823d2ffda5d5a1c8f026173777aac35f83 (diff)
downloadchromium_src-d9310e73313623e83708e0ba4e242343ddb71beb.zip
chromium_src-d9310e73313623e83708e0ba4e242343ddb71beb.tar.gz
chromium_src-d9310e73313623e83708e0ba4e242343ddb71beb.tar.bz2
Makes launcher handle overflow.
BUG=101505 TEST=none R=ben@chromium.org Review URL: http://codereview.chromium.org/8334036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108667 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/aura/window.cc5
-rw-r--r--ui/aura/window.h5
-rw-r--r--ui/aura_shell/launcher/launcher_view.cc151
-rw-r--r--ui/aura_shell/launcher/launcher_view.h19
-rwxr-xr-xui/resources/aura/launcher_overflow.pngbin0 -> 1695 bytes
-rw-r--r--ui/resources/ui_resources.grd1
-rw-r--r--views/widget/native_widget_aura.cc2
7 files changed, 171 insertions, 12 deletions
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 45dcf0ea..17f1b50 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -100,12 +100,11 @@ bool Window::IsVisible() const {
}
gfx::Rect Window::GetScreenBounds() const {
- const gfx::Rect local_bounds = bounds();
- gfx::Point origin = local_bounds.origin();
+ gfx::Point origin = bounds().origin();
Window::ConvertPointToWindow(parent_,
aura::Desktop::GetInstance(),
&origin);
- return gfx::Rect(origin, local_bounds.size());
+ return gfx::Rect(origin, bounds().size());
}
void Window::Activate() {
diff --git a/ui/aura/window.h b/ui/aura/window.h
index bab696d..df3e1aa 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -72,6 +72,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
const std::string& name() const { return name_; }
void set_name(const std::string& name) { name_ = name; }
+ const string16 title() const { return title_; }
+ void set_title(const string16& title) { title_ = title; }
+
ui::Layer* layer() { return layer_.get(); }
const ui::Layer* layer() const { return layer_.get(); }
@@ -327,6 +330,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
int id_;
std::string name_;
+ string16 title_;
+
scoped_ptr<EventFilter> event_filter_;
scoped_ptr<LayoutManager> layout_manager_;
diff --git a/ui/aura_shell/launcher/launcher_view.cc b/ui/aura_shell/launcher/launcher_view.cc
index fe4fb79..6d22e5a 100644
--- a/ui/aura_shell/launcher/launcher_view.cc
+++ b/ui/aura_shell/launcher/launcher_view.cc
@@ -13,13 +13,17 @@
#include "ui/aura_shell/launcher/view_model_utils.h"
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_delegate.h"
+#include "ui/aura/window.h"
#include "ui/base/animation/animation.h"
#include "ui/base/animation/throb_animation.h"
+#include "ui/base/models/simple_menu_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/image/image.h"
#include "views/animation/bounds_animator.h"
#include "views/controls/button/image_button.h"
+#include "views/controls/menu/menu_model_adapter.h"
+#include "views/controls/menu/menu_runner.h"
#include "views/widget/widget.h"
using ui::Animation;
@@ -47,6 +51,37 @@ static const float kDimmedButtonOpacity = .8f;
namespace {
+// ui::SimpleMenuModel::Delegate implementation that remembers the id of the
+// menu that was activated.
+class MenuDelegateImpl : public ui::SimpleMenuModel::Delegate {
+ public:
+ MenuDelegateImpl() : activated_command_id_(-1) {}
+
+ int activated_command_id() const { return activated_command_id_; }
+
+ // ui::SimpleMenuModel::Delegate overrides:
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE {
+ return false;
+ }
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
+ return true;
+ }
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) OVERRIDE {
+ return false;
+ }
+ virtual void ExecuteCommand(int command_id) OVERRIDE {
+ activated_command_id_ = command_id;
+ }
+
+ private:
+ // ID of the command passed to ExecuteCommand.
+ int activated_command_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuDelegateImpl);
+};
+
// ImageButton subclass that animates transition changes using the opacity of
// the layer.
class FadeButton : public views::ImageButton {
@@ -195,6 +230,7 @@ LauncherView::LauncherView(LauncherModel* model)
view_model_(new ViewModel),
new_browser_button_(NULL),
show_apps_button_(NULL),
+ overflow_button_(NULL),
dragging_(NULL),
drag_view_(NULL),
drag_offset_(0),
@@ -232,7 +268,15 @@ void LauncherView::Init() {
ConfigureChildView(show_apps_button_);
AddChildView(show_apps_button_);
- LayoutToIdealBounds();
+ overflow_button_ = new FadeButton(this);
+ // TODO: need image for this.
+ overflow_button_->SetImage(
+ views::CustomButton::BS_NORMAL,
+ rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToSkBitmap());
+ ConfigureChildView(overflow_button_);
+ AddChildView(overflow_button_);
+
+ // We'll layout when our bounds change.
}
void LauncherView::LayoutToIdealBounds() {
@@ -244,6 +288,10 @@ void LauncherView::LayoutToIdealBounds() {
}
void LauncherView::CalculateIdealBounds(IdealBounds* bounds) {
+ int available_width = width();
+ if (!available_width)
+ return;
+
// new_browser_button first.
int x = kLeadingInset;
gfx::Size pref = new_browser_button_->GetPreferredSize();
@@ -260,12 +308,45 @@ void LauncherView::CalculateIdealBounds(IdealBounds* bounds) {
x += pref.width() + kHorizontalPadding;
}
- // And the show_apps_button.
- pref = show_apps_button_->GetPreferredSize();
+ // Show apps button and overflow button.
+ bounds->show_apps_bounds.set_size(show_apps_button_->GetPreferredSize());
+ bounds->overflow_bounds.set_size(overflow_button_->GetPreferredSize());
+ int last_visible_index = DetermineLastVisibleIndex(
+ available_width - kLeadingInset - bounds->show_apps_bounds.width() -
+ kHorizontalPadding - bounds->overflow_bounds.width() -
+ kHorizontalPadding);
+ bool show_overflow = (last_visible_index + 1 != view_model_->view_size());
+ if (overflow_button_->IsVisible() != show_overflow) {
+ // Only change visibility of the views if the visibility of the overflow
+ // button changes. Otherwise we'll effect the insertion animation, which
+ // changes the visibility.
+ for (int i = 0; i <= last_visible_index; ++i)
+ view_model_->view_at(i)->SetVisible(true);
+ for (int i = last_visible_index + 1; i < view_model_->view_size(); ++i)
+ view_model_->view_at(i)->SetVisible(false);
+ }
+
+ overflow_button_->SetVisible(show_overflow);
+ if (show_overflow) {
+ DCHECK_NE(0, view_model_->view_size());
+ x = view_model_->ideal_bounds(last_visible_index).right() +
+ kHorizontalPadding;
+ bounds->overflow_bounds.set_x(x);
+ bounds->overflow_bounds.set_y(
+ (kPreferredHeight - bounds->overflow_bounds.height()) / 2);
+ x = bounds->overflow_bounds.right() + kHorizontalPadding;
+ }
// TODO(sky): -8 is a hack, remove when we get better images.
- bounds->show_apps_bounds = gfx::Rect(
- x - 8, (kPreferredHeight - pref.width()) / 2, pref.width(),
- pref.height());
+ bounds->show_apps_bounds.set_x(x - 8);
+ bounds->show_apps_bounds.set_y(
+ (kPreferredHeight - bounds->show_apps_bounds.height()) / 2);
+}
+
+int LauncherView::DetermineLastVisibleIndex(int max_x) {
+ int index = view_model_->view_size() - 1;
+ while (index >= 0 && view_model_->ideal_bounds(index).right() > max_x)
+ index--;
+ return index;
}
void LauncherView::AnimateToIdealBounds() {
@@ -279,6 +360,7 @@ void LauncherView::AnimateToIdealBounds() {
}
bounds_animator_->AnimateViewTo(show_apps_button_,
ideal_bounds.show_apps_bounds);
+ overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds);
}
views::View* LauncherView::CreateViewForItem(const LauncherItem& item) {
@@ -351,6 +433,51 @@ void LauncherView::ConfigureChildView(views::View* view) {
view->layer()->SetFillsBoundsOpaquely(false);
}
+void LauncherView::GetOverflowWindows(std::vector<aura::Window*>* names) {
+ int index = 0;
+ while (index < view_model_->view_size() &&
+ view_model_->view_at(index)->IsVisible()) {
+ index++;
+ }
+ while (index < view_model_->view_size()) {
+ names->push_back(model_->items()[index].window);
+ index++;
+ }
+}
+
+void LauncherView::ShowOverflowMenu() {
+ std::vector<aura::Window*> windows;
+ GetOverflowWindows(&windows);
+ if (windows.empty())
+ return;
+
+ MenuDelegateImpl menu_delegate;
+ ui::SimpleMenuModel menu_model(&menu_delegate);
+ for (size_t i = 0; i < windows.size(); ++i)
+ menu_model.AddItem(static_cast<int>(i), windows[i]->title());
+ views::MenuModelAdapter menu_adapter(&menu_model);
+ overflow_menu_runner_.reset(new views::MenuRunner(menu_adapter.CreateMenu()));
+ gfx::Rect bounds(overflow_button_->size());
+ gfx::Point origin;
+ ConvertPointToScreen(overflow_button_, &origin);
+ if (overflow_menu_runner_->RunMenuAt(GetWidget(), NULL,
+ gfx::Rect(origin, size()), views::MenuItemView::TOPLEFT, 0) ==
+ views::MenuRunner::MENU_DELETED ||
+ menu_delegate.activated_command_id() == -1)
+ return;
+
+ aura::Window* activated_window =
+ windows[menu_delegate.activated_command_id()];
+ LauncherItems::const_iterator window_iter =
+ model_->ItemByWindow(activated_window);
+ if (window_iter == model_->items().end())
+ return; // Window was deleted while menu was up.
+ ShellDelegate* delegate = Shell::GetInstance()->delegate();
+ if (!delegate)
+ return;
+ delegate->LauncherItemClicked(*window_iter);
+}
+
void LauncherView::CancelDrag(views::View* deleted_view) {
if (!drag_view_)
return;
@@ -376,6 +503,10 @@ gfx::Size LauncherView::GetPreferredSize() {
kPreferredHeight);
}
+void LauncherView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ LayoutToIdealBounds();
+}
+
void LauncherView::LauncherItemAdded(int model_index) {
CancelDrag(NULL);
@@ -389,8 +520,10 @@ void LauncherView::LauncherItemAdded(int model_index) {
// hidden, so it visually appears as though we are providing space for
// it. When done we'll fade the view in.
AnimateToIdealBounds();
- bounds_animator_->SetAnimationDelegate(
- view, new StartFadeAnimationDelegate(this, view), true);
+ if (!overflow_button_->IsVisible()) {
+ bounds_animator_->SetAnimationDelegate(
+ view, new StartFadeAnimationDelegate(this, view), true);
+ }
}
void LauncherView::LauncherItemRemoved(int model_index) {
@@ -466,6 +599,8 @@ void LauncherView::ButtonPressed(views::Button* sender,
delegate->CreateNewWindow();
} else if (sender == show_apps_button_) {
delegate->ShowApps();
+ } else if (sender == overflow_button_) {
+ ShowOverflowMenu();
} else {
int view_index = view_model_->GetIndexOfView(sender);
// May be -1 while in the process of animating closed.
diff --git a/ui/aura_shell/launcher/launcher_view.h b/ui/aura_shell/launcher/launcher_view.h
index b5d0320..a2f63b3 100644
--- a/ui/aura_shell/launcher/launcher_view.h
+++ b/ui/aura_shell/launcher/launcher_view.h
@@ -6,6 +6,8 @@
#define UI_AURA_SHELL_LAUNCHER_VIEW_H_
#pragma once
+#include <vector>
+
#include "ui/aura_shell/launcher/launcher_button_host.h"
#include "ui/aura_shell/launcher/launcher_model_observer.h"
#include "views/controls/button/button.h"
@@ -14,6 +16,7 @@
namespace views {
class BoundsAnimator;
class ImageButton;
+class MenuRunner;
}
namespace aura_shell {
@@ -41,6 +44,7 @@ class LauncherView : public views::WidgetDelegateView,
struct IdealBounds {
gfx::Rect new_browser_bounds;
gfx::Rect show_apps_bounds;
+ gfx::Rect overflow_bounds;
};
// Sets the bounds of each view to its ideal bounds.
@@ -51,6 +55,10 @@ class LauncherView : public views::WidgetDelegateView,
// |new_browser_button_| and |show_apps_button_| is set in |bounds|.
void CalculateIdealBounds(IdealBounds* bounds);
+ // Returns the index of the last view whose max x-coordinate is less than
+ // |max_x|. Returns -1 if nothing fits, or there are no views.
+ int DetermineLastVisibleIndex(int max_x);
+
// Animates the bounds of each view to its ideal bounds.
void AnimateToIdealBounds();
@@ -73,8 +81,15 @@ class LauncherView : public views::WidgetDelegateView,
// Common setup done for all children.
void ConfigureChildView(views::View* view);
+ // Returns the windows whose icon is not show because it doesn't fit.
+ void GetOverflowWindows(std::vector<aura::Window*>* names);
+
+ // Shows the overflow menu.
+ void ShowOverflowMenu();
+
// Overridden from views::View:
virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
// Overridden from LauncherModelObserver:
virtual void LauncherItemAdded(int model_index) OVERRIDE;
@@ -107,6 +122,8 @@ class LauncherView : public views::WidgetDelegateView,
views::ImageButton* show_apps_button_;
+ views::ImageButton* overflow_button_;
+
// Are we dragging? This is only set if the mouse is dragged far enough to
// trigger a drag.
bool dragging_;
@@ -121,6 +138,8 @@ class LauncherView : public views::WidgetDelegateView,
// Index |drag_view_| was initially at.
int start_drag_index_;
+ scoped_ptr<views::MenuRunner> overflow_menu_runner_;
+
DISALLOW_COPY_AND_ASSIGN(LauncherView);
};
diff --git a/ui/resources/aura/launcher_overflow.png b/ui/resources/aura/launcher_overflow.png
new file mode 100755
index 0000000..5535278
--- /dev/null
+++ b/ui/resources/aura/launcher_overflow.png
Binary files differ
diff --git a/ui/resources/ui_resources.grd b/ui/resources/ui_resources.grd
index c9670c2..4f294d2 100644
--- a/ui/resources/ui_resources.grd
+++ b/ui/resources/ui_resources.grd
@@ -131,6 +131,7 @@
<!-- Images only used by Aura. -->
<if expr="pp_ifdef('use_aura')">
<include name="IDR_AURA_LAUNCHER_ICON_CHROME" file="aura/chromium-32.png" type="BINDATA" />
+ <include name="IDR_AURA_LAUNCHER_OVERFLOW" file="aura/launcher_overflow.png" type="BINDATA" />
<include name="IDR_AURA_LAUNCHER_TABBED_BROWSER_1" file="aura/browser_instance_1.png" type="BINDATA" />
<include name="IDR_AURA_LAUNCHER_TABBED_BROWSER_2" file="aura/browser_instance_2.png" type="BINDATA" />
<include name="IDR_AURA_LAUNCHER_TABBED_BROWSER_3" file="aura/browser_instance_3.png" type="BINDATA" />
diff --git a/views/widget/native_widget_aura.cc b/views/widget/native_widget_aura.cc
index 53d4216..cb4eeba 100644
--- a/views/widget/native_widget_aura.cc
+++ b/views/widget/native_widget_aura.cc
@@ -286,7 +286,7 @@ void NativeWidgetAura::GetWindowPlacement(
}
void NativeWidgetAura::SetWindowTitle(const string16& title) {
- // Aura doesn't have native window frames.
+ window_->set_title(title);
}
void NativeWidgetAura::SetWindowIcons(const SkBitmap& window_icon,