Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / ash / launcher / shell_window_launcher_item_controller.cc
blob4a0ca09cd8a22dbebcc2c69e3715fa5c1d88ac39
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
7 #include "apps/shell_window.h"
8 #include "apps/ui/native_app_window.h"
9 #include "ash/shelf/shelf_model.h"
10 #include "ash/wm/window_state.h"
11 #include "ash/wm/window_util.h"
12 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
13 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h"
14 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
15 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
16 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
17 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
18 #include "content/public/browser/web_contents.h"
19 #include "skia/ext/image_operations.h"
20 #include "ui/aura/client/aura_constants.h"
21 #include "ui/aura/window.h"
22 #include "ui/events/event.h"
23 #include "ui/gfx/image/image_skia.h"
24 #include "ui/views/corewm/window_animations.h"
26 using apps::ShellWindow;
28 namespace {
30 // Size of the icon in the shelf launcher in display-independent pixels.
31 const int kAppListIconSize = 24;
33 // This will return a slightly smaller icon than the app icon to be used in
34 // the application list menu.
35 scoped_ptr<gfx::Image> GetAppListIcon(ShellWindow* shell_window) {
36 // TODO(skuhne): We instead might want to use LoadImages in
37 // ShellWindow::UpdateExtensionAppIcon() to let the extension give us
38 // pre-defined icons in the launcher and the launcher list sizes. Since there
39 // is no mock yet, doing this now seems a bit premature and we scale for the
40 // time being.
41 if (shell_window->app_icon().IsEmpty())
42 return make_scoped_ptr(new gfx::Image());
44 SkBitmap bmp =
45 skia::ImageOperations::Resize(*shell_window->app_icon().ToSkBitmap(),
46 skia::ImageOperations::RESIZE_BEST,
47 kAppListIconSize,
48 kAppListIconSize);
49 return make_scoped_ptr(
50 new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp)));
53 // Functor for std::find_if used in AppLauncherItemController.
54 class ShellWindowHasWindow {
55 public:
56 explicit ShellWindowHasWindow(aura::Window* window) : window_(window) { }
58 bool operator()(ShellWindow* shell_window) const {
59 return shell_window->GetNativeWindow() == window_;
62 private:
63 const aura::Window* window_;
66 } // namespace
68 ShellWindowLauncherItemController::ShellWindowLauncherItemController(
69 Type type,
70 const std::string& app_launcher_id,
71 const std::string& app_id,
72 ChromeLauncherController* controller)
73 : LauncherItemController(type, app_id, controller),
74 last_active_shell_window_(NULL),
75 app_launcher_id_(app_launcher_id),
76 observed_windows_(this) {
79 ShellWindowLauncherItemController::~ShellWindowLauncherItemController() {
82 void ShellWindowLauncherItemController::AddShellWindow(
83 ShellWindow* shell_window,
84 ash::LauncherItemStatus status) {
85 if (shell_window->window_type_is_panel() && type() != TYPE_APP_PANEL)
86 LOG(ERROR) << "ShellWindow of type Panel added to non-panel launcher item";
87 shell_windows_.push_front(shell_window);
88 observed_windows_.Add(shell_window->GetNativeWindow());
91 void ShellWindowLauncherItemController::RemoveShellWindowForWindow(
92 aura::Window* window) {
93 ShellWindowList::iterator iter =
94 std::find_if(shell_windows_.begin(), shell_windows_.end(),
95 ShellWindowHasWindow(window));
96 if (iter != shell_windows_.end()) {
97 if (*iter == last_active_shell_window_)
98 last_active_shell_window_ = NULL;
99 shell_windows_.erase(iter);
101 observed_windows_.Remove(window);
104 void ShellWindowLauncherItemController::SetActiveWindow(aura::Window* window) {
105 ShellWindowList::iterator iter =
106 std::find_if(shell_windows_.begin(), shell_windows_.end(),
107 ShellWindowHasWindow(window));
108 if (iter != shell_windows_.end())
109 last_active_shell_window_ = *iter;
112 bool ShellWindowLauncherItemController::IsOpen() const {
113 return !shell_windows_.empty();
116 bool ShellWindowLauncherItemController::IsVisible() const {
117 // Return true if any windows are visible.
118 for (ShellWindowList::const_iterator iter = shell_windows_.begin();
119 iter != shell_windows_.end(); ++iter) {
120 if ((*iter)->GetNativeWindow()->IsVisible())
121 return true;
123 return false;
126 void ShellWindowLauncherItemController::Launch(ash::LaunchSource source,
127 int event_flags) {
128 launcher_controller()->LaunchApp(app_id(),
129 source,
130 ui::EF_NONE);
133 bool ShellWindowLauncherItemController::Activate(ash::LaunchSource source) {
134 DCHECK(!shell_windows_.empty());
135 ShellWindow* window_to_activate = last_active_shell_window_ ?
136 last_active_shell_window_ : shell_windows_.back();
137 window_to_activate->GetBaseWindow()->Activate();
138 return false;
141 void ShellWindowLauncherItemController::Close() {
142 // Note: Closing windows may affect the contents of shell_windows_.
143 ShellWindowList windows_to_close = shell_windows_;
144 for (ShellWindowList::iterator iter = windows_to_close.begin();
145 iter != windows_to_close.end(); ++iter) {
146 (*iter)->GetBaseWindow()->Close();
150 void ShellWindowLauncherItemController::ActivateIndexedApp(size_t index) {
151 if (index >= shell_windows_.size())
152 return;
153 ShellWindowList::iterator it = shell_windows_.begin();
154 std::advance(it, index);
155 ShowAndActivateOrMinimize(*it);
158 ChromeLauncherAppMenuItems
159 ShellWindowLauncherItemController::GetApplicationList(int event_flags) {
160 ChromeLauncherAppMenuItems items;
161 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false));
162 int index = 0;
163 for (ShellWindowList::iterator iter = shell_windows_.begin();
164 iter != shell_windows_.end(); ++iter) {
165 ShellWindow* shell_window = *iter;
166 scoped_ptr<gfx::Image> image(GetAppListIcon(shell_window));
167 items.push_back(new ChromeLauncherAppMenuItemV2App(
168 shell_window->GetTitle(),
169 image.get(), // Will be copied
170 app_id(),
171 launcher_controller(),
172 index,
173 index == 0 /* has_leading_separator */));
174 ++index;
176 return items.Pass();
179 bool ShellWindowLauncherItemController::ItemSelected(const ui::Event& event) {
180 if (shell_windows_.empty())
181 return false;
182 if (type() == TYPE_APP_PANEL) {
183 DCHECK(shell_windows_.size() == 1);
184 ShellWindow* panel = shell_windows_.front();
185 aura::Window* panel_window = panel->GetNativeWindow();
186 // If the panel is attached on another display, move it to the current
187 // display and activate it.
188 if (ash::wm::GetWindowState(panel_window)->panel_attached() &&
189 ash::wm::MoveWindowToEventRoot(panel_window, event)) {
190 if (!panel->GetBaseWindow()->IsActive())
191 ShowAndActivateOrMinimize(panel);
192 } else {
193 ShowAndActivateOrMinimize(panel);
195 } else {
196 ShellWindow* window_to_show = last_active_shell_window_ ?
197 last_active_shell_window_ : shell_windows_.front();
198 // If the event was triggered by a keystroke, we try to advance to the next
199 // item if the window we are trying to activate is already active.
200 if (shell_windows_.size() >= 1 &&
201 window_to_show->GetBaseWindow()->IsActive() &&
202 event.type() == ui::ET_KEY_RELEASED) {
203 ActivateOrAdvanceToNextShellWindow(window_to_show);
204 } else {
205 ShowAndActivateOrMinimize(window_to_show);
208 return false;
211 base::string16 ShellWindowLauncherItemController::GetTitle() {
212 // For panels return the title of the contents if set.
213 // Otherwise return the title of the app.
214 if (type() == TYPE_APP_PANEL && !shell_windows_.empty()) {
215 ShellWindow* shell_window = shell_windows_.front();
216 if (shell_window->web_contents()) {
217 base::string16 title = shell_window->web_contents()->GetTitle();
218 if (!title.empty())
219 return title;
222 return GetAppTitle();
225 ui::MenuModel* ShellWindowLauncherItemController::CreateContextMenu(
226 aura::Window* root_window) {
227 ash::LauncherItem item =
228 *(launcher_controller()->model()->ItemByID(launcher_id()));
229 return new LauncherContextMenu(launcher_controller(), &item, root_window);
232 ash::ShelfMenuModel* ShellWindowLauncherItemController::CreateApplicationMenu(
233 int event_flags) {
234 return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
237 bool ShellWindowLauncherItemController::IsDraggable() {
238 if (type() == TYPE_APP_PANEL)
239 return true;
240 return launcher_controller()->CanPin() ? true : false;
243 bool ShellWindowLauncherItemController::ShouldShowTooltip() {
244 if (type() == TYPE_APP_PANEL && IsVisible())
245 return false;
246 return true;
249 void ShellWindowLauncherItemController::OnWindowPropertyChanged(
250 aura::Window* window,
251 const void* key,
252 intptr_t old) {
253 if (key == aura::client::kDrawAttentionKey) {
254 ash::LauncherItemStatus status;
255 if (ash::wm::IsActiveWindow(window)) {
256 status = ash::STATUS_ACTIVE;
257 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) {
258 status = ash::STATUS_ATTENTION;
259 } else {
260 status = ash::STATUS_RUNNING;
262 launcher_controller()->SetItemStatus(launcher_id(), status);
266 void ShellWindowLauncherItemController::ShowAndActivateOrMinimize(
267 ShellWindow* shell_window) {
268 // Either show or minimize windows when shown from the launcher.
269 launcher_controller()->ActivateWindowOrMinimizeIfActive(
270 shell_window->GetBaseWindow(),
271 GetApplicationList(0).size() == 2);
274 void ShellWindowLauncherItemController::ActivateOrAdvanceToNextShellWindow(
275 ShellWindow* window_to_show) {
276 ShellWindowList::iterator i(
277 std::find(shell_windows_.begin(),
278 shell_windows_.end(),
279 window_to_show));
280 if (i != shell_windows_.end()) {
281 if (++i != shell_windows_.end())
282 window_to_show = *i;
283 else
284 window_to_show = shell_windows_.front();
286 if (window_to_show->GetBaseWindow()->IsActive()) {
287 // Coming here, only a single window is active. For keyboard activations
288 // the window gets animated.
289 AnimateWindow(window_to_show->GetNativeWindow(),
290 views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE);
291 } else {
292 ShowAndActivateOrMinimize(window_to_show);