Home | History | Annotate | Download | only in touchui
      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/font_list.h"
     13 #include "ui/gfx/insets.h"
     14 #include "ui/gfx/text_utils.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"
     22 
     23 namespace {
     24 
     25 const int kMenuCommands[] = {IDS_APP_CUT,
     26                              IDS_APP_COPY,
     27                              IDS_APP_PASTE};
     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;
     33 
     34 const char* kEllipsesButtonText = "...";
     35 const int kEllipsesButtonTag = -1;
     36 }  // namespace
     37 
     38 namespace views {
     39 
     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_use_focusless(true);
     51   set_adjust_if_offscreen(true);
     52 
     53   SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0,
     54       kSpacingBetweenButtons));
     55   CreateButtons();
     56 
     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);
     65 
     66   views::BubbleDelegateView::CreateBubble(this);
     67   GetWidget()->Show();
     68 }
     69 
     70 TouchEditingMenuView::~TouchEditingMenuView() {
     71 }
     72 
     73 // static
     74 TouchEditingMenuView* TouchEditingMenuView::Create(
     75     TouchEditingMenuController* controller,
     76     const gfx::Rect& anchor_rect,
     77     const gfx::Size& handle_image_size,
     78     gfx::NativeView context) {
     79   if (controller) {
     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);
     84       }
     85     }
     86   }
     87   return NULL;
     88 }
     89 
     90 void TouchEditingMenuView::Close() {
     91   if (GetWidget()) {
     92     controller_ = NULL;
     93     GetWidget()->Close();
     94   }
     95 }
     96 
     97 void TouchEditingMenuView::WindowClosing() {
     98   views::BubbleDelegateView::WindowClosing();
     99   if (controller_)
    100     controller_->OnMenuClosed(this);
    101 }
    102 
    103 void TouchEditingMenuView::ButtonPressed(Button* sender,
    104                                          const ui::Event& event) {
    105   if (controller_) {
    106     if (sender->tag() != kEllipsesButtonTag)
    107       controller_->ExecuteCommand(sender->tag(), event.flags());
    108     else
    109       controller_->OpenContextMenu();
    110   }
    111 }
    112 
    113 void TouchEditingMenuView::OnPaint(gfx::Canvas* canvas) {
    114   BubbleDelegateView::OnPaint(canvas);
    115 
    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);
    122   }
    123 }
    124 
    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),
    131           command_id);
    132       AddChildView(button);
    133     }
    134   }
    135 
    136   // Finally, add ellipses button.
    137   AddChildView(CreateButton(
    138       base::UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag));
    139   Layout();
    140 }
    141 
    142 Button* TouchEditingMenuView::CreateButton(const base::string16& title,
    143                                            int tag) {
    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);
    160   return button;
    161 }
    162 
    163 }  // namespace views
    164