window_type_launcher.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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.
4
5#include "ash/shell/window_type_launcher.h"
6
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"
36
37using views::MenuItemView;
38using views::MenuRunner;
39
40namespace ash {
41namespace shell {
42
43namespace {
44
45SkColor g_colors[] = { SK_ColorRED,
46                       SK_ColorYELLOW,
47                       SK_ColorBLUE,
48                       SK_ColorGREEN };
49int g_color_index = 0;
50
51class ModalWindow : public views::WidgetDelegateView,
52                    public views::ButtonListener {
53 public:
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_);
61  }
62  virtual ~ModalWindow() {
63  }
64
65  static void OpenModalWindow(aura::Window* parent, ui::ModalType modal_type) {
66    views::Widget* widget =
67        views::Widget::CreateWindowWithParent(new ModalWindow(modal_type),
68                                              parent);
69    widget->GetNativeView()->SetName("ModalWindow");
70    widget->Show();
71  }
72
73  // Overridden from views::View:
74  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
75    canvas->FillRect(GetLocalBounds(), color_);
76  }
77  virtual gfx::Size GetPreferredSize() OVERRIDE {
78    return gfx::Size(200, 200);
79  }
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());
86  }
87
88  // Overridden from views::WidgetDelegate:
89  virtual views::View* GetContentsView() OVERRIDE {
90    return this;
91  }
92  virtual bool CanResize() const OVERRIDE {
93    return true;
94  }
95  virtual base::string16 GetWindowTitle() const OVERRIDE {
96    return ASCIIToUTF16("Modal Window");
97  }
98  virtual ui::ModalType GetModalType() const OVERRIDE {
99    return modal_type_;
100  }
101
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_);
107  }
108
109 private:
110  ui::ModalType modal_type_;
111  SkColor color_;
112  views::LabelButton* open_button_;
113
114  DISALLOW_COPY_AND_ASSIGN(ModalWindow);
115};
116
117class NonModalTransient : public views::WidgetDelegateView {
118 public:
119  NonModalTransient()
120      : color_(g_colors[g_color_index]) {
121    ++g_color_index %= arraysize(g_colors);
122  }
123  virtual ~NonModalTransient() {
124  }
125
126  static void OpenNonModalTransient(aura::Window* parent) {
127    views::Widget* widget =
128        views::Widget::CreateWindowWithParent(new NonModalTransient, parent);
129    widget->GetNativeView()->SetName("NonModalTransient");
130    widget->Show();
131  }
132
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");
138    }
139    if (non_modal_transient_->IsVisible())
140      non_modal_transient_->Hide();
141    else
142      non_modal_transient_->Show();
143  }
144
145  // Overridden from views::View:
146  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
147    canvas->FillRect(GetLocalBounds(), color_);
148  }
149  virtual gfx::Size GetPreferredSize() OVERRIDE {
150    return gfx::Size(250, 250);
151  }
152
153  // Overridden from views::WidgetDelegate:
154  virtual views::View* GetContentsView() OVERRIDE {
155    return this;
156  }
157  virtual bool CanResize() const OVERRIDE {
158    return true;
159  }
160  virtual base::string16 GetWindowTitle() const OVERRIDE {
161    return ASCIIToUTF16("Non-Modal Transient");
162  }
163  virtual void DeleteDelegate() OVERRIDE {
164    if (GetWidget() == non_modal_transient_)
165      non_modal_transient_ = NULL;
166
167    delete this;
168  }
169
170 private:
171  SkColor color_;
172
173  static views::Widget* non_modal_transient_;
174
175  DISALLOW_COPY_AND_ASSIGN(NonModalTransient);
176};
177
178// static
179views::Widget* NonModalTransient::non_modal_transient_ = NULL;
180
181void AddViewToLayout(views::GridLayout* layout, views::View* view) {
182  layout->StartRow(0, 0);
183  layout->AddView(view);
184  layout->AddPaddingRow(0, 5);
185}
186
187}  // namespace
188
189void 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);
198  widget->Show();
199}
200
201WindowTypeLauncher::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);
247
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,
254                        0,
255                        views::GridLayout::USE_PREF,
256                        0,
257                        0);
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);
275#endif
276}
277
278WindowTypeLauncher::~WindowTypeLauncher() {
279}
280
281void WindowTypeLauncher::OnPaint(gfx::Canvas* canvas) {
282  canvas->FillRect(GetLocalBounds(), SK_ColorWHITE);
283}
284
285bool WindowTypeLauncher::OnMousePressed(const ui::MouseEvent& event) {
286  // Overridden so we get OnMouseReleased and can show the context menu.
287  return true;
288}
289
290views::View* WindowTypeLauncher::GetContentsView() {
291  return this;
292}
293
294bool WindowTypeLauncher::CanResize() const {
295  return true;
296}
297
298base::string16 WindowTypeLauncher::GetWindowTitle() const {
299  return ASCIIToUTF16("Examples: Window Builder");
300}
301
302bool WindowTypeLauncher::CanMaximize() const {
303  return true;
304}
305
306void 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,
345                                            FROM_HERE,
346                                            base::Bind(&ash::CloseScreensaver),
347                                            base::TimeDelta::FromSeconds(5));
348
349  } else if (sender == show_web_notification_) {
350    ash::Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget()
351        ->web_notification_tray()->message_center()
352        ->AddNotification(message_center::NOTIFICATION_TYPE_SIMPLE,
353                          "id0",
354                          ASCIIToUTF16("Test Shell Web Notification"),
355                          ASCIIToUTF16("Notification message body."),
356                          ASCIIToUTF16("www.testshell.org"),
357                          "" /* extension id */,
358                          NULL /* optional_fields */,
359                          NULL /* delegate */);
360  }
361#if !defined(OS_MACOSX)
362      else if (sender == examples_button_) {
363    views::examples::ShowExamplesWindowWithContent(
364        views::examples::DO_NOTHING_ON_CLOSE,
365        ash::Shell::GetInstance()->browser_context());
366  }
367#endif  // !defined(OS_MACOSX)
368}
369
370#if !defined(OS_MACOSX)
371void WindowTypeLauncher::ExecuteCommand(int id, int event_flags) {
372  switch (id) {
373    case COMMAND_NEW_WINDOW:
374      InitWindowTypeLauncher();
375      break;
376    case COMMAND_TOGGLE_FULLSCREEN:
377      GetWidget()->SetFullscreen(!GetWidget()->IsFullscreen());
378      break;
379    default:
380      break;
381  }
382}
383#endif  // !defined(OS_MACOSX)
384
385#if !defined(OS_MACOSX)
386void WindowTypeLauncher::ShowContextMenuForView(views::View* source,
387                                                const gfx::Point& point) {
388  MenuItemView* root = new MenuItemView(this);
389  root->AppendMenuItem(COMMAND_NEW_WINDOW,
390                       ASCIIToUTF16("New Window"),
391                       MenuItemView::NORMAL);
392  root->AppendMenuItem(COMMAND_TOGGLE_FULLSCREEN,
393                       ASCIIToUTF16("Toggle FullScreen"),
394                       MenuItemView::NORMAL);
395  // MenuRunner takes ownership of root.
396  menu_runner_.reset(new MenuRunner(root));
397  if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point, gfx::Size()),
398        MenuItemView::TOPLEFT,
399        MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
400        MenuRunner::MENU_DELETED)
401    return;
402}
403#endif  // !defined(OS_MACOSX)
404
405}  // namespace shell
406}  // namespace ash
407