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