普通文本  |  164行  |  5.32 KB

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/touchui/touch_editing_menu.h"

#include "base/strings/utf_string_conversions.h"
#include "grit/ui_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"

namespace {

const int kMenuCommands[] = {IDS_APP_CUT,
                             IDS_APP_COPY,
                             IDS_APP_PASTE};
const int kSpacingBetweenButtons = 2;
const int kButtonSeparatorColor = SkColorSetARGB(13, 0, 0, 0);
const int kMenuButtonHeight = 38;
const int kMenuButtonWidth = 63;
const int kMenuMargin = 1;

const char* kEllipsesButtonText = "...";
const int kEllipsesButtonTag = -1;
}  // namespace

namespace views {

TouchEditingMenuView::TouchEditingMenuView(
    TouchEditingMenuController* controller,
    const gfx::Rect& anchor_rect,
    const gfx::Size& handle_image_size,
    gfx::NativeView context)
    : BubbleDelegateView(NULL, views::BubbleBorder::BOTTOM_CENTER),
      controller_(controller) {
  set_shadow(views::BubbleBorder::SMALL_SHADOW);
  set_parent_window(context);
  set_margins(gfx::Insets(kMenuMargin, kMenuMargin, kMenuMargin, kMenuMargin));
  set_use_focusless(true);
  set_adjust_if_offscreen(true);

  SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0,
      kSpacingBetweenButtons));
  CreateButtons();

  // After buttons are created, check if there is enough room between handles to
  // show the menu and adjust anchor rect properly if needed, just in case the
  // menu is needed to be shown under the selection.
  gfx::Rect adjusted_anchor_rect(anchor_rect);
  int menu_width = GetPreferredSize().width();
  if (menu_width > anchor_rect.width() - handle_image_size.width())
    adjusted_anchor_rect.Inset(0, 0, 0, -handle_image_size.height());
  SetAnchorRect(adjusted_anchor_rect);

  views::BubbleDelegateView::CreateBubble(this);
  GetWidget()->Show();
}

TouchEditingMenuView::~TouchEditingMenuView() {
}

// static
TouchEditingMenuView* TouchEditingMenuView::Create(
    TouchEditingMenuController* controller,
    const gfx::Rect& anchor_rect,
    const gfx::Size& handle_image_size,
    gfx::NativeView context) {
  if (controller) {
    for (size_t i = 0; i < arraysize(kMenuCommands); i++) {
      if (controller->IsCommandIdEnabled(kMenuCommands[i])) {
        return new TouchEditingMenuView(controller, anchor_rect,
                                        handle_image_size, context);
      }
    }
  }
  return NULL;
}

void TouchEditingMenuView::Close() {
  if (GetWidget()) {
    controller_ = NULL;
    GetWidget()->Close();
  }
}

void TouchEditingMenuView::WindowClosing() {
  views::BubbleDelegateView::WindowClosing();
  if (controller_)
    controller_->OnMenuClosed(this);
}

void TouchEditingMenuView::ButtonPressed(Button* sender,
                                         const ui::Event& event) {
  if (controller_) {
    if (sender->tag() != kEllipsesButtonTag)
      controller_->ExecuteCommand(sender->tag(), event.flags());
    else
      controller_->OpenContextMenu();
  }
}

void TouchEditingMenuView::OnPaint(gfx::Canvas* canvas) {
  BubbleDelegateView::OnPaint(canvas);

  // Draw separator bars.
  for (int i = 0; i < child_count() - 1; ++i) {
    View* child = child_at(i);
    int x = child->bounds().right() + kSpacingBetweenButtons / 2;
    canvas->FillRect(gfx::Rect(x, 0, 1, child->height()),
        kButtonSeparatorColor);
  }
}

void TouchEditingMenuView::CreateButtons() {
  RemoveAllChildViews(true);
  for (size_t i = 0; i < arraysize(kMenuCommands); i++) {
    int command_id = kMenuCommands[i];
    if (controller_ && controller_->IsCommandIdEnabled(command_id)) {
      Button* button = CreateButton(l10n_util::GetStringUTF16(command_id),
          command_id);
      AddChildView(button);
    }
  }

  // Finally, add ellipses button.
  AddChildView(CreateButton(
      base::UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag));
  Layout();
}

Button* TouchEditingMenuView::CreateButton(const base::string16& title,
                                           int tag) {
  base::string16 label = gfx::RemoveAcceleratorChar(title, '&', NULL, NULL);
  LabelButton* button = new LabelButton(this, label);
  button->SetFocusable(true);
  button->set_request_focus_on_press(false);
  const gfx::FontList& font_list =
      ui::ResourceBundle::GetSharedInstance().GetFontList(
          ui::ResourceBundle::SmallFont);
  scoped_ptr<LabelButtonBorder> button_border(
      new LabelButtonBorder(button->style()));
  int v_border = (kMenuButtonHeight - font_list.GetHeight()) / 2;
  int h_border = (kMenuButtonWidth - gfx::GetStringWidth(label, font_list)) / 2;
  button_border->set_insets(
      gfx::Insets(v_border, h_border, v_border, h_border));
  button->SetBorder(button_border.PassAs<Border>());
  button->SetFontList(font_list);
  button->set_tag(tag);
  return button;
}

}  // namespace views