diff options
Diffstat (limited to 'ui')
23 files changed, 485 insertions, 282 deletions
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp index 596909d..a4c46a1 100644 --- a/ui/aura/aura.gyp +++ b/ui/aura/aura.gyp @@ -49,6 +49,7 @@ 'window.cc', 'window.h', 'window_delegate.h', + 'window_observer.h', 'window_types.h', ], }, diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 2014f25..1357a89 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -13,6 +13,7 @@ #include "ui/aura/event_filter.h" #include "ui/aura/layout_manager.h" #include "ui/aura/window_delegate.h" +#include "ui/aura/window_observer.h" #include "ui/aura/window_types.h" #include "ui/base/animation/multi_animation.h" #include "ui/gfx/canvas_skia.h" @@ -205,11 +206,13 @@ void Window::AddChild(Window* child) { child->parent_ = this; layer_->Add(child->layer_.get()); children_.push_back(child); + FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child)); } void Window::RemoveChild(Window* child) { Windows::iterator i = std::find(children_.begin(), children_.end(), child); DCHECK(i != children_.end()); + FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child)); child->parent_ = NULL; layer_->Remove(child->layer_.get()); children_.erase(i); @@ -259,6 +262,14 @@ bool Window::OnKeyEvent(KeyEvent* event) { return IsVisible() && delegate_->OnKeyEvent(event); } +void Window::AddObserver(WindowObserver* observer) { + observers_.AddObserver(observer); +} + +void Window::RemoveObserver(WindowObserver* observer) { + observers_.RemoveObserver(observer); +} + bool Window::HitTest(const gfx::Point& point) { gfx::Rect local_bounds(gfx::Point(), bounds().size()); // TODO(beng): hittest masks. diff --git a/ui/aura/window.h b/ui/aura/window.h index 2e13521..139c269 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" #include "base/string16.h" #include "ui/base/ui_base_types.h" #include "ui/aura/aura_export.h" @@ -34,6 +35,7 @@ class LayoutManager; class MouseEvent; class ToplevelWindowContainer; class WindowDelegate; +class WindowObserver; namespace internal { class FocusManager; @@ -119,6 +121,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // the desktop's window. void SetParent(Window* parent); Window* parent() { return parent_; } + const Window* parent() const { return parent_; } // Move the specified child of this Window to the front of the z-order. // TODO(beng): this is (obviously) feeble. @@ -158,6 +161,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate { WindowDelegate* delegate() { return delegate_; } + // Add/remove observer. + void AddObserver(WindowObserver* observer); + void RemoveObserver(WindowObserver* observer); + // When set to true, this Window will stop propagation of all events targeted // at Windows below it in the z-order, but only if this Window has children. // This is used to implement lock-screen type functionality where we do not @@ -267,6 +274,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // provided this window has children. See set_stops_event_propagation(). bool stops_event_propagation_; + ObserverList<WindowObserver> observers_; + DISALLOW_COPY_AND_ASSIGN(Window); }; diff --git a/ui/aura/window_observer.h b/ui/aura/window_observer.h new file mode 100644 index 0000000..fd71a5f --- /dev/null +++ b/ui/aura/window_observer.h @@ -0,0 +1,29 @@ +// Copyright (c) 2011 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 UI_AURA_WINDOW_OBSERVER_H_ +#define UI_AURA_WINDOW_OBSERVER_H_ +#pragma once + +#include "ui/aura/aura_export.h" + +namespace aura { + +class Window; + +class AURA_EXPORT WindowObserver { + public: + // Invoked when the Window |new_window| has been added. + virtual void OnWindowAdded(Window* new_window) {} + + // Invoked prior to removing |window|. + virtual void OnWillRemoveWindow(Window* window) {} + + protected: + virtual ~WindowObserver() {} +}; + +} // namespace aura + +#endif // UI_AURA_WINDOW_OBSERVER_H_ diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index cbd2e95..ba6813c 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -2,8 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/aura/window.h" + #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/desktop.h" #include "ui/aura/desktop_observer.h" @@ -15,6 +18,7 @@ #include "ui/aura/test/test_desktop_delegate.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window_delegate.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/canvas_skia.h" #include "ui/gfx/compositor/layer.h" #include "ui/base/keycodes/keyboard_codes.h" @@ -761,14 +765,68 @@ TEST_F(WindowTest, Deactivate) { EXPECT_EQ(w2.get(), parent->children()[1]); } -class ObserverTest : public WindowTest, - public DesktopObserver { +class WindowObserverTest : public WindowTest, + public WindowObserver { + public: + WindowObserverTest() : added_count_(0), removed_count_(0) {} + + virtual ~WindowObserverTest() {} + + // Returns a description of the WindowObserver methods that have been invoked. + std::string WindowObserverCountStateAndClear() { + std::string result( + base::StringPrintf("added=%d removed=%d", + added_count_, removed_count_)); + added_count_ = removed_count_ = 0; + return result; + } + + private: + virtual void OnWindowAdded(Window* new_window) OVERRIDE { + added_count_++; + } + + virtual void OnWillRemoveWindow(Window* window) OVERRIDE { + removed_count_++; + } + + int added_count_; + int removed_count_; + + DISALLOW_COPY_AND_ASSIGN(WindowObserverTest); +}; + +// Various assertions for WindowObserver. +TEST_F(WindowObserverTest, WindowObserver) { + scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL)); + w1->AddObserver(this); + + // Create a new window as a child of w1, our observer should be notified. + scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get())); + EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear()); + + // Delete w2, which should result in the remove notification. + w2.reset(); + EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear()); + + // Create a window that isn't parented to w1, we shouldn't get any + // notification. + scoped_ptr<Window> w3(CreateTestWindowWithId(3, NULL)); + EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear()); + + // Similarly destroying w3 shouldn't notify us either. + w3.reset(); + EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear()); + w1->RemoveObserver(this); +} + +class DesktopObserverTest : public WindowTest, + public DesktopObserver { public: - ObserverTest() - : active_(NULL) { + DesktopObserverTest() : active_(NULL) { } - virtual ~ObserverTest() {} + virtual ~DesktopObserverTest() {} Window* active() const { return active_; } @@ -793,10 +851,10 @@ class ObserverTest : public WindowTest, Window* active_; - DISALLOW_COPY_AND_ASSIGN(ObserverTest); + DISALLOW_COPY_AND_ASSIGN(DesktopObserverTest); }; -TEST_F(ObserverTest, WindowActivationObserve) { +TEST_F(DesktopObserverTest, WindowActivationObserve) { scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL)); scoped_ptr<Window> w2(CreateTestWindowWithId(2, NULL)); scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get())); diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp index ec42c1a..c009523 100644 --- a/ui/aura_shell/aura_shell.gyp +++ b/ui/aura_shell/aura_shell.gyp @@ -37,12 +37,12 @@ 'desktop_background_view.h', 'desktop_layout_manager.cc', 'desktop_layout_manager.h', - 'desktop_window.cc', - 'launcher/launcher_button.cc', - 'launcher/launcher_button.h', + 'launcher/launcher.cc', + 'launcher/launcher.h', 'launcher/launcher_model.cc', 'launcher/launcher_model.h', 'launcher/launcher_model_observer.h', + 'launcher/launcher_types.h', 'launcher/launcher_view.cc', 'launcher/launcher_view.h', 'shell.cc', diff --git a/ui/aura_shell/desktop_layout_manager.cc b/ui/aura_shell/desktop_layout_manager.cc index 01366fd..8e0dc0f 100644 --- a/ui/aura_shell/desktop_layout_manager.cc +++ b/ui/aura_shell/desktop_layout_manager.cc @@ -38,8 +38,7 @@ void DesktopLayoutManager::OnWindowResized() { gfx::Rect launcher_bounds = launcher_widget_->GetWindowScreenBounds(); launcher_widget_->SetBounds( - gfx::Rect(owner_->bounds().width() / 2 - launcher_bounds.width() / 2, - owner_->bounds().bottom() - launcher_bounds.height(), + gfx::Rect(0, owner_->bounds().bottom() - launcher_bounds.height(), launcher_bounds.width(), launcher_bounds.height())); diff --git a/ui/aura_shell/desktop_window.cc b/ui/aura_shell/desktop_window.cc deleted file mode 100644 index fb9860b..0000000 --- a/ui/aura_shell/desktop_window.cc +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2011 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 "ui/aura/desktop.h" -#include "ui/aura/toplevel_window_container.h" -#include "ui/aura/window.h" -#include "ui/aura_shell/desktop_layout_manager.h" -#include "ui/aura_shell/launcher/launcher_model.h" -#include "ui/aura_shell/shell.h" -#include "ui/aura_shell/shell_factory.h" -#include "ui/aura_shell/shell_window_ids.h" -#include "views/widget/widget.h" - -namespace aura_shell { - -// Creates each of the special window containers that holds windows of various -// types in the shell UI. They are added to |containers| from back to front in -// the z-index. -void CreateSpecialContainers(aura::Window::Windows* containers) { - aura::Window* background_container = new aura::Window(NULL); - background_container->set_id( - internal::kShellWindowId_DesktopBackgroundContainer); - containers->push_back(background_container); - - aura::Window* default_container = new aura::ToplevelWindowContainer; - default_container->set_id(internal::kShellWindowId_DefaultContainer); - containers->push_back(default_container); - - aura::Window* always_on_top_container = new aura::ToplevelWindowContainer; - always_on_top_container->set_id( - internal::kShellWindowId_AlwaysOnTopContainer); - containers->push_back(always_on_top_container); - - aura::Window* launcher_container = new aura::Window(NULL); - launcher_container->set_id(internal::kShellWindowId_LauncherContainer); - containers->push_back(launcher_container); - - aura::Window* lock_container = new aura::Window(NULL); - lock_container->set_stops_event_propagation(true); - lock_container->set_id(internal::kShellWindowId_LockScreenContainer); - containers->push_back(lock_container); - - aura::Window* status_container = new aura::Window(NULL); - status_container->set_id(internal::kShellWindowId_StatusContainer); - containers->push_back(status_container); -} - -void InitDesktopWindow() { - aura::Window::Windows containers; - CreateSpecialContainers(&containers); - aura::Window::Windows::const_iterator i; - for (i = containers.begin(); i != containers.end(); ++i) { - (*i)->Init(); - aura::Desktop::GetInstance()->window()->AddChild(*i); - (*i)->Show(); - } - - aura::Window* root_window = aura::Desktop::GetInstance()->window(); - internal::DesktopLayoutManager* desktop_layout = - new internal::DesktopLayoutManager(root_window); - root_window->SetLayoutManager(desktop_layout); - - Shell* shell = Shell::GetInstance(); - views::Widget* desktop_background = internal::CreateDesktopBackground(); - shell->GetContainer( - internal::kShellWindowId_DesktopBackgroundContainer)->AddChild( - desktop_background->GetNativeView()); - - // TODO: this leaks. - views::Widget* launcher = internal::CreateLauncher(new LauncherModel); - shell->GetContainer(internal::kShellWindowId_LauncherContainer)->AddChild( - launcher->GetNativeView()); - - views::Widget* status_area = internal::CreateStatusArea(); - shell->GetContainer(internal::kShellWindowId_StatusContainer)->AddChild( - status_area->GetNativeView()); - - desktop_layout->set_background_widget(desktop_background); - desktop_layout->set_launcher_widget(launcher); - desktop_layout->set_status_area_widget(status_area); -} - -} // namespace aura_shell - diff --git a/ui/aura_shell/examples/aura_shell_main.cc b/ui/aura_shell/examples/aura_shell_main.cc index 0c06b79..1d02144 100644 --- a/ui/aura_shell/examples/aura_shell_main.cc +++ b/ui/aura_shell/examples/aura_shell_main.cc @@ -9,6 +9,7 @@ #include "base/message_loop.h" #include "ui/aura/desktop.h" #include "ui/aura_shell/examples/toplevel_window.h" +#include "ui/aura_shell/launcher/launcher_types.h" #include "ui/aura_shell/shell.h" #include "ui/aura_shell/shell_delegate.h" #include "ui/aura_shell/shell_factory.h" @@ -32,6 +33,15 @@ class ShellDelegateImpl : public aura_shell::ShellDelegate { virtual void ShowApps() OVERRIDE { NOTIMPLEMENTED(); } + + virtual void LauncherItemClicked( + const aura_shell::LauncherItem& item) OVERRIDE { + item.window->Activate(); + } + + virtual bool ConfigureLauncherItem(aura_shell::LauncherItem* item) OVERRIDE { + return true; // Makes the entry show up in the launcher. + } }; } // namesapce diff --git a/ui/aura_shell/launcher/launcher.cc b/ui/aura_shell/launcher/launcher.cc new file mode 100644 index 0000000..5cb6a13 --- /dev/null +++ b/ui/aura_shell/launcher/launcher.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 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 "ui/aura_shell/launcher/launcher.h" + +#include "ui/aura/toplevel_window_container.h" +#include "ui/aura_shell/launcher/launcher_model.h" +#include "ui/aura_shell/launcher/launcher_view.h" +#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/shell_delegate.h" +#include "ui/aura_shell/shell_window_ids.h" +#include "ui/gfx/compositor/layer.h" +#include "views/widget/widget.h" + +namespace aura_shell { + +Launcher::Launcher(aura::ToplevelWindowContainer* window_container) + : widget_(NULL), + window_container_(window_container) { + window_container->AddObserver(this); + + model_.reset(new LauncherModel); + + widget_ = new views::Widget; + views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); + params.parent = Shell::GetInstance()->GetContainer( + aura_shell::internal::kShellWindowId_LauncherContainer); + internal::LauncherView* launcher_view = + new internal::LauncherView(model_.get()); + launcher_view->Init(); + params.delegate = launcher_view; + widget_->Init(params); + widget_->GetNativeWindow()->layer()->SetOpacity(0.8f); + gfx::Size pref = static_cast<views::View*>(launcher_view)->GetPreferredSize(); + widget_->SetBounds(gfx::Rect(0, 0, pref.width(), pref.height())); + widget_->SetContentsView(launcher_view); + widget_->Show(); + widget_->GetNativeView()->set_name("LauncherView"); +} + +Launcher::~Launcher() { + window_container_->RemoveObserver(this); +} + +void Launcher::OnWindowAdded(aura::Window* new_window) { + ShellDelegate* delegate = Shell::GetInstance()->delegate(); + if (!delegate) + return; + LauncherItem item; + item.window = new_window; + if (!delegate->ConfigureLauncherItem(&item)) + return; // The delegate doesn't want to show this item in the launcher. + model_->Add(model_->items().size(), item); +} + +void Launcher::OnWillRemoveWindow(aura::Window* window) { + const LauncherItems& items(model_->items()); + for (LauncherItems::const_iterator i = items.begin(); i != items.end(); ++i) { + if (i->window == window) { + model_->RemoveItemAt(i - items.begin()); + break; + } + } +} + +} // namespace aura_shell diff --git a/ui/aura_shell/launcher/launcher.h b/ui/aura_shell/launcher/launcher.h new file mode 100644 index 0000000..0dda152 --- /dev/null +++ b/ui/aura_shell/launcher/launcher.h @@ -0,0 +1,51 @@ +// Copyright (c) 2011 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 UI_AURA_SHELL_LAUNCHER_LAUNCHER_H_ +#define UI_AURA_SHELL_LAUNCHER_LAUNCHER_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "ui/aura/window_observer.h" +#include "ui/aura_shell/aura_shell_export.h" + +namespace aura { +class ToplevelWindowContainer; +} + +namespace views { +class Widget; +} + +namespace aura_shell { + +class LauncherModel; + +class AURA_SHELL_EXPORT Launcher : public aura::WindowObserver { + public: + explicit Launcher(aura::ToplevelWindowContainer* window_container); + ~Launcher(); + + LauncherModel* model() { return model_.get(); } + views::Widget* widget() { return widget_; } + + private: + // WindowObserver overrides: + virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE; + virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE; + + scoped_ptr<LauncherModel> model_; + + // Widget hosting the view. + views::Widget* widget_; + + aura::ToplevelWindowContainer* window_container_; + + DISALLOW_COPY_AND_ASSIGN(Launcher); +}; + +} // namespace aura_shell + +#endif // UI_AURA_SHELL_LAUNCHER_LAUNCHER_H_ diff --git a/ui/aura_shell/launcher/launcher_model.cc b/ui/aura_shell/launcher/launcher_model.cc index 58ab9d3..43a6d00 100644 --- a/ui/aura_shell/launcher/launcher_model.cc +++ b/ui/aura_shell/launcher/launcher_model.cc @@ -5,36 +5,22 @@ #include "ui/aura_shell/launcher/launcher_model.h" #include "ui/aura_shell/launcher/launcher_model_observer.h" -#include "views/view.h" namespace aura_shell { -LauncherModel::LauncherModel() : selected_index_(-1) { +LauncherModel::LauncherModel() { } LauncherModel::~LauncherModel() { - for (Items::iterator i = items_.begin(); i != items_.end(); ++i) { - delete i->view; - i->view = NULL; - } } -void LauncherModel::AddItem(views::View* view, int index, bool draggable) { +void LauncherModel::Add(int index, const LauncherItem& item) { DCHECK(index >= 0 && index <= item_count()); - Item item; - item.view = view; - item.draggable = draggable; items_.insert(items_.begin() + index, item); FOR_EACH_OBSERVER(LauncherModelObserver, observers_, LauncherItemAdded(index)); } -void LauncherModel::RemoveItem(views::View* view) { - int index = IndexOfItemByView(view); - if (index != -1) - RemoveItemAt(index); -} - void LauncherModel::RemoveItemAt(int index) { DCHECK(index >= 0 && index < item_count()); items_.erase(items_.begin() + index); @@ -42,22 +28,21 @@ void LauncherModel::RemoveItemAt(int index) { LauncherItemRemoved(index)); } -void LauncherModel::SetSelectedIndex(int index) { - if (index == selected_index_) - return; - DCHECK(selected_index_ == -1 || - (selected_index_ >= 0 && selected_index_ < item_count())); - selected_index_ = index; +void LauncherModel::SetTabbedImages(int index, + const LauncherTabbedImages& images) { + DCHECK(index >= 0 && index < item_count()); + DCHECK_EQ(TYPE_TABBED, items_[index].type); + items_[index].tab_images = images; FOR_EACH_OBSERVER(LauncherModelObserver, observers_, - LauncherSelectionChanged()); + LauncherItemImagesChanged(index)); } -int LauncherModel::IndexOfItemByView(views::View* view) { - for (Items::const_iterator i = items_.begin(); i != items_.end(); ++i) { - if (i->view == view) - return i - items_.begin(); - } - return -1; +void LauncherModel::SetAppImage(int index, const SkBitmap& image) { + DCHECK(index >= 0 && index < item_count()); + DCHECK_EQ(TYPE_APP, items_[index].type); + items_[index].app_image = image; + FOR_EACH_OBSERVER(LauncherModelObserver, observers_, + LauncherItemImagesChanged(index)); } void LauncherModel::AddObserver(LauncherModelObserver* observer) { diff --git a/ui/aura_shell/launcher/launcher_model.h b/ui/aura_shell/launcher/launcher_model.h index 9aac41c..242129e 100644 --- a/ui/aura_shell/launcher/launcher_model.h +++ b/ui/aura_shell/launcher/launcher_model.h @@ -10,6 +10,7 @@ #include "base/observer_list.h" #include "ui/aura_shell/aura_shell_export.h" +#include "ui/aura_shell/launcher/launcher_types.h" namespace views { class View; @@ -25,40 +26,24 @@ class AURA_SHELL_EXPORT LauncherModel { LauncherModel(); ~LauncherModel(); - // Adds a new view to the model. The model takes ownership of the view. - void AddItem(views::View* view, int index, bool draggable); - - // Removes an item by the view. - void RemoveItem(views::View* view); + // Adds a new item to the model. + void Add(int index, const LauncherItem& item); // Removes the item at |index|. void RemoveItemAt(int index); - // The selected index; -1 if nothing is selected. - void SetSelectedIndex(int index); - int selected_index() const { return selected_index_; } + // Changes the images of the specified item. + void SetTabbedImages(int index, const LauncherTabbedImages& images); + void SetAppImage(int index, const SkBitmap& image); - // Returns the index of |view|, or -1 if view isn't contained in this model. - int IndexOfItemByView(views::View* view); + const LauncherItems& items() const { return items_; } int item_count() const { return static_cast<int>(items_.size()); } - views::View* view_at(int index) { return items_[index].view; } - bool is_draggable(int index) { return items_[index].draggable; } void AddObserver(LauncherModelObserver* observer); void RemoveObserver(LauncherModelObserver* observer); private: - struct Item { - Item() : view(NULL), draggable(false) {} - - // The view, we own this. - views::View* view; - bool draggable; - }; - typedef std::vector<Item> Items; - - Items items_; - int selected_index_; + LauncherItems items_; ObserverList<LauncherModelObserver> observers_; DISALLOW_COPY_AND_ASSIGN(LauncherModel); diff --git a/ui/aura_shell/launcher/launcher_model_observer.h b/ui/aura_shell/launcher/launcher_model_observer.h index 6372392..5732400 100644 --- a/ui/aura_shell/launcher/launcher_model_observer.h +++ b/ui/aura_shell/launcher/launcher_model_observer.h @@ -19,8 +19,8 @@ class AURA_SHELL_EXPORT LauncherModelObserver { // at. virtual void LauncherItemRemoved(int index) = 0; - // Invoked when the selection changes. - virtual void LauncherSelectionChanged() = 0; + // Invoked when the images of an item change. + virtual void LauncherItemImagesChanged(int index) = 0; protected: virtual ~LauncherModelObserver() {} diff --git a/ui/aura_shell/launcher/launcher_model_unittest.cc b/ui/aura_shell/launcher/launcher_model_unittest.cc index c55decc..0c10e13 100644 --- a/ui/aura_shell/launcher/launcher_model_unittest.cc +++ b/ui/aura_shell/launcher/launcher_model_unittest.cc @@ -7,9 +7,6 @@ #include "base/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura_shell/launcher/launcher_model_observer.h" -#include "views/view.h" - -using views::View; namespace aura_shell { @@ -21,15 +18,16 @@ class TestLauncherModelObserver : public LauncherModelObserver { TestLauncherModelObserver() : added_count_(0), removed_count_(0), - selection_changed_count_(0) { + images_changed_count_(0) { } // Returns a string description of the changes that have occurred since this // was last invoked. Resets state to initial state. std::string StateStringAndClear() { - std::string result(base::StringPrintf("added=%d removed=%d s_changed=%d", - added_count_, removed_count_, selection_changed_count_)); - added_count_ = removed_count_ = selection_changed_count_ = 0; + std::string result( + base::StringPrintf("added=%d removed=%d images_changed=%d", + added_count_, removed_count_, images_changed_count_)); + added_count_ = removed_count_ = images_changed_count_ = 0; return result; } @@ -40,14 +38,14 @@ class TestLauncherModelObserver : public LauncherModelObserver { virtual void LauncherItemRemoved(int index) OVERRIDE { removed_count_++; } - virtual void LauncherSelectionChanged() OVERRIDE { - selection_changed_count_++; + virtual void LauncherItemImagesChanged(int index) OVERRIDE { + images_changed_count_++; } - private: + private: int added_count_; int removed_count_; - int selection_changed_count_; + int images_changed_count_; DISALLOW_COPY_AND_ASSIGN(TestLauncherModelObserver); }; @@ -59,29 +57,32 @@ TEST(TestLauncher, BasicAssertions) { LauncherModel model; // Add an item. model.AddObserver(&observer); - EXPECT_EQ(-1, model.selected_index()); - View* view = new View; - model.AddItem(view, 0, true); + LauncherItem item; + model.Add(0, item); EXPECT_EQ(1, model.item_count()); - EXPECT_EQ(view, model.view_at(0)); - EXPECT_EQ(true, model.is_draggable(0)); - EXPECT_EQ(-1, model.selected_index()); - EXPECT_EQ("added=1 removed=0 s_changed=0", observer.StateStringAndClear()); - - EXPECT_EQ(0, model.IndexOfItemByView(view)); - EXPECT_EQ(-1, model.IndexOfItemByView(NULL)); + EXPECT_EQ("added=1 removed=0 images_changed=0", + observer.StateStringAndClear()); - // Change the selection. - model.SetSelectedIndex(0); - EXPECT_EQ("added=0 removed=0 s_changed=1", observer.StateStringAndClear()); + // Change a tabbed image. + model.SetTabbedImages(0, LauncherTabbedImages()); + EXPECT_EQ("added=0 removed=0 images_changed=1", + observer.StateStringAndClear()); // Remove the item. model.RemoveItemAt(0); - delete view; // We now own the view. - view = NULL; EXPECT_EQ(0, model.item_count()); - EXPECT_EQ(0, model.selected_index()); - EXPECT_EQ("added=0 removed=1 s_changed=0", observer.StateStringAndClear()); + EXPECT_EQ("added=0 removed=1 images_changed=0", + observer.StateStringAndClear()); + + // Add an app item. + item.type = TYPE_APP; + model.Add(0, item); + observer.StateStringAndClear(); + + // Change an app image. + model.SetAppImage(0, SkBitmap()); + EXPECT_EQ("added=0 removed=0 images_changed=1", + observer.StateStringAndClear()); } } // namespace aura_shell diff --git a/ui/aura_shell/launcher/launcher_types.h b/ui/aura_shell/launcher/launcher_types.h new file mode 100644 index 0000000..b435fa0 --- /dev/null +++ b/ui/aura_shell/launcher/launcher_types.h @@ -0,0 +1,67 @@ +// Copyright (c) 2011 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 UI_AURA_SHELL_LAUNCHER_ENTRY_TYPES_H_ +#define UI_AURA_SHELL_LAUNCHER_ENTRY_TYPES_H_ +#pragma once + +#include <vector> + +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/aura_shell/aura_shell_export.h" + +namespace aura { +class Window; +} + +namespace aura_shell { + +// Type the LauncherItem represents. +enum AURA_SHELL_EXPORT LauncherItemType { + TYPE_TABBED, + TYPE_APP +}; + +// Represents an image in a launcher item of type TYPE_APP. +struct AURA_SHELL_EXPORT LauncherTabbedImage { + LauncherTabbedImage() : user_data(NULL) {} + LauncherTabbedImage(const SkBitmap& image, void* user_data) + : image(image), + user_data(user_data) { + } + + // The image to show. + SkBitmap image; + + // Used to identify the image. + void* user_data; +}; + +typedef std::vector<LauncherTabbedImage> LauncherTabbedImages; + +struct AURA_SHELL_EXPORT LauncherItem { + LauncherItem() : type(TYPE_TABBED), window(NULL), user_data(NULL) {} + LauncherItem(LauncherItemType type, + aura::Window* window, + void* user_data) + : type(type), + window(window), + user_data(user_data) {} + + LauncherItemType type; + aura::Window* window; + void* user_data; + + // Image to display in the launcher if the item is of type TYPE_APP. + SkBitmap app_image; + + // Image to display in the launcher if the item is of type TYPE_TABBED. + LauncherTabbedImages tab_images; +}; + +typedef std::vector<LauncherItem> LauncherItems; + +} // namespace aura_shell + +#endif // UI_AURA_SHELL_LAUNCHER_ENTRY_TYPES_H_ diff --git a/ui/aura_shell/launcher/launcher_view.cc b/ui/aura_shell/launcher/launcher_view.cc index 0900e3c..22b44a5 100644 --- a/ui/aura_shell/launcher/launcher_view.cc +++ b/ui/aura_shell/launcher/launcher_view.cc @@ -5,13 +5,13 @@ #include "ui/aura_shell/launcher/launcher_view.h" #include "base/utf_string_conversions.h" -#include "ui/aura/desktop.h" -#include "ui/aura_shell/aura_shell_export.h" +#include "grit/ui_resources.h" #include "ui/aura_shell/launcher/launcher_model.h" #include "ui/aura_shell/shell.h" -#include "ui/aura_shell/shell_window_ids.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/compositor/layer.h" +#include "ui/aura_shell/shell_delegate.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" +#include "views/controls/button/image_button.h" #include "views/widget/widget.h" using views::View; @@ -26,27 +26,56 @@ static const int kHorizontalPadding = 12; // added/removed. static const int kPreferredHeight = 64; -LauncherView::LauncherView() : model_(NULL) { +LauncherView::LauncherView(LauncherModel* model) + : model_(model), + new_browser_button_(NULL), + show_apps_button_(NULL) { + DCHECK(model_); } LauncherView::~LauncherView() { - // The model owns the views. - RemoveAllChildViews(false); - model_->RemoveObserver(this); } -void LauncherView::Init(LauncherModel* model) { - DCHECK(!model_); - model_ = model; +void LauncherView::Init() { model_->AddObserver(this); - for (int i = 0; i < model_->item_count(); ++i) - AddChildView(model_->view_at(i)); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + new_browser_button_ = new views::ImageButton(this); + new_browser_button_->SetImage( + views::CustomButton::BS_NORMAL, + rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_CHROME).ToSkBitmap()); + AddChildView(new_browser_button_); + + const LauncherItems& items(model_->items()); + for (LauncherItems::const_iterator i = items.begin(); i != items.end(); ++i) + AddChildView(CreateViewForItem(*i)); + + show_apps_button_ = new views::ImageButton(this); + show_apps_button_->SetImage( + views::CustomButton::BS_NORMAL, + rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST).ToSkBitmap()); + AddChildView(show_apps_button_); +} + +views::View* LauncherView::CreateViewForItem(const LauncherItem& item) { + // TODO: need to support images. + views::ImageButton* button = new views::ImageButton(this); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + button->SetImage( + views::CustomButton::BS_NORMAL, + rb.GetImageNamed(IDR_AURA_LAUNCHER_TABBED_BROWSER).ToSkBitmap()); + return button; +} + +void LauncherView::Resize() { + int y = GetWidget()->GetClientAreaScreenBounds().y(); + gfx::Size pref(GetPreferredSize()); + GetWidget()->SetBounds(gfx::Rect(0, y, pref.width(), pref.height())); } void LauncherView::Layout() { // TODO: need to deal with overflow. - int x = 0; + int x = kHorizontalPadding; for (int i = 0; i < child_count(); ++i) { View* child = child_at(i); if (child->IsVisible()) { @@ -59,7 +88,7 @@ void LauncherView::Layout() { } gfx::Size LauncherView::GetPreferredSize() { - int x = 0; + int x = kHorizontalPadding; for (int i = 0; i < child_count(); ++i) { View* child = child_at(i); if (child->IsVisible()) { @@ -67,41 +96,40 @@ gfx::Size LauncherView::GetPreferredSize() { x += pref_size.width() + kHorizontalPadding; } } - if (x > 0) - x -= kHorizontalPadding; return gfx::Size(x, kPreferredHeight); } void LauncherView::LauncherItemAdded(int index) { // TODO: to support animations is going to require coordinate conversions. - AddChildViewAt(model_->view_at(index), index); + AddChildViewAt(CreateViewForItem(model_->items()[index]), index + 1); + Resize(); } void LauncherView::LauncherItemRemoved(int index) { // TODO: to support animations is going to require coordinate conversions. - RemoveChildView(child_at(index)); + RemoveChildView(child_at(index + 1)); + Resize(); } -void LauncherView::LauncherSelectionChanged() { +void LauncherView::LauncherItemImagesChanged(int index) { + // TODO: implement me. } -views::Widget* CreateLauncher(LauncherModel* model) { - views::Widget* launcher_widget = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); - params.bounds = gfx::Rect(0, 0, 300, kPreferredHeight); - params.parent = Shell::GetInstance()->GetContainer( - aura_shell::internal::kShellWindowId_LauncherContainer); - LauncherView* launcher_view = new LauncherView; - launcher_view->Init(model); - params.delegate = launcher_view; - launcher_widget->Init(params); - launcher_widget->GetNativeWindow()->layer()->SetOpacity(0.8f); - gfx::Size pref = static_cast<views::View*>(launcher_view)->GetPreferredSize(); - launcher_widget->SetBounds(gfx::Rect(0, 0, pref.width(), pref.height())); - launcher_widget->SetContentsView(launcher_view); - launcher_widget->Show(); - launcher_widget->GetNativeView()->set_name("LauncherView"); - return launcher_widget; +void LauncherView::ButtonPressed(views::Button* sender, + const views::Event& event) { + ShellDelegate* delegate = Shell::GetInstance()->delegate(); + if (!delegate) + return; + if (sender == new_browser_button_) { + delegate->CreateNewWindow(); + } else if (sender == show_apps_button_) { + delegate->ShowApps(); + } else { + int index = GetIndexOf(sender); + DCHECK_NE(-1, index); + // TODO: animations will require coordinate transforms. + delegate->LauncherItemClicked(model_->items()[index - 1]); + } } } // namespace internal diff --git a/ui/aura_shell/launcher/launcher_view.h b/ui/aura_shell/launcher/launcher_view.h index d7b6e79..65b2696 100644 --- a/ui/aura_shell/launcher/launcher_view.h +++ b/ui/aura_shell/launcher/launcher_view.h @@ -7,26 +7,36 @@ #pragma once #include "ui/aura_shell/launcher/launcher_model_observer.h" +#include "views/controls/button/button.h" #include "views/widget/widget_delegate.h" +namespace views { +class ImageButton; +} + namespace aura_shell { +struct LauncherItem; class LauncherModel; namespace internal { -class LauncherButton; - class LauncherView : public views::WidgetDelegateView, - public LauncherModelObserver { + public LauncherModelObserver, + public views::ButtonListener { public: - LauncherView(); + explicit LauncherView(LauncherModel* model); virtual ~LauncherView(); - // Populates this LauncherView from the contents of |model|. - void Init(LauncherModel* model); + void Init(); private: + // Creates the view used to represent |item|. + views::View* CreateViewForItem(const LauncherItem& item); + + // Resizes the widget to fit the view. + void Resize(); + // Overridden from views::View: virtual void Layout() OVERRIDE; virtual gfx::Size GetPreferredSize() OVERRIDE; @@ -34,11 +44,19 @@ class LauncherView : public views::WidgetDelegateView, // Overridden from LauncherModelObserver: virtual void LauncherItemAdded(int index) OVERRIDE; virtual void LauncherItemRemoved(int index) OVERRIDE; - virtual void LauncherSelectionChanged() OVERRIDE; + virtual void LauncherItemImagesChanged(int index) OVERRIDE; - // The model, we don't own it. + // Overriden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) OVERRIDE; + + // The model; owned by Launcher. LauncherModel* model_; + views::ImageButton* new_browser_button_; + + views::ImageButton* show_apps_button_; + DISALLOW_COPY_AND_ASSIGN(LauncherView); }; diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc index afcd051..ea00f25 100644 --- a/ui/aura_shell/shell.cc +++ b/ui/aura_shell/shell.cc @@ -5,25 +5,22 @@ #include "ui/aura_shell/shell.h" #include "base/bind.h" -#include "grit/ui_resources.h" #include "ui/aura/desktop.h" #include "ui/aura/toplevel_window_container.h" #include "ui/aura/window.h" #include "ui/aura/window_types.h" #include "ui/aura_shell/desktop_layout_manager.h" -#include "ui/aura_shell/launcher/launcher_model.h" +#include "ui/aura_shell/launcher/launcher.h" #include "ui/aura_shell/shell_delegate.h" #include "ui/aura_shell/shell_factory.h" #include "ui/aura_shell/shell_window_ids.h" -#include "ui/base/resource/resource_bundle.h" #include "ui/gfx/compositor/layer.h" -#include "ui/gfx/image/image.h" -#include "views/controls/button/image_button.h" #include "views/widget/widget.h" namespace aura_shell { namespace { + // Creates each of the special window containers that holds windows of various // types in the shell UI. They are added to |containers| from back to front in // the z-index. @@ -123,9 +120,7 @@ Shell* Shell::instance_ = NULL; // Shell, public: Shell::Shell() - : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), - new_browser_button_(NULL), - show_apps_button_(NULL) { + : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { aura::Desktop::GetInstance()->SetDelegate(this); } @@ -142,8 +137,6 @@ Shell* Shell::GetInstance() { } void Shell::Init() { - InitLauncherModel(); - aura::Window::Windows containers; CreateSpecialContainers(&containers); aura::Window::Windows::const_iterator i; @@ -159,8 +152,11 @@ void Shell::Init() { root_window->SetLayoutManager(desktop_layout); desktop_layout->set_background_widget(internal::CreateDesktopBackground()); - desktop_layout->set_launcher_widget( - internal::CreateLauncher(launcher_model_.get())); + aura::ToplevelWindowContainer* toplevel_container = + GetContainer(internal::kShellWindowId_DefaultContainer)-> + AsToplevelWindowContainer(); + launcher_.reset(new Launcher(toplevel_container)); + desktop_layout->set_launcher_widget(launcher_->widget()); desktop_layout->set_status_area_widget(internal::CreateStatusArea()); } @@ -222,23 +218,6 @@ void Shell::RestoreTiledWindows() { to_restore_.clear(); } -void Shell::InitLauncherModel() { - launcher_model_.reset(new LauncherModel); - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - new_browser_button_ = new views::ImageButton(this); - new_browser_button_->SetImage( - views::CustomButton::BS_NORMAL, - rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_CHROME).ToSkBitmap()); - launcher_model_->AddItem(new_browser_button_, 0, false); - - show_apps_button_ = new views::ImageButton(this); - show_apps_button_->SetImage( - views::CustomButton::BS_NORMAL, - rb.GetImageNamed(IDR_AURA_LAUNCHER_ICON_APPLIST).ToSkBitmap()); - launcher_model_->AddItem(show_apps_button_, 1, false); -} - //////////////////////////////////////////////////////////////////////////////// // Shell, aura::DesktopDelegate implementation: @@ -267,12 +246,4 @@ aura::Window* Shell::GetTopmostWindowToActivate(aura::Window* ignore) const { return container->GetTopmostWindowToActivate(ignore); } -void Shell::ButtonPressed(views::Button* sender, - const views::Event& event) { - if (sender == new_browser_button_ && delegate_.get()) - delegate_->CreateNewWindow(); - else if (sender == show_apps_button_ && delegate_.get()) - delegate_->ShowApps(); -} - } // namespace aura_shell diff --git a/ui/aura_shell/shell.h b/ui/aura_shell/shell.h index 879bc35..114ee02 100644 --- a/ui/aura_shell/shell.h +++ b/ui/aura_shell/shell.h @@ -16,7 +16,6 @@ #include "base/memory/weak_ptr.h" #include "ui/aura/desktop_delegate.h" #include "ui/aura_shell/aura_shell_export.h" -#include "views/controls/button/button.h" namespace aura { class Window; @@ -24,19 +23,15 @@ class Window; namespace gfx { class Rect; } -namespace views { -class ImageButton; -} namespace aura_shell { -class LauncherModel; +class Launcher; class ShellDelegate; // Shell is a singleton object that presents the Shell API and implements the // Desktop's delegate interface. -class AURA_SHELL_EXPORT Shell : public aura::DesktopDelegate, - public views::ButtonListener { +class AURA_SHELL_EXPORT Shell : public aura::DesktopDelegate { public: // Upon creation, the Shell sets itself as the Desktop's delegate, which takes // ownership of the Shell. @@ -49,6 +44,7 @@ class AURA_SHELL_EXPORT Shell : public aura::DesktopDelegate, // Sets the delegate. Shell owns its delegate. void SetDelegate(ShellDelegate* delegate); + ShellDelegate* delegate() { return delegate_.get(); } aura::Window* GetContainer(int container_id); const aura::Window* GetContainer(int container_id) const; @@ -56,32 +52,26 @@ class AURA_SHELL_EXPORT Shell : public aura::DesktopDelegate, void TileWindows(); void RestoreTiledWindows(); + Launcher* launcher() { return launcher_.get(); } + private: typedef std::pair<aura::Window*, gfx::Rect> WindowAndBoundsPair; - void InitLauncherModel(); - // Overridden from aura::DesktopDelegate: virtual void AddChildToDefaultParent(aura::Window* window) OVERRIDE; virtual aura::Window* GetTopmostWindowToActivate( aura::Window* ignore) const OVERRIDE; - // Overriden from views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const views::Event& event) OVERRIDE; - static Shell* instance_; std::vector<WindowAndBoundsPair> to_restore_; base::WeakPtrFactory<Shell> method_factory_; - scoped_ptr<LauncherModel> launcher_model_; - views::ImageButton* new_browser_button_; - views::ImageButton* show_apps_button_; - scoped_ptr<ShellDelegate> delegate_; + scoped_ptr<Launcher> launcher_; + DISALLOW_COPY_AND_ASSIGN(Shell); }; diff --git a/ui/aura_shell/shell_delegate.h b/ui/aura_shell/shell_delegate.h index 60b04ec..1fdb735 100644 --- a/ui/aura_shell/shell_delegate.h +++ b/ui/aura_shell/shell_delegate.h @@ -10,6 +10,8 @@ namespace aura_shell { +struct LauncherItem; + // Delegate of the Shell. class AURA_SHELL_EXPORT ShellDelegate { public: @@ -22,6 +24,14 @@ class AURA_SHELL_EXPORT ShellDelegate { // Invoked when the user clicks the app list button on the launcher. virtual void ShowApps() = 0; + + // Invoked when the user clicks on a window entry in the launcher. + virtual void LauncherItemClicked(const LauncherItem& item) = 0; + + // Invoked when a window is added. If the delegate wants the launcher to show + // an entry for |item->window| it should configure |item| appropriately and + // return true. + virtual bool ConfigureLauncherItem(LauncherItem* item) = 0; }; } // namespace aura_shell diff --git a/ui/aura_shell/shell_factory.h b/ui/aura_shell/shell_factory.h index 0411261..a29cc0a 100644 --- a/ui/aura_shell/shell_factory.h +++ b/ui/aura_shell/shell_factory.h @@ -14,15 +14,12 @@ class Widget; namespace aura_shell { -class LauncherModel; - namespace examples { void InitWindowTypeLauncher(); } // namespace examples namespace internal { views::Widget* CreateDesktopBackground(); -views::Widget* CreateLauncher(LauncherModel* model); views::Widget* CreateStatusArea(); } // namespace internal diff --git a/ui/resources/ui_resources.grd b/ui/resources/ui_resources.grd index fec1ec9..dcb3a99 100644 --- a/ui/resources/ui_resources.grd +++ b/ui/resources/ui_resources.grd @@ -117,6 +117,7 @@ <!-- Images only used by Aura. --> <if expr="pp_ifdef('use_aura')"> <include name="IDR_AURA_LAUNCHER_ICON_CHROME" file="aura/chromium-48.png" type="BINDATA" /> + <include name="IDR_AURA_LAUNCHER_TABBED_BROWSER" file="aura/browser_instance.png" type="BINDATA" /> <include name="IDR_AURA_LAUNCHER_ICON_APPLIST" file="aura/applist.png" type="BINDATA" /> <include name="IDR_AURA_STATUS_MOCK" file="aura/statusbar.png" type="BINDATA" /> <include name="IDR_AURA_WALLPAPER" file="aura/damask.png" type="BINDATA" /> |