1 // Copyright (c) 2013 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/touchui/touch_editing_menu.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "grit/ui_strings.h" 9 #include "ui/base/l10n/l10n_util.h" 10 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/insets.h" 13 #include "ui/gfx/text_utils.h" 14 #include "ui/views/bubble/bubble_border.h" 15 #include "ui/views/bubble/bubble_frame_view.h" 16 #include "ui/views/controls/button/custom_button.h" 17 #include "ui/views/controls/button/label_button.h" 18 #include "ui/views/controls/button/label_button_border.h" 19 #include "ui/views/layout/box_layout.h" 20 #include "ui/views/widget/widget.h" 21 22 namespace { 23 24 const int kMenuCommands[] = {IDS_APP_CUT, 25 IDS_APP_COPY, 26 IDS_APP_PASTE}; 27 const int kSpacingBetweenButtons = 2; 28 const int kButtonSeparatorColor = SkColorSetARGB(13, 0, 0, 0); 29 const int kMenuButtonHeight = 38; 30 const int kMenuButtonWidth = 63; 31 const int kMenuMargin = 1; 32 const SkColor kMenuButtonColorNormal = SkColorSetARGB(102, 255, 255, 255); 33 const SkColor kMenuButtonColorHover = SkColorSetARGB(13, 0, 0, 0); 34 35 const char* kEllipsesButtonText = "..."; 36 const int kEllipsesButtonTag = -1; 37 } // namespace 38 39 namespace views { 40 41 class TouchEditingMenuButtonBorder : public LabelButtonBorder { 42 public: 43 TouchEditingMenuButtonBorder(Button::ButtonStyle style, 44 const gfx::Insets& insets) 45 : LabelButtonBorder(style), 46 insets_(insets) { 47 } 48 49 virtual ~TouchEditingMenuButtonBorder() { 50 } 51 52 private: 53 // Overridden from LabelButtonBorder 54 virtual gfx::Insets GetInsets() const OVERRIDE { 55 return insets_; 56 } 57 58 gfx::Insets insets_; 59 60 DISALLOW_COPY_AND_ASSIGN(TouchEditingMenuButtonBorder); 61 }; 62 63 TouchEditingMenuView::TouchEditingMenuView( 64 TouchEditingMenuController* controller, 65 gfx::Rect anchor_rect, 66 gfx::NativeView context) 67 : BubbleDelegateView(NULL, views::BubbleBorder::BOTTOM_CENTER), 68 controller_(controller) { 69 set_anchor_rect(anchor_rect); 70 set_shadow(views::BubbleBorder::SMALL_SHADOW); 71 set_parent_window(context); 72 set_margins(gfx::Insets(kMenuMargin, kMenuMargin, kMenuMargin, kMenuMargin)); 73 set_use_focusless(true); 74 set_adjust_if_offscreen(true); 75 76 SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0, 77 kSpacingBetweenButtons)); 78 CreateButtons(); 79 views::BubbleDelegateView::CreateBubble(this); 80 GetWidget()->Show(); 81 } 82 83 TouchEditingMenuView::~TouchEditingMenuView() { 84 } 85 86 // static 87 TouchEditingMenuView* TouchEditingMenuView::Create( 88 TouchEditingMenuController* controller, 89 gfx::Rect anchor_rect, 90 gfx::NativeView context) { 91 if (controller) { 92 for (size_t i = 0; i < arraysize(kMenuCommands); i++) { 93 if (controller->IsCommandIdEnabled(kMenuCommands[i])) 94 return new TouchEditingMenuView(controller, anchor_rect, context); 95 } 96 } 97 return NULL; 98 } 99 100 void TouchEditingMenuView::Close() { 101 if (GetWidget()) { 102 controller_ = NULL; 103 GetWidget()->Close(); 104 } 105 } 106 107 void TouchEditingMenuView::WindowClosing() { 108 views::BubbleDelegateView::WindowClosing(); 109 if (controller_) 110 controller_->OnMenuClosed(this); 111 } 112 113 void TouchEditingMenuView::ButtonPressed(Button* sender, 114 const ui::Event& event) { 115 if (controller_) { 116 if (sender->tag() != kEllipsesButtonTag) 117 controller_->ExecuteCommand(sender->tag(), event.flags()); 118 else 119 controller_->OpenContextMenu(); 120 } 121 } 122 123 void TouchEditingMenuView::OnPaint(gfx::Canvas* canvas) { 124 BubbleDelegateView::OnPaint(canvas); 125 126 // Draw separator bars. 127 for (int i = 0; i < child_count() - 1; ++i) { 128 View* child = child_at(i); 129 int x = child->bounds().right() + kSpacingBetweenButtons / 2; 130 canvas->FillRect(gfx::Rect(x, 0, 1, child->height()), 131 kButtonSeparatorColor); 132 } 133 } 134 135 void TouchEditingMenuView::CreateButtons() { 136 RemoveAllChildViews(true); 137 for (size_t i = 0; i < arraysize(kMenuCommands); i++) { 138 int command_id = kMenuCommands[i]; 139 if (controller_ && controller_->IsCommandIdEnabled(command_id)) { 140 Button* button = CreateButton(l10n_util::GetStringUTF16(command_id), 141 command_id); 142 AddChildView(button); 143 } 144 } 145 146 // Finally, add ellipses button. 147 AddChildView(CreateButton( 148 UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag)); 149 Layout(); 150 } 151 152 Button* TouchEditingMenuView::CreateButton(const string16& title, int tag) { 153 string16 label = gfx::RemoveAcceleratorChar(title, '&', NULL, NULL); 154 LabelButton* button = new LabelButton(this, label); 155 button->set_focusable(true); 156 button->set_request_focus_on_press(false); 157 gfx::Font font = ui::ResourceBundle::GetSharedInstance().GetFont( 158 ui::ResourceBundle::SmallFont); 159 int v_border = (kMenuButtonHeight - font.GetHeight()) / 2; 160 int h_border = (kMenuButtonWidth - font.GetStringWidth(label)) / 2; 161 button->set_border(new TouchEditingMenuButtonBorder(button->style(), 162 gfx::Insets(v_border, h_border, v_border, h_border))); 163 button->SetFont(font); 164 button->set_tag(tag); 165 return button; 166 } 167 168 } // namespace views 169