15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_scroll_view_container.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPath.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/native_theme/native_theme_aura.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/bubble/bubble_border.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_config.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_controller.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/submenu_view.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/round_rect_painter.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::NativeTheme; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kBorderPaddingDueToRoundedCorners = 1; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuScrollButton ------------------------------------------------------------ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuScrollButton is used for the scroll buttons when not all menu items fit 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on screen. MenuScrollButton forwards appropriate events to the 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuController. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuScrollButton : public View { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuScrollButton(SubmenuView* host, bool is_up) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : host_(host), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_up_(is_up), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make our height the same as that of other MenuItemViews. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_height_(MenuItemView::pref_menu_height()) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Size GetPreferredSize() const OVERRIDE { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Size( 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->GetMenuItem()->GetMenuConfig().scroll_arrow_height * 2 - 1, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_height_); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool CanDrop(const OSExchangeData& data) OVERRIDE { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_->GetMenuItem()->GetMenuController()); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Always return true so that drop events are targeted to us. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_->GetMenuItem()->GetMenuController()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->GetMenuItem()->GetMenuController()->OnDragEnteredScrollButton( 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_, is_up_); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnDragExited() OVERRIDE { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_->GetMenuItem()->GetMenuController()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_->GetMenuItem()->GetMenuController()->OnDragExitedScrollButton(host_); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MenuConfig& config = host_->GetMenuItem()->GetMenuConfig(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The background. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect item_bounds(0, 0, width(), height()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeTheme::ExtraParams extra; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra.menu_item.is_selected = false; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNativeTheme()->Paint(canvas->sk_canvas(), 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeTheme::kMenuItemBackground, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeTheme::kNormal, item_bounds, extra); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then the arrow. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = width() / 2; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = (height() - config.scroll_arrow_height) / 2; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x_left = x - config.scroll_arrow_height; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x_right = x + config.scroll_arrow_height; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y_bottom; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_up_) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_bottom = y; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = y_bottom + config.scroll_arrow_height; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_bottom = y + config.scroll_arrow_height; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPath path; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.setFillType(SkPath::kWinding_FillType); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.moveTo(SkIntToScalar(x), SkIntToScalar(y)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.lineTo(SkIntToScalar(x_left), SkIntToScalar(y_bottom)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.lineTo(SkIntToScalar(x_right), SkIntToScalar(y_bottom)); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.lineTo(SkIntToScalar(x), SkIntToScalar(y)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPaint paint; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint.setStyle(SkPaint::kFill_Style); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint.setAntiAlias(true); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint.setColor(config.arrow_color); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawPath(path, paint); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SubmenuView we were created for. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SubmenuView* host_; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Direction of the button. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_up_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Preferred height. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pref_height_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MenuScrollButton); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuScrollView -------------------------------------------------------------- 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuScrollView is a viewport for the SubmenuView. It's reason to exist is so 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that ScrollRectToVisible works. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: It is possible to use ScrollView directly (after making it deal with 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// null scrollbars), but clicking on a child of ScrollView forces the window to 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// become active, which we don't want. As we really only need a fraction of 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// what ScrollView does, so we use a one off variant. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuScrollViewContainer::MenuScrollView : public View { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MenuScrollView(View* child) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(child); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void ScrollRectToVisible(const gfx::Rect& rect) OVERRIDE { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: this assumes we only want to scroll in the y direction. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If the rect is already visible, do not scroll. 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (GetLocalBounds().Contains(rect)) 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Scroll just enough so that the rect is visible. 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int dy = 0; 151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (rect.bottom() > GetLocalBounds().bottom()) 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dy = rect.bottom() - GetLocalBounds().bottom(); 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch else 154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dy = rect.y(); 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert rect.y() to view's coordinates and make sure we don't show past 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the bottom of the view. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* child = GetContents(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child->SetY(-std::max(0, std::min( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child->GetPreferredSize().height() - this->height(), 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dy - child->y()))); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the contents, which is the SubmenuView. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* GetContents() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child_at(0); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MenuScrollView); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MenuScrollViewContainer ---------------------------------------------------- 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : content_view_(content_view), 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arrow_(BubbleBorder::NONE), 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bubble_border_(NULL) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_up_button_ = new MenuScrollButton(content_view, true); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_down_button_ = new MenuScrollButton(content_view, false); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(scroll_up_button_); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(scroll_down_button_); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_view_ = new MenuScrollView(content_view); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(scroll_view_); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arrow_ = BubbleBorderTypeFromAnchor( 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition()); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (arrow_ != BubbleBorder::NONE) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateBubbleBorder(); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDefaultBorder(); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MenuScrollViewContainer::HasBubbleBorder() { 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return arrow_ != BubbleBorder::NONE; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MenuScrollViewContainer::SetBubbleArrowOffset(int offset) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(HasBubbleBorder()); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bubble_border_->set_arrow_offset(offset); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuScrollViewContainer::OnPaintBackground(gfx::Canvas* canvas) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (background()) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View::OnPaintBackground(canvas); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect bounds(0, 0, width(), height()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeTheme::ExtraParams extra; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const MenuConfig& menu_config = content_view_->GetMenuItem()->GetMenuConfig(); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extra.menu_background.corner_radius = menu_config.corner_radius; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNativeTheme()->Paint(canvas->sk_canvas(), 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeTheme::kMenuPopupBackground, NativeTheme::kNormal, bounds, extra); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuScrollViewContainer::Layout() { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Insets insets = GetInsets(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = insets.left(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = insets.top(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = View::width() - insets.width(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int content_height = height() - insets.height(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!scroll_up_button_->visible()) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_view_->SetBounds(x, y, width, content_height); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_view_->Layout(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size pref = scroll_up_button_->GetPreferredSize(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_up_button_->SetBounds(x, y, width, pref.height()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_height -= pref.height(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int scroll_view_y = y + pref.height(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref = scroll_down_button_->GetPreferredSize(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_down_button_->SetBounds(x, height() - pref.height() - insets.top(), 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width, pref.height()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_height -= pref.height(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_view_->SetBounds(x, scroll_view_y, width, content_height); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_view_->Layout(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size MenuScrollViewContainer::GetPreferredSize() const { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size prefsize = scroll_view_->GetContents()->GetPreferredSize(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Insets insets = GetInsets(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefsize.Enlarge(insets.width(), insets.height()); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return prefsize; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuScrollViewContainer::GetAccessibleState( 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui::AXViewState* state) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the name from the submenu view. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_view_->GetAccessibleState(state); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now change the role. 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_MENU_BAR; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some AT (like NVDA) will not process focus events on menu item children 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unless a parent claims to be focused. 262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch state->AddStateFlag(ui::AX_STATE_FOCUSED); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuScrollViewContainer::OnBoundsChanged( 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& previous_bounds) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size content_pref = scroll_view_->GetContents()->GetPreferredSize(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_up_button_->SetVisible(content_pref.height() > height()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_down_button_->SetVisible(content_pref.height() > height()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MenuScrollViewContainer::CreateDefaultBorder() { 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arrow_ = BubbleBorder::NONE; 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bubble_border_ = NULL; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const MenuConfig& menu_config = 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_view_->GetMenuItem()->GetMenuConfig(); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool use_border = true; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int padding = menu_config.corner_radius > 0 ? 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kBorderPaddingDueToRoundedCorners : 0; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_AURA) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS)) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (menu_config.native_theme == ui::NativeThemeAura::instance()) { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In case of NativeThemeAura the border gets drawn with the shadow. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Furthermore no additional padding is wanted. 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_border = false; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) padding = 0; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top = menu_config.menu_vertical_border_size + padding; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int left = menu_config.menu_horizontal_border_size + padding; 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom = menu_config.menu_vertical_border_size + padding; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int right = menu_config.menu_horizontal_border_size + padding; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (use_border) { 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetBorder(views::Border::CreateBorderPainter( 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new views::RoundRectPainter( 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) menu_config.native_theme->GetSystemColor( 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::NativeTheme::kColorId_MenuBorderColor), 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) menu_config.corner_radius), 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Insets(top, left, bottom, right))); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetBorder(Border::CreateEmptyBorder(top, left, bottom, right)); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MenuScrollViewContainer::CreateBubbleBorder() { 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bubble_border_ = new BubbleBorder(arrow_, 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BubbleBorder::SMALL_SHADOW, 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SK_ColorWHITE); 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetBorder(scoped_ptr<Border>(bubble_border_)); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_background(new BubbleBackground(bubble_border_)); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuBubbleBorder::Arrow MenuScrollViewContainer::BubbleBorderTypeFromAnchor( 3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MenuAnchorPosition anchor) { 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (anchor) { 3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case MENU_ANCHOR_BUBBLE_LEFT: 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BubbleBorder::RIGHT_CENTER; 3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case MENU_ANCHOR_BUBBLE_RIGHT: 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BubbleBorder::LEFT_CENTER; 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case MENU_ANCHOR_BUBBLE_ABOVE: 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BubbleBorder::BOTTOM_CENTER; 3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case MENU_ANCHOR_BUBBLE_BELOW: 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BubbleBorder::TOP_CENTER; 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BubbleBorder::NONE; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 335