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.
5 #include "ui/views/touchui/touch_editing_menu.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "ui/base/l10n/l10n_util.h"
9 #include "ui/base/resource/resource_bundle.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/gfx/font_list.h"
12 #include "ui/gfx/insets.h"
13 #include "ui/gfx/text_utils.h"
14 #include "ui/strings/grit/ui_strings.h"
15 #include "ui/views/bubble/bubble_border.h"
16 #include "ui/views/bubble/bubble_frame_view.h"
17 #include "ui/views/controls/button/custom_button.h"
18 #include "ui/views/controls/button/label_button.h"
19 #include "ui/views/controls/button/label_button_border.h"
20 #include "ui/views/layout/box_layout.h"
21 #include "ui/views/widget/widget.h"
25 const int kMenuCommands
[] = {IDS_APP_CUT
,
28 const int kSpacingBetweenButtons
= 2;
29 const int kButtonSeparatorColor
= SkColorSetARGB(13, 0, 0, 0);
30 const int kMenuButtonHeight
= 38;
31 const int kMenuButtonWidth
= 63;
32 const int kMenuMargin
= 1;
34 const char* kEllipsesButtonText
= "...";
35 const int kEllipsesButtonTag
= -1;
40 TouchEditingMenuView::TouchEditingMenuView(
41 TouchEditingMenuController
* controller
,
42 const gfx::Rect
& anchor_rect
,
43 const gfx::Size
& handle_image_size
,
44 gfx::NativeView context
)
45 : BubbleDelegateView(NULL
, views::BubbleBorder::BOTTOM_CENTER
),
46 controller_(controller
) {
47 set_shadow(views::BubbleBorder::SMALL_SHADOW
);
48 set_parent_window(context
);
49 set_margins(gfx::Insets(kMenuMargin
, kMenuMargin
, kMenuMargin
, kMenuMargin
));
50 set_can_activate(false);
51 set_adjust_if_offscreen(true);
53 SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal
, 0, 0,
54 kSpacingBetweenButtons
));
57 // After buttons are created, check if there is enough room between handles to
58 // show the menu and adjust anchor rect properly if needed, just in case the
59 // menu is needed to be shown under the selection.
60 gfx::Rect
adjusted_anchor_rect(anchor_rect
);
61 int menu_width
= GetPreferredSize().width();
62 if (menu_width
> anchor_rect
.width() - handle_image_size
.width())
63 adjusted_anchor_rect
.Inset(0, 0, 0, -handle_image_size
.height());
64 SetAnchorRect(adjusted_anchor_rect
);
66 views::BubbleDelegateView::CreateBubble(this);
70 TouchEditingMenuView::~TouchEditingMenuView() {
74 TouchEditingMenuView
* TouchEditingMenuView::Create(
75 TouchEditingMenuController
* controller
,
76 const gfx::Rect
& anchor_rect
,
77 const gfx::Size
& handle_image_size
,
78 gfx::NativeView context
) {
80 for (size_t i
= 0; i
< arraysize(kMenuCommands
); i
++) {
81 if (controller
->IsCommandIdEnabled(kMenuCommands
[i
])) {
82 return new TouchEditingMenuView(controller
, anchor_rect
,
83 handle_image_size
, context
);
90 void TouchEditingMenuView::Close() {
97 void TouchEditingMenuView::WindowClosing() {
98 views::BubbleDelegateView::WindowClosing();
100 controller_
->OnMenuClosed(this);
103 void TouchEditingMenuView::ButtonPressed(Button
* sender
,
104 const ui::Event
& event
) {
106 if (sender
->tag() != kEllipsesButtonTag
)
107 controller_
->ExecuteCommand(sender
->tag(), event
.flags());
109 controller_
->OpenContextMenu();
113 void TouchEditingMenuView::OnPaint(gfx::Canvas
* canvas
) {
114 BubbleDelegateView::OnPaint(canvas
);
116 // Draw separator bars.
117 for (int i
= 0; i
< child_count() - 1; ++i
) {
118 View
* child
= child_at(i
);
119 int x
= child
->bounds().right() + kSpacingBetweenButtons
/ 2;
120 canvas
->FillRect(gfx::Rect(x
, 0, 1, child
->height()),
121 kButtonSeparatorColor
);
125 void TouchEditingMenuView::CreateButtons() {
126 RemoveAllChildViews(true);
127 for (size_t i
= 0; i
< arraysize(kMenuCommands
); i
++) {
128 int command_id
= kMenuCommands
[i
];
129 if (controller_
&& controller_
->IsCommandIdEnabled(command_id
)) {
130 Button
* button
= CreateButton(l10n_util::GetStringUTF16(command_id
),
132 AddChildView(button
);
136 // Finally, add ellipses button.
137 AddChildView(CreateButton(
138 base::UTF8ToUTF16(kEllipsesButtonText
), kEllipsesButtonTag
));
142 Button
* TouchEditingMenuView::CreateButton(const base::string16
& title
,
144 base::string16 label
= gfx::RemoveAcceleratorChar(title
, '&', NULL
, NULL
);
145 LabelButton
* button
= new LabelButton(this, label
);
146 button
->SetFocusable(true);
147 button
->set_request_focus_on_press(false);
148 const gfx::FontList
& font_list
=
149 ui::ResourceBundle::GetSharedInstance().GetFontList(
150 ui::ResourceBundle::SmallFont
);
151 scoped_ptr
<LabelButtonBorder
> button_border(
152 new LabelButtonBorder(button
->style()));
153 int v_border
= (kMenuButtonHeight
- font_list
.GetHeight()) / 2;
154 int h_border
= (kMenuButtonWidth
- gfx::GetStringWidth(label
, font_list
)) / 2;
155 button_border
->set_insets(
156 gfx::Insets(v_border
, h_border
, v_border
, h_border
));
157 button
->SetBorder(button_border
.PassAs
<Border
>());
158 button
->SetFontList(font_list
);
159 button
->set_tag(tag
);