Home | History | Annotate | Download | only in shell
      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/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 "ash/test/child_modal_window.h"
     20 #include "base/bind.h"
     21 #include "base/strings/utf_string_conversions.h"
     22 #include "base/time/time.h"
     23 #include "content/public/browser/browser_thread.h"
     24 #include "ui/aura/window.h"
     25 #include "ui/aura/window_event_dispatcher.h"
     26 #include "ui/compositor/layer.h"
     27 #include "ui/gfx/canvas.h"
     28 #include "ui/message_center/message_center.h"
     29 #include "ui/message_center/notification_types.h"
     30 #include "ui/views/controls/button/label_button.h"
     31 #include "ui/views/controls/menu/menu_item_view.h"
     32 #include "ui/views/controls/menu/menu_runner.h"
     33 #include "ui/views/examples/examples_window_with_content.h"
     34 #include "ui/views/layout/grid_layout.h"
     35 #include "ui/views/widget/widget.h"
     36 #include "ui/wm/core/shadow_types.h"
     37 
     38 using views::MenuItemView;
     39 using views::MenuRunner;
     40 
     41 namespace ash {
     42 namespace shell {
     43 
     44 namespace {
     45 
     46 SkColor g_colors[] = { SK_ColorRED,
     47                        SK_ColorYELLOW,
     48                        SK_ColorBLUE,
     49                        SK_ColorGREEN };
     50 int g_color_index = 0;
     51 
     52 class 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() const 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 
    119 class 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() const 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
    181 views::Widget* NonModalTransient::non_modal_transient_ = NULL;
    182 
    183 void 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 
    191 void 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   wm::SetShadowType(widget->GetNativeView(),
    199                                wm::SHADOW_TYPE_RECTANGULAR);
    200   widget->Show();
    201 }
    202 
    203 WindowTypeLauncher::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 
    274 WindowTypeLauncher::~WindowTypeLauncher() {
    275 }
    276 
    277 void WindowTypeLauncher::OnPaint(gfx::Canvas* canvas) {
    278   canvas->FillRect(GetLocalBounds(), SK_ColorWHITE);
    279 }
    280 
    281 bool WindowTypeLauncher::OnMousePressed(const ui::MouseEvent& event) {
    282   // Overridden so we get OnMouseReleased and can show the context menu.
    283   return true;
    284 }
    285 
    286 views::View* WindowTypeLauncher::GetContentsView() {
    287   return this;
    288 }
    289 
    290 bool WindowTypeLauncher::CanResize() const {
    291   return true;
    292 }
    293 
    294 base::string16 WindowTypeLauncher::GetWindowTitle() const {
    295   return base::ASCIIToUTF16("Examples: Window Builder");
    296 }
    297 
    298 bool WindowTypeLauncher::CanMaximize() const {
    299   return true;
    300 }
    301 
    302 void 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     ash::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 
    364 void 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 
    377 void 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(
    391           GetWidget(),
    392           NULL,
    393           gfx::Rect(point, gfx::Size()),
    394           views::MENU_ANCHOR_TOPLEFT,
    395           source_type,
    396           MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
    397       MenuRunner::MENU_DELETED) {
    398     return;
    399   }
    400 }
    401 
    402 }  // namespace shell
    403 }  // namespace ash
    404