Home | History | Annotate | Download | only in menu
      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 "ui/views/controls/menu/menu_host.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "ui/gfx/path.h"
      9 #include "ui/native_theme/native_theme.h"
     10 #include "ui/views/controls/menu/menu_controller.h"
     11 #include "ui/views/controls/menu/menu_host_root_view.h"
     12 #include "ui/views/controls/menu/menu_item_view.h"
     13 #include "ui/views/controls/menu/menu_scroll_view_container.h"
     14 #include "ui/views/controls/menu/submenu_view.h"
     15 #include "ui/views/round_rect_painter.h"
     16 #include "ui/views/widget/native_widget_private.h"
     17 #include "ui/views/widget/widget.h"
     18 
     19 #if defined(USE_AURA)
     20 #include "ui/views/corewm/shadow_types.h"
     21 #endif
     22 
     23 namespace views {
     24 
     25 ////////////////////////////////////////////////////////////////////////////////
     26 // MenuHost, public:
     27 
     28 MenuHost::MenuHost(SubmenuView* submenu)
     29     : submenu_(submenu),
     30       destroying_(false),
     31       ignore_capture_lost_(false) {
     32 }
     33 
     34 MenuHost::~MenuHost() {
     35 }
     36 
     37 void MenuHost::InitMenuHost(Widget* parent,
     38                             const gfx::Rect& bounds,
     39                             View* contents_view,
     40                             bool do_capture) {
     41   TRACE_EVENT0("views", "MenuHost::InitMenuHost");
     42   Widget::InitParams params(Widget::InitParams::TYPE_MENU);
     43   const MenuController* menu_controller =
     44       submenu_->GetMenuItem()->GetMenuController();
     45   const MenuConfig& menu_config = submenu_->GetMenuItem()->GetMenuConfig();
     46   bool rounded_border = menu_controller && menu_config.corner_radius > 0;
     47   bool bubble_border = submenu_->GetScrollViewContainer() &&
     48                        submenu_->GetScrollViewContainer()->HasBubbleBorder();
     49   params.has_dropshadow = !bubble_border;
     50   params.opacity = (bubble_border || rounded_border) ?
     51       Widget::InitParams::TRANSLUCENT_WINDOW :
     52       Widget::InitParams::OPAQUE_WINDOW;
     53   params.parent = parent ? parent->GetNativeView() : NULL;
     54   params.bounds = bounds;
     55   Init(params);
     56 
     57 #if defined(USE_AURA)
     58   if (bubble_border)
     59     SetShadowType(GetNativeView(), views::corewm::SHADOW_TYPE_NONE);
     60 #endif
     61 
     62   SetContentsView(contents_view);
     63   if (bubble_border || rounded_border)
     64     SetOpacity(0);
     65   ShowMenuHost(do_capture);
     66 }
     67 
     68 bool MenuHost::IsMenuHostVisible() {
     69   return IsVisible();
     70 }
     71 
     72 void MenuHost::ShowMenuHost(bool do_capture) {
     73   // Doing a capture may make us get capture lost. Ignore it while we're in the
     74   // process of showing.
     75   ignore_capture_lost_ = true;
     76   Show();
     77   if (do_capture)
     78     native_widget_private()->SetCapture();
     79   ignore_capture_lost_ = false;
     80 }
     81 
     82 void MenuHost::HideMenuHost() {
     83   ignore_capture_lost_ = true;
     84   ReleaseMenuHostCapture();
     85   Hide();
     86   ignore_capture_lost_ = false;
     87 }
     88 
     89 void MenuHost::DestroyMenuHost() {
     90   HideMenuHost();
     91   destroying_ = true;
     92   static_cast<MenuHostRootView*>(GetRootView())->ClearSubmenu();
     93   Close();
     94 }
     95 
     96 void MenuHost::SetMenuHostBounds(const gfx::Rect& bounds) {
     97   SetBounds(bounds);
     98 }
     99 
    100 void MenuHost::ReleaseMenuHostCapture() {
    101   if (native_widget_private()->HasCapture())
    102     native_widget_private()->ReleaseCapture();
    103 }
    104 
    105 ////////////////////////////////////////////////////////////////////////////////
    106 // MenuHost, Widget overrides:
    107 
    108 internal::RootView* MenuHost::CreateRootView() {
    109   return new MenuHostRootView(this, submenu_);
    110 }
    111 
    112 bool MenuHost::ShouldReleaseCaptureOnMouseReleased() const {
    113   return false;
    114 }
    115 
    116 void MenuHost::OnMouseCaptureLost() {
    117   if (destroying_ || ignore_capture_lost_)
    118     return;
    119   MenuController* menu_controller =
    120       submenu_->GetMenuItem()->GetMenuController();
    121   if (menu_controller && !menu_controller->drag_in_progress())
    122     menu_controller->CancelAll();
    123   Widget::OnMouseCaptureLost();
    124 }
    125 
    126 void MenuHost::OnNativeWidgetDestroyed() {
    127   if (!destroying_) {
    128     // We weren't explicitly told to destroy ourselves, which means the menu was
    129     // deleted out from under us (the window we're parented to was closed). Tell
    130     // the SubmenuView to drop references to us.
    131     submenu_->MenuHostDestroyed();
    132   }
    133   Widget::OnNativeWidgetDestroyed();
    134 }
    135 
    136 void MenuHost::OnOwnerClosing() {
    137   if (destroying_)
    138     return;
    139 
    140   MenuController* menu_controller =
    141       submenu_->GetMenuItem()->GetMenuController();
    142   if (menu_controller && !menu_controller->drag_in_progress())
    143     menu_controller->CancelAll();
    144 }
    145 
    146 }  // namespace views
    147