Index: views/touchui/touch_selection_controller_impl.cc |
diff --git a/views/touchui/touch_selection_controller_impl.cc b/views/touchui/touch_selection_controller_impl.cc |
deleted file mode 100644 |
index e590216e9bbfeba77b040cca0683637140216d3d..0000000000000000000000000000000000000000 |
--- a/views/touchui/touch_selection_controller_impl.cc |
+++ /dev/null |
@@ -1,508 +0,0 @@ |
-// Copyright (c) 2011 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 "views/touchui/touch_selection_controller_impl.h" |
- |
-#include "base/time.h" |
-#include "base/utf_string_conversions.h" |
-#include "grit/ui_strings.h" |
-#include "third_party/skia/include/effects/SkGradientShader.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/base/resource/resource_bundle.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/canvas_skia.h" |
-#include "ui/gfx/path.h" |
-#include "ui/gfx/rect.h" |
-#include "ui/gfx/screen.h" |
-#include "ui/gfx/size.h" |
-#include "ui/gfx/transform.h" |
-#include "views/background.h" |
-#include "views/controls/button/button.h" |
-#include "views/controls/button/custom_button.h" |
-#include "views/controls/button/text_button.h" |
-#include "views/controls/label.h" |
-#include "views/controls/menu/menu_config.h" |
-#include "views/layout/box_layout.h" |
-#include "views/widget/widget.h" |
- |
-namespace { |
- |
-// Constants defining the visual attributes of selection handles |
-const int kSelectionHandleRadius = 10; |
-const int kSelectionHandleCursorHeight = 10; |
-const int kSelectionHandleAlpha = 0x7F; |
-const SkColor kSelectionHandleColor = |
- SkColorSetA(SK_ColorBLUE, kSelectionHandleAlpha); |
- |
-// The minimum selection size to trigger selection controller. |
-const int kMinSelectionSize = 4; |
- |
-const int kContextMenuCommands[] = {IDS_APP_CUT, |
- IDS_APP_COPY, |
-// TODO(varunjain): PASTE is acting funny due to some gtk clipboard issue. |
-// Uncomment the following when that is fixed. |
-// IDS_APP_PASTE, |
- IDS_APP_DELETE, |
- IDS_APP_SELECT_ALL}; |
-const int kContextMenuPadding = 2; |
-const int kContextMenuTimoutMs = 1000; |
-const int kContextMenuVerticalOffset = 25; |
- |
-// Convenience struct to represent a circle shape. |
-struct Circle { |
- int radius; |
- gfx::Point center; |
- SkColor color; |
-}; |
- |
-// Creates a widget to host SelectionHandleView. |
-views::Widget* CreateTouchSelectionPopupWidget() { |
- views::Widget* widget = new views::Widget; |
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
- params.can_activate = false; |
- params.transparent = true; |
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- widget->Init(params); |
- return widget; |
-} |
- |
-void PaintCircle(const Circle& circle, gfx::Canvas* canvas) { |
- SkPaint paint; |
- paint.setAntiAlias(true); |
- paint.setStyle(SkPaint::kFill_Style); |
- paint.setColor(circle.color); |
- gfx::Path path; |
- gfx::Rect bounds(circle.center.x() - circle.radius, |
- circle.center.y() - circle.radius, |
- circle.radius * 2, |
- circle.radius * 2); |
- SkRect rect; |
- rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()), |
- SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom())); |
- SkScalar radius = SkIntToScalar(circle.radius); |
- path.addRoundRect(rect, radius, radius); |
- canvas->GetSkCanvas()->drawPath(path, paint); |
-} |
- |
-// The points may not match exactly, since the selection range computation may |
-// introduce some floating point errors. So check for a minimum size to decide |
-// whether or not there is any selection. |
-bool IsEmptySelection(const gfx::Point& p1, const gfx::Point& p2) { |
- int delta_x = p2.x() - p1.x(); |
- int delta_y = p2.y() - p1.y(); |
- return (abs(delta_x) < kMinSelectionSize && abs(delta_y) < kMinSelectionSize); |
-} |
- |
-} // namespace |
- |
-namespace views { |
- |
-// A View that displays the text selection handle. |
-class TouchSelectionControllerImpl::SelectionHandleView : public View { |
- public: |
- SelectionHandleView(TouchSelectionControllerImpl* controller) |
- : controller_(controller) { |
- widget_.reset(CreateTouchSelectionPopupWidget()); |
- widget_->SetContentsView(this); |
- widget_->SetAlwaysOnTop(true); |
- |
- // We are owned by the TouchSelectionController. |
- set_parent_owned(false); |
- } |
- |
- virtual ~SelectionHandleView() { |
- } |
- |
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { |
- Circle circle = {kSelectionHandleRadius, gfx::Point(kSelectionHandleRadius, |
- kSelectionHandleRadius + kSelectionHandleCursorHeight), |
- kSelectionHandleColor}; |
- PaintCircle(circle, canvas); |
- canvas->DrawLineInt(kSelectionHandleColor, kSelectionHandleRadius, 0, |
- kSelectionHandleRadius, kSelectionHandleCursorHeight); |
- } |
- |
- virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE { |
- controller_->dragging_handle_ = this; |
- return true; |
- } |
- |
- virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE { |
- controller_->SelectionHandleDragged(event.location()); |
- return true; |
- } |
- |
- virtual void OnMouseReleased(const MouseEvent& event) OVERRIDE { |
- controller_->dragging_handle_ = NULL; |
- } |
- |
- virtual void OnMouseCaptureLost() OVERRIDE { |
- controller_->dragging_handle_ = NULL; |
- } |
- |
- virtual void SetVisible(bool visible) OVERRIDE { |
- // We simply show/hide the container widget. |
- if (visible != widget_->IsVisible()) { |
- if (visible) |
- widget_->Show(); |
- else |
- widget_->Hide(); |
- } |
- View::SetVisible(visible); |
- } |
- |
- virtual gfx::Size GetPreferredSize() OVERRIDE { |
- return gfx::Size(2 * kSelectionHandleRadius, |
- 2 * kSelectionHandleRadius + kSelectionHandleCursorHeight); |
- } |
- |
- void SetScreenPosition(const gfx::Point& position) { |
- gfx::Rect widget_bounds(position.x() - kSelectionHandleRadius, position.y(), |
- 2 * kSelectionHandleRadius, |
- 2 * kSelectionHandleRadius + kSelectionHandleCursorHeight); |
- widget_->SetBounds(widget_bounds); |
- } |
- |
- gfx::Point GetScreenPosition() { |
- return widget_->GetClientAreaScreenBounds().origin(); |
- } |
- |
- private: |
- scoped_ptr<Widget> widget_; |
- TouchSelectionControllerImpl* controller_; |
- |
- DISALLOW_COPY_AND_ASSIGN(SelectionHandleView); |
-}; |
- |
-class ContextMenuButtonBackground : public Background { |
- public: |
- ContextMenuButtonBackground() {} |
- |
- virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { |
- CustomButton::ButtonState state = static_cast<CustomButton*>(view)->state(); |
- SkColor background_color, border_color; |
- if (state == CustomButton::BS_NORMAL) { |
- background_color = SkColorSetARGB(102, 255, 255, 255); |
- border_color = SkColorSetARGB(36, 0, 0, 0); |
- } else { |
- background_color = SkColorSetARGB(13, 0, 0, 0); |
- border_color = SkColorSetARGB(72, 0, 0, 0); |
- } |
- int w = view->width(); |
- int h = view->height(); |
- canvas->FillRect(background_color, gfx::Rect(1, 1, w - 2, h - 2)); |
- canvas->FillRect(border_color, gfx::Rect(2, 0, w - 4, 1)); |
- canvas->FillRect(border_color, gfx::Rect(1, 1, 1, 1)); |
- canvas->FillRect(border_color, gfx::Rect(0, 2, 1, h - 4)); |
- canvas->FillRect(border_color, gfx::Rect(1, h - 2, 1, 1)); |
- canvas->FillRect(border_color, gfx::Rect(2, h - 1, w - 4, 1)); |
- canvas->FillRect(border_color, gfx::Rect(w - 2, 1, 1, 1)); |
- canvas->FillRect(border_color, gfx::Rect(w - 1, 2, 1, h - 4)); |
- canvas->FillRect(border_color, gfx::Rect(w - 2, h - 2, 1, 1)); |
- } |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(ContextMenuButtonBackground); |
-}; |
- |
-// A View that displays the touch context menu. |
-class TouchSelectionControllerImpl::TouchContextMenuView |
- : public ButtonListener, |
- public View { |
- public: |
- TouchContextMenuView(TouchSelectionControllerImpl* controller) |
- : controller_(controller) { |
- widget_.reset(CreateTouchSelectionPopupWidget()); |
- widget_->SetContentsView(this); |
- widget_->SetAlwaysOnTop(true); |
- |
- // We are owned by the TouchSelectionController. |
- set_parent_owned(false); |
- SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, kContextMenuPadding, |
- kContextMenuPadding, kContextMenuPadding)); |
- } |
- |
- virtual ~TouchContextMenuView() { |
- } |
- |
- virtual void SetVisible(bool visible) OVERRIDE { |
- // We simply show/hide the container widget. |
- if (visible != widget_->IsVisible()) { |
- if (visible) |
- widget_->Show(); |
- else |
- widget_->Hide(); |
- } |
- View::SetVisible(visible); |
- } |
- |
- void SetScreenPosition(const gfx::Point& position) { |
- RefreshButtonsAndSetWidgetPosition(position); |
- } |
- |
- gfx::Point GetScreenPosition() { |
- return widget_->GetClientAreaScreenBounds().origin(); |
- } |
- |
- void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE { |
- // TODO(varunjain): the following color scheme is copied from |
- // menu_scroll_view_container.cc. Figure out how to consolidate the two |
- // pieces of code. |
-#if defined(OS_CHROMEOS) |
- static const SkColor kGradientColors[2] = { |
- SK_ColorWHITE, |
- SkColorSetRGB(0xF0, 0xF0, 0xF0) |
- }; |
- |
- static const SkScalar kGradientPoints[2] = { |
- SkIntToScalar(0), |
- SkIntToScalar(1) |
- }; |
- |
- SkPoint points[2]; |
- points[0].set(SkIntToScalar(0), SkIntToScalar(0)); |
- points[1].set(SkIntToScalar(0), SkIntToScalar(height())); |
- |
- SkShader* shader = SkGradientShader::CreateLinear(points, |
- kGradientColors, kGradientPoints, arraysize(kGradientPoints), |
- SkShader::kRepeat_TileMode); |
- DCHECK(shader); |
- |
- SkPaint paint; |
- paint.setShader(shader); |
- shader->unref(); |
- |
- paint.setStyle(SkPaint::kFill_Style); |
- paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
- |
- canvas->DrawRectInt(0, 0, width(), height(), paint); |
-#else |
- // This is the same as COLOR_TOOLBAR. |
- canvas->GetSkCanvas()->drawColor(SkColorSetRGB(210, 225, 246), |
- SkXfermode::kSrc_Mode); |
-#endif |
- } |
- |
- // ButtonListener |
- virtual void ButtonPressed(Button* sender, const views::Event& event) { |
- controller_->ExecuteCommand(sender->tag()); |
- } |
- |
- private: |
- // Queries the client view for what elements to show in the menu and sizes |
- // the menu appropriately. |
- void RefreshButtonsAndSetWidgetPosition(const gfx::Point& position) { |
- RemoveAllChildViews(true); |
- int total_width = 0; |
- int height = 0; |
- for (size_t i = 0; i < arraysize(kContextMenuCommands); i++) { |
- int command_id = kContextMenuCommands[i]; |
- if (controller_->IsCommandIdEnabled(command_id)) { |
- TextButton* button = new TextButton( |
- this, l10n_util::GetStringUTF16(command_id)); |
- button->set_focusable(true); |
- button->set_request_focus_on_press(false); |
- button->set_prefix_type(TextButton::PREFIX_HIDE); |
- button->SetEnabledColor(MenuConfig::instance().text_color); |
- button->set_background(new ContextMenuButtonBackground()); |
- button->set_alignment(TextButton::ALIGN_CENTER); |
- button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont( |
- ui::ResourceBundle::LargeFont)); |
- button->set_tag(command_id); |
- AddChildView(button); |
- gfx::Size button_size = button->GetPreferredSize(); |
- total_width += button_size.width() + kContextMenuPadding; |
- if (height < button_size.height()) |
- height = button_size.height(); |
- } |
- } |
- gfx::Rect widget_bounds(position.x() - total_width / 2, |
- position.y() - height, |
- total_width, |
- height); |
- gfx::Rect monitor_bounds = |
- gfx::Screen::GetMonitorAreaNearestPoint(position); |
- widget_->SetBounds(widget_bounds.AdjustToFit(monitor_bounds)); |
- Layout(); |
- } |
- |
- scoped_ptr<Widget> widget_; |
- TouchSelectionControllerImpl* controller_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TouchContextMenuView); |
-}; |
- |
-TouchSelectionControllerImpl::TouchSelectionControllerImpl( |
- TouchSelectionClientView* client_view) |
- : client_view_(client_view), |
- selection_handle_1_(new SelectionHandleView(this)), |
- selection_handle_2_(new SelectionHandleView(this)), |
- context_menu_(new TouchContextMenuView(this)), |
- dragging_handle_(NULL) { |
-} |
- |
-TouchSelectionControllerImpl::~TouchSelectionControllerImpl() { |
-} |
- |
-void TouchSelectionControllerImpl::SelectionChanged(const gfx::Point& p1, |
- const gfx::Point& p2) { |
- gfx::Point screen_pos_1(p1); |
- View::ConvertPointToScreen(client_view_, &screen_pos_1); |
- gfx::Point screen_pos_2(p2); |
- View::ConvertPointToScreen(client_view_, &screen_pos_2); |
- |
- if (dragging_handle_) { |
- // We need to reposition only the selection handle that is being dragged. |
- // The other handle stays the same. Also, the selection handle being dragged |
- // will always be at the end of selection, while the other handle will be at |
- // the start. |
- dragging_handle_->SetScreenPosition(screen_pos_2); |
- } else { |
- UpdateContextMenu(p1, p2); |
- |
- // Check if there is any selection at all. |
- if (IsEmptySelection(screen_pos_2, screen_pos_1)) { |
- selection_handle_1_->SetVisible(false); |
- selection_handle_2_->SetVisible(false); |
- return; |
- } |
- |
- if (client_view_->bounds().Contains(p1)) { |
- selection_handle_1_->SetScreenPosition(screen_pos_1); |
- selection_handle_1_->SetVisible(true); |
- } else { |
- selection_handle_1_->SetVisible(false); |
- } |
- |
- if (client_view_->bounds().Contains(p2)) { |
- selection_handle_2_->SetScreenPosition(screen_pos_2); |
- selection_handle_2_->SetVisible(true); |
- } else { |
- selection_handle_2_->SetVisible(false); |
- } |
- } |
-} |
- |
-void TouchSelectionControllerImpl::ClientViewLostFocus() { |
- selection_handle_1_->SetVisible(false); |
- selection_handle_2_->SetVisible(false); |
- HideContextMenu(); |
-} |
- |
-void TouchSelectionControllerImpl::SelectionHandleDragged( |
- const gfx::Point& drag_pos) { |
- // We do not want to show the context menu while dragging. |
- HideContextMenu(); |
- context_menu_timer_.Start( |
- FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs), |
- this, |
- &TouchSelectionControllerImpl::ContextMenuTimerFired); |
- |
- if (client_view_->GetWidget()) { |
- DCHECK(dragging_handle_); |
- // Find the stationary selection handle. |
- SelectionHandleView* fixed_handle = selection_handle_1_.get(); |
- if (fixed_handle == dragging_handle_) |
- fixed_handle = selection_handle_2_.get(); |
- |
- // Find selection end points in client_view's coordinate system. |
- gfx::Point p1(drag_pos.x() + kSelectionHandleRadius, drag_pos.y()); |
- ConvertPointToClientView(dragging_handle_, &p1); |
- |
- gfx::Point p2(kSelectionHandleRadius, 0); |
- ConvertPointToClientView(fixed_handle, &p2); |
- |
- // Instruct client_view to select the region between p1 and p2. The position |
- // of |fixed_handle| is the start and that of |dragging_handle| is the end |
- // of selection. |
- client_view_->SelectRect(p2, p1); |
- } |
-} |
- |
-void TouchSelectionControllerImpl::ConvertPointToClientView( |
- SelectionHandleView* source, gfx::Point* point) { |
- View::ConvertPointToScreen(source, point); |
- gfx::Rect r = client_view_->GetWidget()->GetClientAreaScreenBounds(); |
- point->SetPoint(point->x() - r.x(), point->y() - r.y()); |
- View::ConvertPointFromWidget(client_view_, point); |
-} |
- |
-bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const { |
- return client_view_->IsCommandIdEnabled(command_id); |
-} |
- |
-void TouchSelectionControllerImpl::ExecuteCommand(int command_id) { |
- HideContextMenu(); |
- client_view_->ExecuteCommand(command_id); |
-} |
- |
-void TouchSelectionControllerImpl::ContextMenuTimerFired() { |
- // Get selection end points in client_view's space. |
- gfx::Point p1(kSelectionHandleRadius, 0); |
- ConvertPointToClientView(selection_handle_1_.get(), &p1); |
- gfx::Point p2(kSelectionHandleRadius, 0); |
- ConvertPointToClientView(selection_handle_2_.get(), &p2); |
- |
- // if selection is completely inside the view, we display the context menu |
- // in the middle of the end points on the top. Else, we show the menu on the |
- // top border of the view in the center. |
- gfx::Point menu_pos; |
- if (client_view_->bounds().Contains(p1) && |
- client_view_->bounds().Contains(p2)) { |
- menu_pos.set_x((p1.x() + p2.x()) / 2); |
- menu_pos.set_y(std::min(p1.y(), p2.y()) - kContextMenuVerticalOffset); |
- } else { |
- menu_pos.set_x(client_view_->x() + client_view_->width() / 2); |
- menu_pos.set_y(client_view_->y()); |
- } |
- |
- View::ConvertPointToScreen(client_view_, &menu_pos); |
- |
- context_menu_->SetScreenPosition(menu_pos); |
- context_menu_->SetVisible(true); |
-} |
- |
-void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1, |
- const gfx::Point& p2) { |
- // Hide context menu to be shown when the timer fires. |
- HideContextMenu(); |
- |
- // If there is selection, we restart the context menu timer. |
- if (!IsEmptySelection(p1, p2)) { |
- context_menu_timer_.Start( |
- FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs), |
- this, |
- &TouchSelectionControllerImpl::ContextMenuTimerFired); |
- } |
-} |
- |
-void TouchSelectionControllerImpl::HideContextMenu() { |
- context_menu_->SetVisible(false); |
- context_menu_timer_.Stop(); |
-} |
- |
-gfx::Point TouchSelectionControllerImpl::GetSelectionHandle1Position() { |
- return selection_handle_1_->GetScreenPosition(); |
-} |
- |
-gfx::Point TouchSelectionControllerImpl::GetSelectionHandle2Position() { |
- return selection_handle_2_->GetScreenPosition(); |
-} |
- |
-bool TouchSelectionControllerImpl::IsSelectionHandle1Visible() { |
- return selection_handle_1_->IsVisible(); |
-} |
- |
-bool TouchSelectionControllerImpl::IsSelectionHandle2Visible() { |
- return selection_handle_2_->IsVisible(); |
-} |
- |
-TouchSelectionController* TouchSelectionController::create( |
- TouchSelectionClientView* client_view) { |
- return new TouchSelectionControllerImpl(client_view); |
-} |
- |
-} // namespace views |