window_type_launcher.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_delegate.h"
16#include "ash/shell_window_ids.h"
17#include "ash/system/status_area_widget.h"
18#include "ash/system/web_notification/web_notification_tray.h"
19#include "base/bind.h"
20#include "base/strings/utf_string_conversions.h"
21#include "base/time/time.h"
22#include "content/public/browser/browser_thread.h"
23#include "ui/aura/root_window.h"
24#include "ui/aura/window.h"
25#include "ui/compositor/layer.h"
26#include "ui/gfx/canvas.h"
27#include "ui/message_center/message_center.h"
28#include "ui/message_center/notification_types.h"
29#include "ui/views/controls/button/label_button.h"
30#include "ui/views/controls/menu/menu_item_view.h"
31#include "ui/views/controls/menu/menu_runner.h"
32#include "ui/views/corewm/shadow_types.h"
33#include "ui/views/examples/examples_window_with_content.h"
34#include "ui/views/layout/grid_layout.h"
35#include "ui/views/test/child_modal_window.h"
36#include "ui/views/widget/widget.h"
37
38using views::MenuItemView;
39using views::MenuRunner;
40
41namespace ash {
42namespace shell {
43
44namespace {
45
46SkColor g_colors[] = { SK_ColorRED,
47                       SK_ColorYELLOW,
48                       SK_ColorBLUE,
49                       SK_ColorGREEN };
50int g_color_index = 0;
51
52class ModalWindow : public views::WidgetDelegateView,
53                    public views::ButtonListener {
54 public:
55  explicit ModalWindow(ui::ModalType modal_type)
56      : modal_type_(modal_type),
57        color_(g_colors[g_color_index]),
58        open_button_(new views::LabelButton(this, ASCIIToUTF16("Moar!"))) {
59    ++g_color_index %= arraysize(g_colors);
60    open_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
61    AddChildView(open_button_);
62  }
63  virtual ~ModalWindow() {
64  }
65
66  static void OpenModalWindow(aura::Window* parent, ui::ModalType modal_type) {
67    views::Widget* widget =
68        views::Widget::CreateWindowWithParent(new ModalWindow(modal_type),
69                                              parent);
70    widget->GetNativeView()->SetName("ModalWindow");
71    widget->Show();
72  }
73
74  // Overridden from views::View:
75  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
76    canvas->FillRect(GetLocalBounds(), color_);
77  }
78  virtual gfx::Size GetPreferredSize() OVERRIDE {
79    return gfx::Size(200, 200);
80  }
81  virtual void Layout() OVERRIDE {
82    gfx::Size open_ps = open_button_->GetPreferredSize();
83    gfx::Rect local_bounds = GetLocalBounds();
84    open_button_->SetBounds(
85        5, local_bounds.bottom() - open_ps.height() - 5,
86        open_ps.width(), open_ps.height());
87  }
88
89  // Overridden from views::WidgetDelegate:
90  virtual views::View* GetContentsView() OVERRIDE {
91    return this;
92  }
93  virtual bool CanResize() const OVERRIDE {
94    return true;
95  }
96  virtual base::string16 GetWindowTitle() const OVERRIDE {
97    return ASCIIToUTF16("Modal Window");
98  }
99  virtual ui::ModalType GetModalType() const OVERRIDE {
100    return modal_type_;
101  }
102
103  // Overridden from views::ButtonListener:
104  virtual void ButtonPressed(views::Button* sender,
105                             const ui::Event& event) OVERRIDE {
106    DCHECK(sender == open_button_);
107    OpenModalWindow(GetWidget()->GetNativeView(), modal_type_);
108  }
109
110 private:
111  ui::ModalType modal_type_;
112  SkColor color_;
113  views::LabelButton* open_button_;
114
115  DISALLOW_COPY_AND_ASSIGN(ModalWindow);
116};
117
118class NonModalTransient : public views::WidgetDelegateView {
119 public:
120  NonModalTransient()
121      : color_(g_colors[g_color_index]) {
122    ++g_color_index %= arraysize(g_colors);
123  }
124  virtual ~NonModalTransient() {
125  }
126
127  static void OpenNonModalTransient(aura::Window* parent) {
128    views::Widget* widget =
129        views::Widget::CreateWindowWithParent(new NonModalTransient, parent);
130    widget->GetNativeView()->SetName("NonModalTransient");
131    widget->Show();
132  }
133
134  static void ToggleNonModalTransient(aura::Window* parent) {
135    if (!non_modal_transient_) {
136      non_modal_transient_ =
137          views::Widget::CreateWindowWithParent(new NonModalTransient, parent);
138      non_modal_transient_->GetNativeView()->SetName("NonModalTransient");
139    }
140    if (non_modal_transient_->IsVisible())
141      non_modal_transient_->Hide();
142    else
143      non_modal_transient_->Show();
144  }
145
146  // Overridden from views::View:
147  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
148    canvas->FillRect(GetLocalBounds(), color_);
149  }
150  virtual gfx::Size GetPreferredSize() OVERRIDE {
151    return gfx::Size(250, 250);
152  }
153
154  // Overridden from views::WidgetDelegate:
155  virtual views::View* GetContentsView() OVERRIDE {
156    return this;
157  }
158  virtual bool CanResize() const OVERRIDE {
159    return true;
160  }
161  virtual base::string16 GetWindowTitle() const OVERRIDE {
162    return ASCIIToUTF16("Non-Modal Transient");
163  }
164  virtual void DeleteDelegate() OVERRIDE {
165    if (GetWidget() == non_modal_transient_)
166      non_modal_transient_ = NULL;
167
168    delete this;
169  }
170
171 private:
172  SkColor color_;
173
174  static views::Widget* non_modal_transient_;
175
176  DISALLOW_COPY_AND_ASSIGN(NonModalTransient);
177};
178
179// static
180views::Widget* NonModalTransient::non_modal_transient_ = NULL;
181
182void AddViewToLayout(views::GridLayout* layout, views::View* view) {
183  layout->StartRow(0, 0);
184  layout->AddView(view);
185  layout->AddPaddingRow(0, 5);
186}
187
188}  // namespace
189
190void InitWindowTypeLauncher() {
191  views::Widget* widget =
192      views::Widget::CreateWindowWithContextAndBounds(
193          new WindowTypeLauncher,
194          Shell::GetPrimaryRootWindow(),
195          gfx::Rect(120, 150, 300, 410));
196  widget->GetNativeView()->SetName("WindowTypeLauncher");
197  views::corewm::SetShadowType(widget->GetNativeView(),
198                               views::corewm::SHADOW_TYPE_RECTANGULAR);
199  widget->Show();
200}
201
202WindowTypeLauncher::WindowTypeLauncher()
203    : create_button_(new views::LabelButton(
204          this, ASCIIToUTF16("Create Window"))),
205      panel_button_(new views::LabelButton(
206          this, ASCIIToUTF16("Create Panel"))),
207      create_nonresizable_button_(new views::LabelButton(
208          this, ASCIIToUTF16("Create Non-Resizable Window"))),
209      bubble_button_(new views::LabelButton(
210          this, ASCIIToUTF16("Create Pointy Bubble"))),
211      lock_button_(new views::LabelButton(
212          this, ASCIIToUTF16("Lock Screen"))),
213      widgets_button_(new views::LabelButton(
214          this, ASCIIToUTF16("Show Example Widgets"))),
215      system_modal_button_(new views::LabelButton(
216          this, ASCIIToUTF16("Open System Modal Window"))),
217      window_modal_button_(new views::LabelButton(
218          this, ASCIIToUTF16("Open Window Modal Window"))),
219      child_modal_button_(new views::LabelButton(
220          this, ASCIIToUTF16("Open Child Modal Window"))),
221      transient_button_(new views::LabelButton(
222          this, ASCIIToUTF16("Open Non-Modal Transient Window"))),
223      examples_button_(new views::LabelButton(
224          this, ASCIIToUTF16("Open Views Examples Window"))),
225      show_hide_window_button_(new views::LabelButton(
226          this, ASCIIToUTF16("Show/Hide a Window"))),
227      show_screensaver_(new views::LabelButton(
228          this, ASCIIToUTF16("Show the Screensaver [for 5 seconds]"))),
229      show_web_notification_(new views::LabelButton(
230          this, ASCIIToUTF16("Show a web/app notification"))) {
231  create_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
232  panel_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
233  create_nonresizable_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
234  bubble_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
235  lock_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
236  widgets_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
237  system_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
238  window_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
239  child_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
240  transient_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
241  examples_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
242  show_hide_window_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
243  show_screensaver_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
244  show_web_notification_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
245
246  views::GridLayout* layout = new views::GridLayout(this);
247  layout->SetInsets(5, 5, 5, 5);
248  SetLayoutManager(layout);
249  views::ColumnSet* column_set = layout->AddColumnSet(0);
250  column_set->AddColumn(views::GridLayout::LEADING,
251                        views::GridLayout::CENTER,
252                        0,
253                        views::GridLayout::USE_PREF,
254                        0,
255                        0);
256  AddViewToLayout(layout, create_button_);
257  AddViewToLayout(layout, panel_button_);
258  AddViewToLayout(layout, create_nonresizable_button_);
259  AddViewToLayout(layout, bubble_button_);
260  AddViewToLayout(layout, lock_button_);
261  AddViewToLayout(layout, widgets_button_);
262  AddViewToLayout(layout, system_modal_button_);
263  AddViewToLayout(layout, window_modal_button_);
264  AddViewToLayout(layout, child_modal_button_);
265  AddViewToLayout(layout, transient_button_);
266  AddViewToLayout(layout, examples_button_);
267  AddViewToLayout(layout, show_hide_window_button_);
268  AddViewToLayout(layout, show_screensaver_);
269  AddViewToLayout(layout, show_web_notification_);
270  set_context_menu_controller(this);
271}
272
273WindowTypeLauncher::~WindowTypeLauncher() {
274}
275
276void WindowTypeLauncher::OnPaint(gfx::Canvas* canvas) {
277  canvas->FillRect(GetLocalBounds(), SK_ColorWHITE);
278}
279
280bool WindowTypeLauncher::OnMousePressed(const ui::MouseEvent& event) {
281  // Overridden so we get OnMouseReleased and can show the context menu.
282  return true;
283}
284
285views::View* WindowTypeLauncher::GetContentsView() {
286  return this;
287}
288
289bool WindowTypeLauncher::CanResize() const {
290  return true;
291}
292
293base::string16 WindowTypeLauncher::GetWindowTitle() const {
294  return ASCIIToUTF16("Examples: Window Builder");
295}
296
297bool WindowTypeLauncher::CanMaximize() const {
298  return true;
299}
300
301void WindowTypeLauncher::ButtonPressed(views::Button* sender,
302                                       const ui::Event& event) {
303  if (sender == create_button_) {
304    ToplevelWindow::CreateParams params;
305    params.can_resize = true;
306    params.can_maximize = true;
307    ToplevelWindow::CreateToplevelWindow(params);
308  } else if (sender == panel_button_) {
309    PanelWindow::CreatePanelWindow(gfx::Rect());
310  } else if (sender == create_nonresizable_button_) {
311    ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
312  } else if (sender == bubble_button_) {
313    CreatePointyBubble(sender);
314  } else if (sender == lock_button_) {
315    Shell::GetInstance()->session_state_delegate()->LockScreen();
316  } else if (sender == widgets_button_) {
317    CreateWidgetsWindow();
318  } else if (sender == system_modal_button_) {
319    ModalWindow::OpenModalWindow(GetWidget()->GetNativeView(),
320                                 ui::MODAL_TYPE_SYSTEM);
321  } else if (sender == window_modal_button_) {
322    ModalWindow::OpenModalWindow(GetWidget()->GetNativeView(),
323                                 ui::MODAL_TYPE_WINDOW);
324  } else if (sender == child_modal_button_) {
325    views::test::CreateChildModalParent(
326        GetWidget()->GetNativeView()->GetRootWindow());
327  } else if (sender == transient_button_) {
328    NonModalTransient::OpenNonModalTransient(GetWidget()->GetNativeView());
329  } else if (sender == show_hide_window_button_) {
330    NonModalTransient::ToggleNonModalTransient(GetWidget()->GetNativeView());
331  } else if (sender == show_screensaver_) {
332    ash::ShowScreensaver(GURL("http://www.google.com"));
333    content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
334                                            FROM_HERE,
335                                            base::Bind(&ash::CloseScreensaver),
336                                            base::TimeDelta::FromSeconds(5));
337
338  } else if (sender == show_web_notification_) {
339    scoped_ptr<message_center::Notification> notification;
340    notification.reset(new message_center::Notification(
341        message_center::NOTIFICATION_TYPE_SIMPLE,
342        "id0",
343        ASCIIToUTF16("Test Shell Web Notification"),
344        ASCIIToUTF16("Notification message body."),
345        gfx::Image(),
346        ASCIIToUTF16("www.testshell.org"),
347        message_center::NotifierId(),
348        message_center::RichNotificationData(),
349        NULL /* delegate */));
350
351    ash::Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget()
352        ->web_notification_tray()->message_center()
353        ->AddNotification(notification.Pass());
354  } else if (sender == examples_button_) {
355    views::examples::ShowExamplesWindowWithContent(
356        views::examples::DO_NOTHING_ON_CLOSE,
357        Shell::GetInstance()->delegate()->GetCurrentBrowserContext(),
358        NULL);
359  }
360}
361
362void WindowTypeLauncher::ExecuteCommand(int id, int event_flags) {
363  switch (id) {
364    case COMMAND_NEW_WINDOW:
365      InitWindowTypeLauncher();
366      break;
367    case COMMAND_TOGGLE_FULLSCREEN:
368      GetWidget()->SetFullscreen(!GetWidget()->IsFullscreen());
369      break;
370    default:
371      break;
372  }
373}
374
375void WindowTypeLauncher::ShowContextMenuForView(
376    views::View* source,
377    const gfx::Point& point,
378    ui::MenuSourceType source_type) {
379  MenuItemView* root = new MenuItemView(this);
380  root->AppendMenuItem(COMMAND_NEW_WINDOW,
381                       ASCIIToUTF16("New Window"),
382                       MenuItemView::NORMAL);
383  root->AppendMenuItem(COMMAND_TOGGLE_FULLSCREEN,
384                       ASCIIToUTF16("Toggle FullScreen"),
385                       MenuItemView::NORMAL);
386  // MenuRunner takes ownership of root.
387  menu_runner_.reset(new MenuRunner(root));
388  if (menu_runner_->RunMenuAt(GetWidget(), NULL,
389        gfx::Rect(point, gfx::Size()),
390        MenuItemView::TOPLEFT,
391        source_type,
392        MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
393        MenuRunner::MENU_DELETED)
394    return;
395}
396
397}  // namespace shell
398}  // namespace ash
399