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 "ash/shell/window_type_launcher.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/screensaver/screensaver_view.h"
9 #include "ash/session_state_delegate.h"
10 #include "ash/shelf/shelf_widget.h"
11 #include "ash/shell.h"
12 #include "ash/shell/example_factory.h"
13 #include "ash/shell/panel_window.h"
14 #include "ash/shell/toplevel_window.h"
15 #include "ash/shell_window_ids.h"
16 #include "ash/system/status_area_widget.h"
17 #include "ash/system/web_notification/web_notification_tray.h"
18 #include "base/bind.h"
19 #include "base/time.h"
20 #include "base/utf_string_conversions.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "ui/aura/root_window.h"
23 #include "ui/aura/window.h"
24 #include "ui/compositor/layer.h"
25 #include "ui/gfx/canvas.h"
26 #include "ui/message_center/message_center.h"
27 #include "ui/message_center/notification_types.h"
28 #include "ui/views/controls/button/label_button.h"
29 #include "ui/views/controls/menu/menu_item_view.h"
30 #include "ui/views/controls/menu/menu_runner.h"
31 #include "ui/views/corewm/shadow_types.h"
32 #include "ui/views/examples/examples_window_with_content.h"
33 #include "ui/views/layout/grid_layout.h"
34 #include "ui/views/test/child_modal_window.h"
35 #include "ui/views/widget/widget.h"
37 using views::MenuItemView
;
38 using views::MenuRunner
;
45 SkColor g_colors
[] = { SK_ColorRED
,
49 int g_color_index
= 0;
51 class ModalWindow
: public views::WidgetDelegateView
,
52 public views::ButtonListener
{
54 explicit ModalWindow(ui::ModalType modal_type
)
55 : modal_type_(modal_type
),
56 color_(g_colors
[g_color_index
]),
57 open_button_(new views::LabelButton(this, ASCIIToUTF16("Moar!"))) {
58 ++g_color_index
%= arraysize(g_colors
);
59 open_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
60 AddChildView(open_button_
);
62 virtual ~ModalWindow() {
65 static void OpenModalWindow(aura::Window
* parent
, ui::ModalType modal_type
) {
66 views::Widget
* widget
=
67 views::Widget::CreateWindowWithParent(new ModalWindow(modal_type
),
69 widget
->GetNativeView()->SetName("ModalWindow");
73 // Overridden from views::View:
74 virtual void OnPaint(gfx::Canvas
* canvas
) OVERRIDE
{
75 canvas
->FillRect(GetLocalBounds(), color_
);
77 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
78 return gfx::Size(200, 200);
80 virtual void Layout() OVERRIDE
{
81 gfx::Size open_ps
= open_button_
->GetPreferredSize();
82 gfx::Rect local_bounds
= GetLocalBounds();
83 open_button_
->SetBounds(
84 5, local_bounds
.bottom() - open_ps
.height() - 5,
85 open_ps
.width(), open_ps
.height());
88 // Overridden from views::WidgetDelegate:
89 virtual views::View
* GetContentsView() OVERRIDE
{
92 virtual bool CanResize() const OVERRIDE
{
95 virtual base::string16
GetWindowTitle() const OVERRIDE
{
96 return ASCIIToUTF16("Modal Window");
98 virtual ui::ModalType
GetModalType() const OVERRIDE
{
102 // Overridden from views::ButtonListener:
103 virtual void ButtonPressed(views::Button
* sender
,
104 const ui::Event
& event
) OVERRIDE
{
105 DCHECK(sender
== open_button_
);
106 OpenModalWindow(GetWidget()->GetNativeView(), modal_type_
);
110 ui::ModalType modal_type_
;
112 views::LabelButton
* open_button_
;
114 DISALLOW_COPY_AND_ASSIGN(ModalWindow
);
117 class NonModalTransient
: public views::WidgetDelegateView
{
120 : color_(g_colors
[g_color_index
]) {
121 ++g_color_index
%= arraysize(g_colors
);
123 virtual ~NonModalTransient() {
126 static void OpenNonModalTransient(aura::Window
* parent
) {
127 views::Widget
* widget
=
128 views::Widget::CreateWindowWithParent(new NonModalTransient
, parent
);
129 widget
->GetNativeView()->SetName("NonModalTransient");
133 static void ToggleNonModalTransient(aura::Window
* parent
) {
134 if (!non_modal_transient_
) {
135 non_modal_transient_
=
136 views::Widget::CreateWindowWithParent(new NonModalTransient
, parent
);
137 non_modal_transient_
->GetNativeView()->SetName("NonModalTransient");
139 if (non_modal_transient_
->IsVisible())
140 non_modal_transient_
->Hide();
142 non_modal_transient_
->Show();
145 // Overridden from views::View:
146 virtual void OnPaint(gfx::Canvas
* canvas
) OVERRIDE
{
147 canvas
->FillRect(GetLocalBounds(), color_
);
149 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
150 return gfx::Size(250, 250);
153 // Overridden from views::WidgetDelegate:
154 virtual views::View
* GetContentsView() OVERRIDE
{
157 virtual bool CanResize() const OVERRIDE
{
160 virtual base::string16
GetWindowTitle() const OVERRIDE
{
161 return ASCIIToUTF16("Non-Modal Transient");
163 virtual void DeleteDelegate() OVERRIDE
{
164 if (GetWidget() == non_modal_transient_
)
165 non_modal_transient_
= NULL
;
173 static views::Widget
* non_modal_transient_
;
175 DISALLOW_COPY_AND_ASSIGN(NonModalTransient
);
179 views::Widget
* NonModalTransient::non_modal_transient_
= NULL
;
181 void AddViewToLayout(views::GridLayout
* layout
, views::View
* view
) {
182 layout
->StartRow(0, 0);
183 layout
->AddView(view
);
184 layout
->AddPaddingRow(0, 5);
189 void InitWindowTypeLauncher() {
190 views::Widget
* widget
=
191 views::Widget::CreateWindowWithContextAndBounds(
192 new WindowTypeLauncher
,
193 Shell::GetPrimaryRootWindow(),
194 gfx::Rect(120, 150, 300, 410));
195 widget
->GetNativeView()->SetName("WindowTypeLauncher");
196 views::corewm::SetShadowType(widget
->GetNativeView(),
197 views::corewm::SHADOW_TYPE_RECTANGULAR
);
201 WindowTypeLauncher::WindowTypeLauncher()
202 : create_button_(new views::LabelButton(
203 this, ASCIIToUTF16("Create Window"))),
204 create_persistant_button_(new views::LabelButton(
205 this, ASCIIToUTF16("Create Persistant Window"))),
206 panel_button_(new views::LabelButton(
207 this, ASCIIToUTF16("Create Panel"))),
208 create_nonresizable_button_(new views::LabelButton(
209 this, ASCIIToUTF16("Create Non-Resizable Window"))),
210 bubble_button_(new views::LabelButton(
211 this, ASCIIToUTF16("Create Pointy Bubble"))),
212 lock_button_(new views::LabelButton(
213 this, ASCIIToUTF16("Lock Screen"))),
214 widgets_button_(new views::LabelButton(
215 this, ASCIIToUTF16("Show Example Widgets"))),
216 system_modal_button_(new views::LabelButton(
217 this, ASCIIToUTF16("Open System Modal Window"))),
218 window_modal_button_(new views::LabelButton(
219 this, ASCIIToUTF16("Open Window Modal Window"))),
220 child_modal_button_(new views::LabelButton(
221 this, ASCIIToUTF16("Open Child Modal Window"))),
222 transient_button_(new views::LabelButton(
223 this, ASCIIToUTF16("Open Non-Modal Transient Window"))),
224 examples_button_(new views::LabelButton(
225 this, ASCIIToUTF16("Open Views Examples Window"))),
226 show_hide_window_button_(new views::LabelButton(
227 this, ASCIIToUTF16("Show/Hide a Window"))),
228 show_screensaver_(new views::LabelButton(
229 this, ASCIIToUTF16("Show the Screensaver [for 5 seconds]"))),
230 show_web_notification_(new views::LabelButton(
231 this, ASCIIToUTF16("Show a web/app notification"))) {
232 create_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
233 create_persistant_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
234 panel_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
235 create_nonresizable_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
236 bubble_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
237 lock_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
238 widgets_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
239 system_modal_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
240 window_modal_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
241 child_modal_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
242 transient_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
243 examples_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
244 show_hide_window_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
245 show_screensaver_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
246 show_web_notification_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
248 views::GridLayout
* layout
= new views::GridLayout(this);
249 layout
->SetInsets(5, 5, 5, 5);
250 SetLayoutManager(layout
);
251 views::ColumnSet
* column_set
= layout
->AddColumnSet(0);
252 column_set
->AddColumn(views::GridLayout::LEADING
,
253 views::GridLayout::CENTER
,
255 views::GridLayout::USE_PREF
,
258 AddViewToLayout(layout
, create_button_
);
259 AddViewToLayout(layout
, create_persistant_button_
);
260 AddViewToLayout(layout
, panel_button_
);
261 AddViewToLayout(layout
, create_nonresizable_button_
);
262 AddViewToLayout(layout
, bubble_button_
);
263 AddViewToLayout(layout
, lock_button_
);
264 AddViewToLayout(layout
, widgets_button_
);
265 AddViewToLayout(layout
, system_modal_button_
);
266 AddViewToLayout(layout
, window_modal_button_
);
267 AddViewToLayout(layout
, child_modal_button_
);
268 AddViewToLayout(layout
, transient_button_
);
269 AddViewToLayout(layout
, examples_button_
);
270 AddViewToLayout(layout
, show_hide_window_button_
);
271 AddViewToLayout(layout
, show_screensaver_
);
272 AddViewToLayout(layout
, show_web_notification_
);
273 #if !defined(OS_MACOSX)
274 set_context_menu_controller(this);
278 WindowTypeLauncher::~WindowTypeLauncher() {
281 void WindowTypeLauncher::OnPaint(gfx::Canvas
* canvas
) {
282 canvas
->FillRect(GetLocalBounds(), SK_ColorWHITE
);
285 bool WindowTypeLauncher::OnMousePressed(const ui::MouseEvent
& event
) {
286 // Overridden so we get OnMouseReleased and can show the context menu.
290 views::View
* WindowTypeLauncher::GetContentsView() {
294 bool WindowTypeLauncher::CanResize() const {
298 base::string16
WindowTypeLauncher::GetWindowTitle() const {
299 return ASCIIToUTF16("Examples: Window Builder");
302 bool WindowTypeLauncher::CanMaximize() const {
306 void WindowTypeLauncher::ButtonPressed(views::Button
* sender
,
307 const ui::Event
& event
) {
308 if (sender
== create_button_
) {
309 ToplevelWindow::CreateParams params
;
310 params
.can_resize
= true;
311 params
.can_maximize
= true;
312 ToplevelWindow::CreateToplevelWindow(params
);
313 } else if (sender
== create_persistant_button_
) {
314 ToplevelWindow::CreateParams params
;
315 params
.can_resize
= true;
316 params
.can_maximize
= true;
317 params
.persist_across_all_workspaces
= true;
318 ToplevelWindow::CreateToplevelWindow(params
);
319 } else if (sender
== panel_button_
) {
320 PanelWindow::CreatePanelWindow(gfx::Rect());
321 } else if (sender
== create_nonresizable_button_
) {
322 ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
323 } else if (sender
== bubble_button_
) {
324 CreatePointyBubble(sender
);
325 } else if (sender
== lock_button_
) {
326 Shell::GetInstance()->session_state_delegate()->LockScreen();
327 } else if (sender
== widgets_button_
) {
328 CreateWidgetsWindow();
329 } else if (sender
== system_modal_button_
) {
330 ModalWindow::OpenModalWindow(GetWidget()->GetNativeView(),
331 ui::MODAL_TYPE_SYSTEM
);
332 } else if (sender
== window_modal_button_
) {
333 ModalWindow::OpenModalWindow(GetWidget()->GetNativeView(),
334 ui::MODAL_TYPE_WINDOW
);
335 } else if (sender
== child_modal_button_
) {
336 views::test::CreateChildModalParent(
337 GetWidget()->GetNativeView()->GetRootWindow());
338 } else if (sender
== transient_button_
) {
339 NonModalTransient::OpenNonModalTransient(GetWidget()->GetNativeView());
340 } else if (sender
== show_hide_window_button_
) {
341 NonModalTransient::ToggleNonModalTransient(GetWidget()->GetNativeView());
342 } else if (sender
== show_screensaver_
) {
343 ash::ShowScreensaver(GURL("http://www.google.com"));
344 content::BrowserThread::PostDelayedTask(content::BrowserThread::UI
,
346 base::Bind(&ash::CloseScreensaver
),
347 base::TimeDelta::FromSeconds(5));
349 } else if (sender
== show_web_notification_
) {
350 scoped_ptr
<message_center::Notification
> notification
;
351 notification
.reset(new message_center::Notification(
352 message_center::NOTIFICATION_TYPE_SIMPLE
,
354 ASCIIToUTF16("Test Shell Web Notification"),
355 ASCIIToUTF16("Notification message body."),
357 ASCIIToUTF16("www.testshell.org"),
358 "" /* extension id */,
359 NULL
/* optional_fields */,
360 NULL
/* delegate */));
362 ash::Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget()
363 ->web_notification_tray()->message_center()
364 ->AddNotification(notification
.Pass());
366 #if !defined(OS_MACOSX)
367 else if (sender
== examples_button_
) {
368 views::examples::ShowExamplesWindowWithContent(
369 views::examples::DO_NOTHING_ON_CLOSE
,
370 ash::Shell::GetInstance()->browser_context());
372 #endif // !defined(OS_MACOSX)
375 #if !defined(OS_MACOSX)
376 void WindowTypeLauncher::ExecuteCommand(int id
, int event_flags
) {
378 case COMMAND_NEW_WINDOW
:
379 InitWindowTypeLauncher();
381 case COMMAND_TOGGLE_FULLSCREEN
:
382 GetWidget()->SetFullscreen(!GetWidget()->IsFullscreen());
388 #endif // !defined(OS_MACOSX)
390 #if !defined(OS_MACOSX)
391 void WindowTypeLauncher::ShowContextMenuForView(views::View
* source
,
392 const gfx::Point
& point
) {
393 MenuItemView
* root
= new MenuItemView(this);
394 root
->AppendMenuItem(COMMAND_NEW_WINDOW
,
395 ASCIIToUTF16("New Window"),
396 MenuItemView::NORMAL
);
397 root
->AppendMenuItem(COMMAND_TOGGLE_FULLSCREEN
,
398 ASCIIToUTF16("Toggle FullScreen"),
399 MenuItemView::NORMAL
);
400 // MenuRunner takes ownership of root.
401 menu_runner_
.reset(new MenuRunner(root
));
402 if (menu_runner_
->RunMenuAt(GetWidget(), NULL
, gfx::Rect(point
, gfx::Size()),
403 MenuItemView::TOPLEFT
,
404 MenuRunner::HAS_MNEMONICS
| views::MenuRunner::CONTEXT_MENU
) ==
405 MenuRunner::MENU_DELETED
)
408 #endif // !defined(OS_MACOSX)