| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/touchui/touch_selection_menu_runner_views.h" | 5 #include "ui/views/touchui/touch_selection_menu_runner_views.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
| 12 #include "ui/base/l10n/l10n_util.h" | 12 #include "ui/base/l10n/l10n_util.h" |
| 13 #include "ui/base/resource/resource_bundle.h" | 13 #include "ui/base/resource/resource_bundle.h" |
| 14 #include "ui/gfx/canvas.h" | 14 #include "ui/gfx/canvas.h" |
| 15 #include "ui/gfx/geometry/rect.h" | 15 #include "ui/gfx/geometry/rect.h" |
| 16 #include "ui/gfx/geometry/size.h" | 16 #include "ui/gfx/geometry/size.h" |
| 17 #include "ui/gfx/text_utils.h" | 17 #include "ui/gfx/text_utils.h" |
| 18 #include "ui/strings/grit/ui_strings.h" | 18 #include "ui/strings/grit/ui_strings.h" |
| 19 #include "ui/views/bubble/bubble_delegate.h" | 19 #include "ui/views/bubble/bubble_dialog_delegate.h" |
| 20 #include "ui/views/controls/button/button.h" | 20 #include "ui/views/controls/button/button.h" |
| 21 #include "ui/views/controls/button/label_button.h" | 21 #include "ui/views/controls/button/label_button.h" |
| 22 #include "ui/views/layout/box_layout.h" | 22 #include "ui/views/layout/box_layout.h" |
| 23 | 23 |
| 24 namespace views { | 24 namespace views { |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 const int kMenuCommands[] = {IDS_APP_CUT, IDS_APP_COPY, IDS_APP_PASTE}; | 27 const int kMenuCommands[] = {IDS_APP_CUT, IDS_APP_COPY, IDS_APP_PASTE}; |
| 28 const int kSpacingBetweenButtons = 2; | 28 const int kSpacingBetweenButtons = 2; |
| 29 const int kButtonSeparatorColor = SkColorSetARGB(13, 0, 0, 0); | 29 const int kButtonSeparatorColor = SkColorSetARGB(13, 0, 0, 0); |
| 30 const int kMenuButtonMinHeight = 38; | 30 const int kMenuButtonMinHeight = 38; |
| 31 const int kMenuButtonMinWidth = 63; | 31 const int kMenuButtonMinWidth = 63; |
| 32 const int kMenuMargin = 1; | 32 const int kMenuMargin = 1; |
| 33 | 33 |
| 34 const char kEllipsesButtonText[] = "..."; | 34 const char kEllipsesButtonText[] = "..."; |
| 35 const int kEllipsesButtonTag = -1; | 35 const int kEllipsesButtonTag = -1; |
| 36 | 36 |
| 37 } // namespace | 37 } // namespace |
| 38 | 38 |
| 39 // A bubble that contains actions available for the selected text. An object of | 39 // A bubble that contains actions available for the selected text. An object of |
| 40 // this type, as a BubbleDelegateView, manages its own lifetime. | 40 // this type, as a BubbleDialogDelegateView, manages its own lifetime. |
| 41 class TouchSelectionMenuRunnerViews::Menu : public BubbleDelegateView, | 41 class TouchSelectionMenuRunnerViews::Menu : public BubbleDialogDelegateView, |
| 42 public ButtonListener { | 42 public ButtonListener { |
| 43 public: | 43 public: |
| 44 Menu(TouchSelectionMenuRunnerViews* owner, | 44 Menu(TouchSelectionMenuRunnerViews* owner, |
| 45 ui::TouchSelectionMenuClient* client, | 45 ui::TouchSelectionMenuClient* client, |
| 46 const gfx::Rect& anchor_rect, | 46 const gfx::Rect& anchor_rect, |
| 47 const gfx::Size& handle_image_size, | 47 const gfx::Size& handle_image_size, |
| 48 aura::Window* context); | 48 aura::Window* context); |
| 49 | 49 |
| 50 // Checks whether there is any command available to show in the menu. | 50 // Checks whether there is any command available to show in the menu. |
| 51 static bool IsMenuAvailable(const ui::TouchSelectionMenuClient* client); | 51 static bool IsMenuAvailable(const ui::TouchSelectionMenuClient* client); |
| 52 | 52 |
| 53 // Closes the menu. This will eventually self-destroy the object. | 53 // Closes the menu. This will eventually self-destroy the object. |
| 54 void Close(); | 54 void CloseMenu(); |
| 55 | 55 |
| 56 private: | 56 private: |
| 57 friend class TouchSelectionMenuRunnerViews::TestApi; | 57 friend class TouchSelectionMenuRunnerViews::TestApi; |
| 58 | 58 |
| 59 ~Menu() override; | 59 ~Menu() override; |
| 60 | 60 |
| 61 // Queries the |client_| for what commands to show in the menu and sizes the | 61 // Queries the |client_| for what commands to show in the menu and sizes the |
| 62 // menu appropriately. | 62 // menu appropriately. |
| 63 void CreateButtons(); | 63 void CreateButtons(); |
| 64 | 64 |
| 65 // Helper method to create a single button. | 65 // Helper method to create a single button. |
| 66 Button* CreateButton(const base::string16& title, int tag); | 66 Button* CreateButton(const base::string16& title, int tag); |
| 67 | 67 |
| 68 // Helper to disconnect this menu object from its owning menu runner. | 68 // Helper to disconnect this menu object from its owning menu runner. |
| 69 void DisconnectOwner(); | 69 void DisconnectOwner(); |
| 70 | 70 |
| 71 // BubbleDelegateView: | 71 // BubbleDialogDelegateView: |
| 72 void OnPaint(gfx::Canvas* canvas) override; | 72 void OnPaint(gfx::Canvas* canvas) override; |
| 73 void WindowClosing() override; | 73 void WindowClosing() override; |
| 74 int GetDialogButtons() const override; |
| 74 | 75 |
| 75 // ButtonListener: | 76 // ButtonListener: |
| 76 void ButtonPressed(Button* sender, const ui::Event& event) override; | 77 void ButtonPressed(Button* sender, const ui::Event& event) override; |
| 77 | 78 |
| 78 TouchSelectionMenuRunnerViews* owner_; | 79 TouchSelectionMenuRunnerViews* owner_; |
| 79 ui::TouchSelectionMenuClient* const client_; | 80 ui::TouchSelectionMenuClient* const client_; |
| 80 | 81 |
| 81 DISALLOW_COPY_AND_ASSIGN(Menu); | 82 DISALLOW_COPY_AND_ASSIGN(Menu); |
| 82 }; | 83 }; |
| 83 | 84 |
| 84 TouchSelectionMenuRunnerViews::Menu::Menu(TouchSelectionMenuRunnerViews* owner, | 85 TouchSelectionMenuRunnerViews::Menu::Menu(TouchSelectionMenuRunnerViews* owner, |
| 85 ui::TouchSelectionMenuClient* client, | 86 ui::TouchSelectionMenuClient* client, |
| 86 const gfx::Rect& anchor_rect, | 87 const gfx::Rect& anchor_rect, |
| 87 const gfx::Size& handle_image_size, | 88 const gfx::Size& handle_image_size, |
| 88 aura::Window* context) | 89 aura::Window* context) |
| 89 : BubbleDelegateView(nullptr, BubbleBorder::BOTTOM_CENTER), | 90 : BubbleDialogDelegateView(nullptr, BubbleBorder::BOTTOM_CENTER), |
| 90 owner_(owner), | 91 owner_(owner), |
| 91 client_(client) { | 92 client_(client) { |
| 92 DCHECK(owner_); | 93 DCHECK(owner_); |
| 93 DCHECK(client_); | 94 DCHECK(client_); |
| 94 | 95 |
| 95 set_shadow(BubbleBorder::SMALL_SHADOW); | 96 set_shadow(BubbleBorder::SMALL_SHADOW); |
| 96 set_parent_window(context); | 97 set_parent_window(context); |
| 97 set_margins(gfx::Insets(kMenuMargin, kMenuMargin, kMenuMargin, kMenuMargin)); | 98 set_margins(gfx::Insets(kMenuMargin, kMenuMargin, kMenuMargin, kMenuMargin)); |
| 98 set_can_activate(false); | 99 set_can_activate(false); |
| 99 set_adjust_if_offscreen(true); | 100 set_adjust_if_offscreen(true); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 110 int menu_width = GetPreferredSize().width(); | 111 int menu_width = GetPreferredSize().width(); |
| 111 // TODO(mfomitchev): This assumes that the handles are center-aligned to the | 112 // TODO(mfomitchev): This assumes that the handles are center-aligned to the |
| 112 // |achor_rect| edges, which is not true. We should fix this, perhaps by | 113 // |achor_rect| edges, which is not true. We should fix this, perhaps by |
| 113 // passing down the cumulative width occupied by the handles within | 114 // passing down the cumulative width occupied by the handles within |
| 114 // |anchor_rect| plus the handle image height instead of |handle_image_size|. | 115 // |anchor_rect| plus the handle image height instead of |handle_image_size|. |
| 115 // Perhaps we should also allow for some minimum padding. | 116 // Perhaps we should also allow for some minimum padding. |
| 116 if (menu_width > anchor_rect.width() - handle_image_size.width()) | 117 if (menu_width > anchor_rect.width() - handle_image_size.width()) |
| 117 adjusted_anchor_rect.Inset(0, 0, 0, -handle_image_size.height()); | 118 adjusted_anchor_rect.Inset(0, 0, 0, -handle_image_size.height()); |
| 118 SetAnchorRect(adjusted_anchor_rect); | 119 SetAnchorRect(adjusted_anchor_rect); |
| 119 | 120 |
| 120 BubbleDelegateView::CreateBubble(this); | 121 BubbleDialogDelegateView::CreateBubble(this); |
| 121 GetWidget()->Show(); | 122 GetWidget()->Show(); |
| 122 } | 123 } |
| 123 | 124 |
| 124 bool TouchSelectionMenuRunnerViews::Menu::IsMenuAvailable( | 125 bool TouchSelectionMenuRunnerViews::Menu::IsMenuAvailable( |
| 125 const ui::TouchSelectionMenuClient* client) { | 126 const ui::TouchSelectionMenuClient* client) { |
| 126 DCHECK(client); | 127 DCHECK(client); |
| 127 | 128 |
| 128 for (size_t i = 0; i < arraysize(kMenuCommands); i++) { | 129 for (size_t i = 0; i < arraysize(kMenuCommands); i++) { |
| 129 if (client->IsCommandIdEnabled(kMenuCommands[i])) | 130 if (client->IsCommandIdEnabled(kMenuCommands[i])) |
| 130 return true; | 131 return true; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 button->set_request_focus_on_press(false); | 164 button->set_request_focus_on_press(false); |
| 164 const gfx::FontList& font_list = | 165 const gfx::FontList& font_list = |
| 165 ui::ResourceBundle::GetSharedInstance().GetFontList( | 166 ui::ResourceBundle::GetSharedInstance().GetFontList( |
| 166 ui::ResourceBundle::SmallFont); | 167 ui::ResourceBundle::SmallFont); |
| 167 button->SetFontList(font_list); | 168 button->SetFontList(font_list); |
| 168 button->SetHorizontalAlignment(gfx::ALIGN_CENTER); | 169 button->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 169 button->set_tag(tag); | 170 button->set_tag(tag); |
| 170 return button; | 171 return button; |
| 171 } | 172 } |
| 172 | 173 |
| 173 void TouchSelectionMenuRunnerViews::Menu::Close() { | 174 void TouchSelectionMenuRunnerViews::Menu::CloseMenu() { |
| 174 DisconnectOwner(); | 175 DisconnectOwner(); |
| 175 // Closing the widget will self-destroy this object. | 176 // Closing the widget will self-destroy this object. |
| 176 Widget* widget = GetWidget(); | 177 Widget* widget = GetWidget(); |
| 177 if (widget && !widget->IsClosed()) | 178 if (widget && !widget->IsClosed()) |
| 178 widget->Close(); | 179 widget->Close(); |
| 179 } | 180 } |
| 180 | 181 |
| 181 void TouchSelectionMenuRunnerViews::Menu::DisconnectOwner() { | 182 void TouchSelectionMenuRunnerViews::Menu::DisconnectOwner() { |
| 182 DCHECK(owner_); | 183 DCHECK(owner_); |
| 183 owner_->menu_ = nullptr; | 184 owner_->menu_ = nullptr; |
| 184 owner_ = nullptr; | 185 owner_ = nullptr; |
| 185 } | 186 } |
| 186 | 187 |
| 187 void TouchSelectionMenuRunnerViews::Menu::OnPaint(gfx::Canvas* canvas) { | 188 void TouchSelectionMenuRunnerViews::Menu::OnPaint(gfx::Canvas* canvas) { |
| 188 BubbleDelegateView::OnPaint(canvas); | 189 BubbleDialogDelegateView::OnPaint(canvas); |
| 189 | 190 |
| 190 // Draw separator bars. | 191 // Draw separator bars. |
| 191 for (int i = 0; i < child_count() - 1; ++i) { | 192 for (int i = 0; i < child_count() - 1; ++i) { |
| 192 View* child = child_at(i); | 193 View* child = child_at(i); |
| 193 int x = child->bounds().right() + kSpacingBetweenButtons / 2; | 194 int x = child->bounds().right() + kSpacingBetweenButtons / 2; |
| 194 canvas->FillRect(gfx::Rect(x, 0, 1, child->height()), | 195 canvas->FillRect(gfx::Rect(x, 0, 1, child->height()), |
| 195 kButtonSeparatorColor); | 196 kButtonSeparatorColor); |
| 196 } | 197 } |
| 197 } | 198 } |
| 198 | 199 |
| 199 void TouchSelectionMenuRunnerViews::Menu::WindowClosing() { | 200 void TouchSelectionMenuRunnerViews::Menu::WindowClosing() { |
| 200 DCHECK(!owner_ || owner_->menu_ == this); | 201 DCHECK(!owner_ || owner_->menu_ == this); |
| 201 BubbleDelegateView::WindowClosing(); | 202 BubbleDialogDelegateView::WindowClosing(); |
| 202 if (owner_) | 203 if (owner_) |
| 203 DisconnectOwner(); | 204 DisconnectOwner(); |
| 204 } | 205 } |
| 205 | 206 |
| 207 int TouchSelectionMenuRunnerViews::Menu::GetDialogButtons() const { |
| 208 return ui::DIALOG_BUTTON_NONE; |
| 209 } |
| 210 |
| 206 void TouchSelectionMenuRunnerViews::Menu::ButtonPressed( | 211 void TouchSelectionMenuRunnerViews::Menu::ButtonPressed( |
| 207 Button* sender, | 212 Button* sender, |
| 208 const ui::Event& event) { | 213 const ui::Event& event) { |
| 209 Close(); | 214 CloseMenu(); |
| 210 if (sender->tag() != kEllipsesButtonTag) | 215 if (sender->tag() != kEllipsesButtonTag) |
| 211 client_->ExecuteCommand(sender->tag(), event.flags()); | 216 client_->ExecuteCommand(sender->tag(), event.flags()); |
| 212 else | 217 else |
| 213 client_->RunContextMenu(); | 218 client_->RunContextMenu(); |
| 214 } | 219 } |
| 215 | 220 |
| 216 TouchSelectionMenuRunnerViews::TestApi::TestApi( | 221 TouchSelectionMenuRunnerViews::TestApi::TestApi( |
| 217 TouchSelectionMenuRunnerViews* menu_runner) | 222 TouchSelectionMenuRunnerViews* menu_runner) |
| 218 : menu_runner_(menu_runner) { | 223 : menu_runner_(menu_runner) { |
| 219 DCHECK(menu_runner_); | 224 DCHECK(menu_runner_); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 | 262 |
| 258 if (TouchSelectionMenuRunnerViews::Menu::IsMenuAvailable(client)) | 263 if (TouchSelectionMenuRunnerViews::Menu::IsMenuAvailable(client)) |
| 259 menu_ = new Menu(this, client, anchor_rect, handle_image_size, context); | 264 menu_ = new Menu(this, client, anchor_rect, handle_image_size, context); |
| 260 } | 265 } |
| 261 | 266 |
| 262 void TouchSelectionMenuRunnerViews::CloseMenu() { | 267 void TouchSelectionMenuRunnerViews::CloseMenu() { |
| 263 if (!menu_) | 268 if (!menu_) |
| 264 return; | 269 return; |
| 265 | 270 |
| 266 // Closing the menu sets |menu_| to nullptr and eventually deletes the object. | 271 // Closing the menu sets |menu_| to nullptr and eventually deletes the object. |
| 267 menu_->Close(); | 272 menu_->CloseMenu(); |
| 268 DCHECK(!menu_); | 273 DCHECK(!menu_); |
| 269 } | 274 } |
| 270 | 275 |
| 271 bool TouchSelectionMenuRunnerViews::IsRunning() const { | 276 bool TouchSelectionMenuRunnerViews::IsRunning() const { |
| 272 return menu_ != nullptr; | 277 return menu_ != nullptr; |
| 273 } | 278 } |
| 274 | 279 |
| 275 } // namespace views | 280 } // namespace views |
| OLD | NEW |