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_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/strings/utf_string_conversions.h"
     20 #include "base/time/time.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 
     37 using views::MenuItemView;
     38 using views::MenuRunner;
     39 
     40 namespace ash {
     41 namespace shell {
     42 
     43 namespace {
     44 
     45 SkColor g_colors[] = { SK_ColorRED,
     46                        SK_ColorYELLOW,
     47                        SK_ColorBLUE,
     48                        SK_ColorGREEN };
     49 int g_color_index = 0;
     50 
     51 class 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 
    117 class 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
    179 views::Widget* NonModalTransient::non_modal_transient_ = NULL;
    180 
    181 void 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 
    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);
    198   widget->Show();
    199 }
    200 
    201 WindowTypeLauncher::WindowTypeLauncher()
    202     : create_button_(new views::LabelButton(
    203           this, ASCIIToUTF16("Create Window"))),
    204       panel_button_(new views::LabelButton(
    205           this, ASCIIToUTF16("Create Panel"))),
    206       create_nonresizable_button_(new views::LabelButton(
    207           this, ASCIIToUTF16("Create Non-Resizable Window"))),
    208       bubble_button_(new views::LabelButton(
    209           this, ASCIIToUTF16("Create Pointy Bubble"))),
    210       lock_button_(new views::LabelButton(
    211           this, ASCIIToUTF16("Lock Screen"))),
    212       widgets_button_(new views::LabelButton(
    213           this, ASCIIToUTF16("Show Example Widgets"))),
    214       system_modal_button_(new views::LabelButton(
    215           this, ASCIIToUTF16("Open System Modal Window"))),
    216       window_modal_button_(new views::LabelButton(
    217           this, ASCIIToUTF16("Open Window Modal Window"))),
    218       child_modal_button_(new views::LabelButton(
    219           this, ASCIIToUTF16("Open Child Modal Window"))),
    220       transient_button_(new views::LabelButton(
    221           this, ASCIIToUTF16("Open Non-Modal Transient Window"))),
    222       examples_button_(new views::LabelButton(
    223           this, ASCIIToUTF16("Open Views Examples Window"))),
    224       show_hide_window_button_(new views::LabelButton(
    225           this, ASCIIToUTF16("Show/Hide a Window"))),
    226       show_screensaver_(new views::LabelButton(
    227           this, ASCIIToUTF16("Show the Screensaver [for 5 seconds]"))),
    228       show_web_notification_(new views::LabelButton(
    229           this, ASCIIToUTF16("Show a web/app notification"))) {
    230   create_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    231   panel_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    232   create_nonresizable_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    233   bubble_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    234   lock_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    235   widgets_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    236   system_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    237   window_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    238   child_modal_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    239   transient_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    240   examples_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    241   show_hide_window_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    242   show_screensaver_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    243   show_web_notification_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    244 
    245   views::GridLayout* layout = new views::GridLayout(this);
    246   layout->SetInsets(5, 5, 5, 5);
    247   SetLayoutManager(layout);
    248   views::ColumnSet* column_set = layout->AddColumnSet(0);
    249   column_set->AddColumn(views::GridLayout::LEADING,
    250                         views::GridLayout::CENTER,
    251                         0,
    252                         views::GridLayout::USE_PREF,
    253                         0,
    254                         0);
    255   AddViewToLayout(layout, create_button_);
    256   AddViewToLayout(layout, panel_button_);
    257   AddViewToLayout(layout, create_nonresizable_button_);
    258   AddViewToLayout(layout, bubble_button_);
    259   AddViewToLayout(layout, lock_button_);
    260   AddViewToLayout(layout, widgets_button_);
    261   AddViewToLayout(layout, system_modal_button_);
    262   AddViewToLayout(layout, window_modal_button_);
    263   AddViewToLayout(layout, child_modal_button_);
    264   AddViewToLayout(layout, transient_button_);
    265   AddViewToLayout(layout, examples_button_);
    266   AddViewToLayout(layout, show_hide_window_button_);
    267   AddViewToLayout(layout, show_screensaver_);
    268   AddViewToLayout(layout, show_web_notification_);
    269 #if !defined(OS_MACOSX)
    270   set_context_menu_controller(this);
    271 #endif
    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 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     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         ASCIIToUTF16("Test Shell Web Notification"),
    345         ASCIIToUTF16("Notification message body."),
    346         gfx::Image(),
    347         ASCIIToUTF16("www.testshell.org"),
    348         "" /* extension id */,
    349         message_center::RichNotificationData(),
    350         NULL /* delegate */));
    351 
    352     ash::Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget()
    353         ->web_notification_tray()->message_center()
    354         ->AddNotification(notification.Pass());
    355   }
    356 #if !defined(OS_MACOSX)
    357       else if (sender == examples_button_) {
    358     views::examples::ShowExamplesWindowWithContent(
    359         views::examples::DO_NOTHING_ON_CLOSE,
    360         ash::Shell::GetInstance()->browser_context());
    361   }
    362 #endif  // !defined(OS_MACOSX)
    363 }
    364 
    365 #if !defined(OS_MACOSX)
    366 void WindowTypeLauncher::ExecuteCommand(int id, int event_flags) {
    367   switch (id) {
    368     case COMMAND_NEW_WINDOW:
    369       InitWindowTypeLauncher();
    370       break;
    371     case COMMAND_TOGGLE_FULLSCREEN:
    372       GetWidget()->SetFullscreen(!GetWidget()->IsFullscreen());
    373       break;
    374     default:
    375       break;
    376   }
    377 }
    378 #endif  // !defined(OS_MACOSX)
    379 
    380 #if !defined(OS_MACOSX)
    381 void WindowTypeLauncher::ShowContextMenuForView(
    382     views::View* source,
    383     const gfx::Point& point,
    384     ui::MenuSourceType source_type) {
    385   MenuItemView* root = new MenuItemView(this);
    386   root->AppendMenuItem(COMMAND_NEW_WINDOW,
    387                        ASCIIToUTF16("New Window"),
    388                        MenuItemView::NORMAL);
    389   root->AppendMenuItem(COMMAND_TOGGLE_FULLSCREEN,
    390                        ASCIIToUTF16("Toggle FullScreen"),
    391                        MenuItemView::NORMAL);
    392   // MenuRunner takes ownership of root.
    393   menu_runner_.reset(new MenuRunner(root));
    394   if (menu_runner_->RunMenuAt(GetWidget(), NULL,
    395         gfx::Rect(point, gfx::Size()),
    396         MenuItemView::TOPLEFT,
    397         source_type,
    398         MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
    399         MenuRunner::MENU_DELETED)
    400     return;
    401 }
    402 #endif  // !defined(OS_MACOSX)
    403 
    404 }  // namespace shell
    405 }  // namespace ash
    406