diff options
-rw-r--r-- | ui/base/touch/touch_editing_controller.cc | 12 | ||||
-rw-r--r-- | ui/base/touch/touch_editing_controller.h | 41 | ||||
-rw-r--r-- | ui/base/ui_base_switches.cc | 3 | ||||
-rw-r--r-- | ui/base/ui_base_switches.h | 1 | ||||
-rw-r--r-- | ui/views/controls/textfield/native_textfield_views.cc | 49 | ||||
-rw-r--r-- | ui/views/controls/textfield/native_textfield_views.h | 5 | ||||
-rw-r--r-- | ui/views/touchui/touch_editing_menu.cc | 150 | ||||
-rw-r--r-- | ui/views/touchui/touch_editing_menu.h | 74 | ||||
-rw-r--r-- | ui/views/touchui/touch_selection_controller_impl.cc | 371 | ||||
-rw-r--r-- | ui/views/touchui/touch_selection_controller_impl.h | 40 | ||||
-rw-r--r-- | ui/views/views.gyp | 5 | ||||
-rw-r--r-- | ui/views/views_delegate.cc | 16 | ||||
-rw-r--r-- | ui/views/views_delegate.h | 2 |
13 files changed, 285 insertions, 484 deletions
diff --git a/ui/base/touch/touch_editing_controller.cc b/ui/base/touch/touch_editing_controller.cc index 1b84ed9..8afb740 100644 --- a/ui/base/touch/touch_editing_controller.cc +++ b/ui/base/touch/touch_editing_controller.cc @@ -6,21 +6,9 @@ namespace ui { -namespace { -TouchSelectionControllerFactory* g_shared_instance = NULL; -} // namespace - TouchSelectionController* TouchSelectionController::create( TouchEditable* client_view) { - if (g_shared_instance) - return g_shared_instance->create(client_view); return NULL; } -// static -void TouchSelectionControllerFactory::SetInstance( - TouchSelectionControllerFactory* instance) { - g_shared_instance = instance; -} - } // namespace ui diff --git a/ui/base/touch/touch_editing_controller.h b/ui/base/touch/touch_editing_controller.h index e7985ce..999c2ad 100644 --- a/ui/base/touch/touch_editing_controller.h +++ b/ui/base/touch/touch_editing_controller.h @@ -20,17 +20,6 @@ class UI_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { // end of selection. Visually, |start| may lie after |end|. virtual void SelectRect(const gfx::Point& start, const gfx::Point& end) = 0; - // Gets the end points of the current selection. The end points p1 and p2 must - // be the cursor rect for the start and end of selection: - // ____________________________________ - // | textfield with |selected text| | - // ------------------------------------ - // ^p1 ^p2 - // - // p1 should be the logical start and p2 the logical end of selection. Hence, - // visually, p1 could be to the right of p2 in the figure above. - virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) = 0; - // Gets the bounds of the client view in parent's coordinates. virtual const gfx::Rect& GetBounds() = 0; @@ -41,13 +30,6 @@ class UI_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { virtual void ConvertPointToScreen(gfx::Point* point) = 0; virtual void ConvertPointFromScreen(gfx::Point* point) = 0; - // Returns true if the editable draws its own handles (hence, the - // TouchSelectionController need not draw handles). - virtual bool DrawsHandles() = 0; - - // Tells the editable to open context menu. - virtual void OpenContextMenu(const gfx::Point anchor) = 0; - protected: virtual ~TouchEditable() {} }; @@ -62,18 +44,19 @@ class UI_EXPORT TouchSelectionController { static TouchSelectionController* create( TouchEditable* client_view); - // Notifies the controller that the selection has changed. - virtual void SelectionChanged() = 0; -}; - -class UI_EXPORT TouchSelectionControllerFactory { - public: - static void SetInstance(TouchSelectionControllerFactory* instance); - - virtual TouchSelectionController* create(TouchEditable* client_view) = 0; + // Notification that the text selection in TouchEditable has + // changed. p1 and p2 are lower corners of the start and end of selection: + // ____________________________________ + // | textfield with |selected text| | + // ------------------------------------ + // ^p1 ^p2 + // + // p1 is always the start and p2 is always the end of selection. Hence, + // p1 could be to the right of p2 in the figure above. + virtual void SelectionChanged(const gfx::Point& p1, const gfx::Point& p2) = 0; - protected: - virtual ~TouchSelectionControllerFactory() {} + // Notification that the TouchEditable has lost focus. + virtual void ClientViewLostFocus() = 0; }; } // namespace views diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index b4fdabf..e647ac3 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc @@ -20,9 +20,6 @@ const char kEnableNewDialogStyle[] = "enable-new-dialog-style"; const char kEnableTouchDragDrop[] = "enable-touch-drag-drop"; -// Enables controls that support touch base text editing. -const char kEnableTouchEditing[] = "enable-touch-editing"; - // Enables the Views textfield on Windows. const char kEnableViewsTextfield[] = "enable-views-textfield"; diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index b21e2b1..14bdebc 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h @@ -17,7 +17,6 @@ UI_EXPORT extern const char kDisableTouchAdjustment[]; UI_EXPORT extern const char kEnableBezelTouch[]; UI_EXPORT extern const char kEnableNewDialogStyle[]; UI_EXPORT extern const char kEnableTouchDragDrop[]; -UI_EXPORT extern const char kEnableTouchEditing[]; UI_EXPORT extern const char kEnableViewsTextfield[]; UI_EXPORT extern const char kForceDeviceScaleFactor[]; UI_EXPORT extern const char kHighlightMissingScaledResources[]; diff --git a/ui/views/controls/textfield/native_textfield_views.cc b/ui/views/controls/textfield/native_textfield_views.cc index 16b908f..d9c4348 100644 --- a/ui/views/controls/textfield/native_textfield_views.cc +++ b/ui/views/controls/textfield/native_textfield_views.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -69,7 +69,8 @@ NativeTextfieldViews::NativeTextfieldViews(Textfield* parent) initiating_drag_(false), ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)), aggregated_clicks_(0), - touch_selection_controller_(NULL) { + ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_( + ui::TouchSelectionController::create(this))) { set_border(text_border_); #if defined(OS_CHROMEOS) @@ -103,7 +104,6 @@ bool NativeTextfieldViews::OnMousePressed(const ui::MouseEvent& event) { } OnAfterUserAction(); - touch_selection_controller_.reset(); return true; } @@ -169,12 +169,6 @@ void NativeTextfieldViews::OnGestureEvent(ui::GestureEvent* event) { OnAfterUserAction(); event->SetHandled(); return; - case ui::ET_GESTURE_TAP: - touch_selection_controller_.reset( - ui::TouchSelectionController::create(this)); - if (touch_selection_controller_.get()) - touch_selection_controller_->SelectionChanged(); - break; default: break; } @@ -317,16 +311,6 @@ void NativeTextfieldViews::SelectRect(const gfx::Point& start, OnAfterUserAction(); } -void NativeTextfieldViews::GetSelectionEndPoints(gfx::Rect* p1, - gfx::Rect* p2) { - gfx::RenderText* render_text = GetRenderText(); - const gfx::SelectionModel& sel = render_text->selection_model(); - gfx::SelectionModel start_sel = - render_text->GetSelectionModelForSelectionStart(); - *p1 = render_text->GetCursorBounds(start_sel, true); - *p2 = render_text->GetCursorBounds(sel, true); -} - const gfx::Rect& NativeTextfieldViews::GetBounds() { return bounds(); } @@ -343,15 +327,6 @@ void NativeTextfieldViews::ConvertPointFromScreen(gfx::Point* point) { View::ConvertPointFromScreen(this, point); } -bool NativeTextfieldViews::DrawsHandles() { - return false; -} - -void NativeTextfieldViews::OpenContextMenu(const gfx::Point anchor) { - touch_selection_controller_.reset(); - ShowContextMenu(anchor, false); -} - gfx::NativeCursor NativeTextfieldViews::GetCursor(const ui::MouseEvent& event) { bool in_selection = GetRenderText()->IsPointInSelection(event.location()); bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; @@ -600,7 +575,6 @@ bool NativeTextfieldViews::HandleKeyPressed(const ui::KeyEvent& e) { bool handled = false; if (controller) handled = controller->HandleKeyEvent(textfield_, e); - touch_selection_controller_.reset(); return handled || HandleKeyEvent(e); } @@ -630,7 +604,8 @@ void NativeTextfieldViews::HandleBlur() { RepaintCursor(); } - touch_selection_controller_.reset(); + if (touch_selection_controller_.get()) + touch_selection_controller_->ClientViewLostFocus(); ClearSelection(); } @@ -699,7 +674,6 @@ string16 NativeTextfieldViews::GetLabelForCommandId(int command_id) const { } void NativeTextfieldViews::ExecuteCommand(int command_id) { - touch_selection_controller_.reset(); if (!IsCommandIdEnabled(command_id)) return; @@ -1215,8 +1189,17 @@ void NativeTextfieldViews::OnCaretBoundsChanged() { textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_); // Notify selection controller - if (touch_selection_controller_.get()) - touch_selection_controller_->SelectionChanged(); + if (!touch_selection_controller_.get()) + return; + gfx::RenderText* render_text = GetRenderText(); + const gfx::SelectionModel& sel = render_text->selection_model(); + gfx::SelectionModel start_sel = + render_text->GetSelectionModelForSelectionStart(); + gfx::Rect start_cursor = render_text->GetCursorBounds(start_sel, true); + gfx::Rect end_cursor = render_text->GetCursorBounds(sel, true); + gfx::Point start(start_cursor.x(), start_cursor.bottom() - 1); + gfx::Point end(end_cursor.x(), end_cursor.bottom() - 1); + touch_selection_controller_->SelectionChanged(start, end); } void NativeTextfieldViews::OnBeforeUserAction() { diff --git a/ui/views/controls/textfield/native_textfield_views.h b/ui/views/controls/textfield/native_textfield_views.h index 70aa16e..166d9bb 100644 --- a/ui/views/controls/textfield/native_textfield_views.h +++ b/ui/views/controls/textfield/native_textfield_views.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -80,13 +80,10 @@ class VIEWS_EXPORT NativeTextfieldViews : public View, // ui::TouchEditable overrides: virtual void SelectRect(const gfx::Point& start, const gfx::Point& end) OVERRIDE; - virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE; virtual const gfx::Rect& GetBounds() OVERRIDE; virtual gfx::NativeView GetNativeView() OVERRIDE; virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE; virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE; - virtual bool DrawsHandles() OVERRIDE; - virtual void OpenContextMenu(const gfx::Point anchor) OVERRIDE; // ContextMenuController overrides: virtual void ShowContextMenuForView(View* source, diff --git a/ui/views/touchui/touch_editing_menu.cc b/ui/views/touchui/touch_editing_menu.cc deleted file mode 100644 index ed1dae9..0000000 --- a/ui/views/touchui/touch_editing_menu.cc +++ /dev/null @@ -1,150 +0,0 @@ -// 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/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/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/layout/box_layout.h" -#include "ui/views/widget/widget.h" - -namespace { - -const int kMenuCommands[] = {IDS_APP_CUT, - IDS_APP_COPY, - IDS_APP_PASTE, - IDS_APP_DELETE, - IDS_APP_SELECT_ALL}; -const int kSpacingBetweenButtons = 0; -const int kButtonSeparatorColor = SkColorSetARGB(13, 0, 0, 0); -const int kMenuButtonBorderThickness = 5; -const SkColor kMenuButtonColorNormal = SkColorSetARGB(102, 255, 255, 255); -const SkColor kMenuButtonColorHover = SkColorSetARGB(13, 0, 0, 0); - -const char* kEllipsesButtonText = "..."; -const int kEllipsesButtonTag = -1; -} // namespace - -namespace views { - -class TouchEditingMenuButtonBackground : public Background { - public: - TouchEditingMenuButtonBackground() {} - - virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { - CustomButton::ButtonState state = static_cast<CustomButton*>(view)->state(); - SkColor background_color = (state == CustomButton::STATE_NORMAL)? - kMenuButtonColorNormal : kMenuButtonColorHover; - int w = view->width(); - int h = view->height(); - canvas->FillRect(gfx::Rect(1, 0, w, h), background_color); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TouchEditingMenuButtonBackground); -}; - -TouchEditingMenuView::TouchEditingMenuView( - TouchEditingMenuController* controller, - gfx::Point anchor_point, - gfx::NativeView context) - : BubbleDelegateView(NULL, views::BubbleBorder::BOTTOM_CENTER), - controller_(controller) { - set_anchor_point(anchor_point); - set_shadow(views::BubbleBorder::SMALL_SHADOW); - set_parent_window(context); - set_margins(gfx::Insets()); - set_use_focusless(true); - set_adjust_if_offscreen(true); - - SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0, - kSpacingBetweenButtons)); - CreateButtons(); - views::BubbleDelegateView::CreateBubble(this); - GetBubbleFrameView()->set_background(NULL); - Show(); -} - -TouchEditingMenuView::~TouchEditingMenuView() { -} - -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()); - else - controller_->OpenContextMenu(); - } -} - -void TouchEditingMenuView::OnPaint(gfx::Canvas* canvas) { - BubbleDelegateView::OnPaint(canvas); - - // Draw separator bars. - int x = 0; - for (int i = 0; i < child_count() - 1; ++i) { - View* child = child_at(i); - x += child->width(); - 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( - UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag)); - Layout(); -} - -Button* TouchEditingMenuView::CreateButton(const string16& title, int tag) { - LabelButton* button = new LabelButton(this, gfx::RemoveAcceleratorChar( - title, '&', NULL, NULL)); - button->set_focusable(true); - button->set_request_focus_on_press(false); - button->set_background(new TouchEditingMenuButtonBackground); - button->set_border(Border::CreateEmptyBorder(kMenuButtonBorderThickness, - kMenuButtonBorderThickness, - kMenuButtonBorderThickness, - kMenuButtonBorderThickness)); - button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont( - ui::ResourceBundle::SmallFont)); - button->set_tag(tag); - return button; -} - -} // namespace views diff --git a/ui/views/touchui/touch_editing_menu.h b/ui/views/touchui/touch_editing_menu.h deleted file mode 100644 index 86d4892..0000000 --- a/ui/views/touchui/touch_editing_menu.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_TOUCHUI_TOUCH_EDITING_MENU_H_ -#define UI_VIEWS_TOUCHUI_TOUCH_EDITING_MENU_H_ - -#include "ui/gfx/point.h" -#include "ui/views/bubble/bubble_delegate.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/views_export.h" - -namespace gfx { -class Canvas; -} - -namespace views { -class TouchEditingMenuView; -class Widget; - -class VIEWS_EXPORT TouchEditingMenuController { - public: - // Checks if the specified menu command is supported. - virtual bool IsCommandIdEnabled(int command_id) const = 0; - - // Send a context menu command to the controller. - virtual void ExecuteCommand(int command_id) = 0; - - // Tell the controller that user has selected the context menu button. - virtual void OpenContextMenu() = 0; - - // Called when the menu is closed. - virtual void OnMenuClosed(TouchEditingMenuView* menu) = 0; - - protected: - virtual ~TouchEditingMenuController() {} -}; - -// A View that displays the touch context menu. -class VIEWS_EXPORT TouchEditingMenuView : public BubbleDelegateView, - public ButtonListener { - public: - TouchEditingMenuView(TouchEditingMenuController* controller, - gfx::Point anchor_point, - gfx::NativeView context); - virtual ~TouchEditingMenuView(); - - void Close(); - - private: - // views::WidgetDelegate overrides: - void WindowClosing() OVERRIDE; - - // Overridden from ButtonListener. - void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE; - - // Overridden from BubbleDelegateView. - void OnPaint(gfx::Canvas* canvas) OVERRIDE; - - // Queries the |controller_| for what elements to show in the menu and sizes - // the menu appropriately. - void CreateButtons(); - - // Helper method to create a single button. - Button* CreateButton(const string16& title, int tag); - - TouchEditingMenuController* controller_; - - DISALLOW_COPY_AND_ASSIGN(TouchEditingMenuView); -}; - -} // namespace views - -#endif // UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_ diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc index a0ca742..5956373 100644 --- a/ui/views/touchui/touch_selection_controller_impl.cc +++ b/ui/views/touchui/touch_selection_controller_impl.cc @@ -1,32 +1,52 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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_selection_controller_impl.h" -#include "base/command_line.h" #include "base/time.h" +#include "base/utf_string_conversions.h" #include "grit/ui_strings.h" -#include "ui/base/ui_base_switches.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/rect.h" #include "ui/gfx/screen.h" #include "ui/gfx/size.h" +#include "ui/gfx/text_utils.h" +#include "ui/gfx/transform.h" +#include "ui/views/background.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/button/custom_button.h" +#include "ui/views/controls/button/text_button.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/menu/menu_config.h" +#include "ui/views/layout/box_layout.h" #include "ui/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_ColorBLACK, kSelectionHandleAlpha); + 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 = 5; +const int kContextMenuVerticalOffset = 25; // Convenience struct to represent a circle shape. struct Circle { @@ -36,13 +56,12 @@ struct Circle { }; // Creates a widget to host SelectionHandleView. -views::Widget* CreateTouchSelectionPopupWidget(gfx::NativeView context) { +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; - params.context = context; widget->Init(params); return widget; } @@ -71,11 +90,9 @@ namespace views { // A View that displays the text selection handle. class TouchSelectionControllerImpl::SelectionHandleView : public View { public: - explicit SelectionHandleView(TouchSelectionControllerImpl* controller, - gfx::NativeView context) - : controller_(controller), - cursor_height_(0) { - widget_.reset(CreateTouchSelectionPopupWidget(context)); + explicit SelectionHandleView(TouchSelectionControllerImpl* controller) + : controller_(controller) { + widget_.reset(CreateTouchSelectionPopupWidget()); widget_->SetContentsView(this); widget_->SetAlwaysOnTop(true); @@ -88,30 +105,30 @@ class TouchSelectionControllerImpl::SelectionHandleView : public View { virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { Circle circle = {kSelectionHandleRadius, gfx::Point(kSelectionHandleRadius, - kSelectionHandleRadius + cursor_height_), + kSelectionHandleRadius + kSelectionHandleCursorHeight), kSelectionHandleColor}; PaintCircle(circle, canvas); canvas->DrawLine(gfx::Point(kSelectionHandleRadius, 0), - gfx::Point(kSelectionHandleRadius, cursor_height_), + gfx::Point(kSelectionHandleRadius, kSelectionHandleCursorHeight), kSelectionHandleColor); } - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { - event->SetHandled(); - switch (event->type()) { - case ui::ET_GESTURE_SCROLL_BEGIN: - controller_->dragging_handle_ = this; - break; - case ui::ET_GESTURE_SCROLL_UPDATE: - controller_->SelectionHandleDragged(event->location()); - break; - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_GESTURE_END: - controller_->dragging_handle_ = NULL; - break; - default: - break; - } + virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { + controller_->dragging_handle_ = this; + return true; + } + + virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { + controller_->SelectionHandleDragged(event.location()); + return true; + } + + virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { + controller_->dragging_handle_ = NULL; + } + + virtual void OnMouseCaptureLost() OVERRIDE { + controller_->dragging_handle_ = NULL; } virtual void SetVisible(bool visible) OVERRIDE { @@ -127,18 +144,13 @@ class TouchSelectionControllerImpl::SelectionHandleView : public View { virtual gfx::Size GetPreferredSize() OVERRIDE { return gfx::Size(2 * kSelectionHandleRadius, - 2 * kSelectionHandleRadius + cursor_height_); - } - - bool IsWidgetVisible() const { - return widget_->IsVisible(); + 2 * kSelectionHandleRadius + kSelectionHandleCursorHeight); } - void SetSelectionRectInScreen(const gfx::Rect& rect) { - cursor_height_ = rect.height(); - gfx::Rect widget_bounds(rect.x() - kSelectionHandleRadius, rect.y(), + void SetScreenPosition(const gfx::Point& position) { + gfx::Rect widget_bounds(position.x() - kSelectionHandleRadius, position.y(), 2 * kSelectionHandleRadius, - 2 * kSelectionHandleRadius + cursor_height_); + 2 * kSelectionHandleRadius + kSelectionHandleCursorHeight); widget_->SetBounds(widget_bounds); } @@ -149,65 +161,194 @@ class TouchSelectionControllerImpl::SelectionHandleView : public View { private: scoped_ptr<Widget> widget_; TouchSelectionControllerImpl* controller_; - int cursor_height_; 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::STATE_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(gfx::Rect(1, 1, w - 2, h - 2), background_color); + canvas->FillRect(gfx::Rect(2, 0, w - 4, 1), border_color); + canvas->FillRect(gfx::Rect(1, 1, 1, 1), border_color); + canvas->FillRect(gfx::Rect(0, 2, 1, h - 4), border_color); + canvas->FillRect(gfx::Rect(1, h - 2, 1, 1), border_color); + canvas->FillRect(gfx::Rect(2, h - 1, w - 4, 1), border_color); + canvas->FillRect(gfx::Rect(w - 2, 1, 1, 1), border_color); + canvas->FillRect(gfx::Rect(w - 1, 2, 1, h - 4), border_color); + canvas->FillRect(gfx::Rect(w - 2, h - 2, 1, 1), border_color); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ContextMenuButtonBackground); +}; + +// A View that displays the touch context menu. +class TouchSelectionControllerImpl::TouchContextMenuView + : public ButtonListener, + public View { + public: + explicit TouchContextMenuView(TouchSelectionControllerImpl* controller) + : controller_(controller) { + widget_.reset(CreateTouchSelectionPopupWidget()); + widget_->SetContentsView(this); + widget_->SetAlwaysOnTop(true); + + // We are owned by the TouchSelectionController. + set_owned_by_client(); + 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_->GetClientAreaBoundsInScreen().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].iset(0, 0); + points[1].iset(0, height()); + + skia::RefPtr<SkShader> shader = skia::AdoptRef( + SkGradientShader::CreateLinear( + points, kGradientColors, kGradientPoints, + arraysize(kGradientPoints), + SkShader::kRepeat_TileMode)); + DCHECK(shader); + + SkPaint paint; + paint.setShader(shader.get()); + + paint.setStyle(SkPaint::kFill_Style); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + + canvas->DrawRect(GetLocalBounds(), paint); +#else + canvas->DrawColor(SkColorSetRGB(210, 225, 246), + SkXfermode::kSrc_Mode); +#endif + } + + // Overridden from ButtonListener: + virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE { + 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, gfx::RemoveAcceleratorChar( + l10n_util::GetStringUTF16(command_id), '&', NULL, NULL)); + button->set_focusable(true); + button->set_request_focus_on_press(false); + 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::GetNativeScreen()-> + GetDisplayNearestPoint(position).bounds(); + widget_->SetBounds(widget_bounds.AdjustToFit(monitor_bounds)); + Layout(); + } + + scoped_ptr<Widget> widget_; + TouchSelectionControllerImpl* controller_; + + DISALLOW_COPY_AND_ASSIGN(TouchContextMenuView); +}; + TouchSelectionControllerImpl::TouchSelectionControllerImpl( ui::TouchEditable* client_view) : client_view_(client_view), - client_widget_(NULL), - selection_handle_1_(new SelectionHandleView(this, - client_view->GetNativeView())), - selection_handle_2_(new SelectionHandleView(this, - client_view->GetNativeView())), - context_menu_(NULL), + selection_handle_1_(new SelectionHandleView(this)), + selection_handle_2_(new SelectionHandleView(this)), + context_menu_(new TouchContextMenuView(this)), dragging_handle_(NULL) { - client_widget_ = Widget::GetWidgetForNativeView( - client_view_->GetNativeView()); - client_widget_->AddObserver(this); } TouchSelectionControllerImpl::~TouchSelectionControllerImpl() { - HideContextMenu(); - if (client_widget_) - client_widget_->RemoveObserver(this); } -void TouchSelectionControllerImpl::SelectionChanged() { - gfx::Rect r1, r2; - client_view_->GetSelectionEndPoints(&r1, &r2); - gfx::Point screen_pos_1(r1.origin()); +void TouchSelectionControllerImpl::SelectionChanged(const gfx::Point& p1, + const gfx::Point& p2) { + gfx::Point screen_pos_1(p1); client_view_->ConvertPointToScreen(&screen_pos_1); - gfx::Point screen_pos_2(r2.origin()); + gfx::Point screen_pos_2(p2); client_view_->ConvertPointToScreen(&screen_pos_2); - gfx::Rect screen_rect_1(screen_pos_1, r1.size()); - gfx::Rect screen_rect_2(screen_pos_2, r2.size()); - if (client_view_->DrawsHandles()) { - UpdateContextMenu(r1.origin(), r2.origin()); - return; - } 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_->SetSelectionRectInScreen(screen_rect_2); - - // The non-dragging-handle might have recently become visible. - SelectionHandleView* non_dragging_handle = - dragging_handle_ == selection_handle_1_.get()? - selection_handle_2_.get() : selection_handle_1_.get(); - if (client_view_->GetBounds().Contains(r1.origin())) { - non_dragging_handle->SetSelectionRectInScreen(screen_rect_1); - non_dragging_handle->SetVisible(true); - } else { - non_dragging_handle->SetVisible(false); - } + dragging_handle_->SetScreenPosition(screen_pos_2); } else { - UpdateContextMenu(r1.origin(), r2.origin()); + UpdateContextMenu(p1, p2); // Check if there is any selection at all. if (IsEmptySelection(screen_pos_2, screen_pos_1)) { @@ -216,15 +357,15 @@ void TouchSelectionControllerImpl::SelectionChanged() { return; } - if (client_view_->GetBounds().Contains(r1.origin())) { - selection_handle_1_->SetSelectionRectInScreen(screen_rect_1); + if (client_view_->GetBounds().Contains(p1)) { + selection_handle_1_->SetScreenPosition(screen_pos_1); selection_handle_1_->SetVisible(true); } else { selection_handle_1_->SetVisible(false); } - if (client_view_->GetBounds().Contains(r2.origin())) { - selection_handle_2_->SetSelectionRectInScreen(screen_rect_2); + if (client_view_->GetBounds().Contains(p2)) { + selection_handle_2_->SetScreenPosition(screen_pos_2); selection_handle_2_->SetVisible(true); } else { selection_handle_2_->SetVisible(false); @@ -232,6 +373,12 @@ void TouchSelectionControllerImpl::SelectionChanged() { } } +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. @@ -276,44 +423,21 @@ void TouchSelectionControllerImpl::ExecuteCommand(int command_id) { client_view_->ExecuteCommand(command_id); } -void TouchSelectionControllerImpl::OpenContextMenu() { - gfx::Point anchor = context_menu_->anchor_point(); - HideContextMenu(); - client_view_->OpenContextMenu(anchor); -} - -void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) { - if (menu == context_menu_) - context_menu_ = NULL; -} - -void TouchSelectionControllerImpl::OnWidgetClosing(Widget* widget) { - DCHECK_EQ(client_widget_, widget); - client_widget_ = NULL; -} - -void TouchSelectionControllerImpl::OnWidgetBoundsChanged( - Widget* widget, - const gfx::Rect& new_bounds) { - DCHECK_EQ(client_widget_, widget); - HideContextMenu(); - SelectionChanged(); -} - void TouchSelectionControllerImpl::ContextMenuTimerFired() { // Get selection end points in client_view's space. - gfx::Rect r1, r2; - client_view_->GetSelectionEndPoints(&r1, &r2); + 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; gfx::Rect client_bounds = client_view_->GetBounds(); - if (client_bounds.Contains(r1.origin()) && - client_bounds.Contains(r2.origin())) { - menu_pos.set_x((r1.origin().x() + r2.origin().x()) / 2); - menu_pos.set_y(std::min(r1.y(), r2.y()) - kContextMenuVerticalOffset); + if (client_bounds.Contains(p1) && client_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_bounds.x() + client_bounds.width() / 2); menu_pos.set_y(client_bounds.y()); @@ -321,9 +445,8 @@ void TouchSelectionControllerImpl::ContextMenuTimerFired() { client_view_->ConvertPointToScreen(&menu_pos); - DCHECK(!context_menu_); - context_menu_ = new TouchEditingMenuView(this, menu_pos, - client_view_->GetNativeView()); + context_menu_->SetScreenPosition(menu_pos); + context_menu_->SetVisible(true); } void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1, @@ -342,9 +465,7 @@ void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1, } void TouchSelectionControllerImpl::HideContextMenu() { - if (context_menu_) - context_menu_->Close(); - context_menu_ = NULL; + context_menu_->SetVisible(false); context_menu_timer_.Stop(); } @@ -364,17 +485,13 @@ bool TouchSelectionControllerImpl::IsSelectionHandle2Visible() { return selection_handle_2_->visible(); } -ViewsTouchSelectionControllerFactory::ViewsTouchSelectionControllerFactory() { -} +} // namespace views -ui::TouchSelectionController* ViewsTouchSelectionControllerFactory::create( - ui::TouchEditable* client_view) { -#if defined(OS_CHROMEOS) - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableTouchEditing)) - return new views::TouchSelectionControllerImpl(client_view); -#endif - return NULL; +namespace ui { + +TouchSelectionController* TouchSelectionController::create( + TouchEditable* client_view) { + return new views::TouchSelectionControllerImpl(client_view); } -} // namespace views +} // namespace ui diff --git a/ui/views/touchui/touch_selection_controller_impl.h b/ui/views/touchui/touch_selection_controller_impl.h index 04579fe..5d042e7 100644 --- a/ui/views/touchui/touch_selection_controller_impl.h +++ b/ui/views/touchui/touch_selection_controller_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// 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. @@ -8,7 +8,6 @@ #include "base/timer.h" #include "ui/base/touch/touch_editing_controller.h" #include "ui/gfx/point.h" -#include "ui/views/touchui/touch_editing_menu.h" #include "ui/views/view.h" #include "ui/views/views_export.h" @@ -17,9 +16,7 @@ namespace views { // Touch specific implementation of TouchSelectionController. Responsible for // displaying selection handles and menu elements relevant in a touch interface. class VIEWS_EXPORT TouchSelectionControllerImpl - : public ui::TouchSelectionController, - public TouchEditingMenuController, - public WidgetObserver { + : public ui::TouchSelectionController { public: // Use TextSelectionController::create(). explicit TouchSelectionControllerImpl( @@ -28,11 +25,15 @@ class VIEWS_EXPORT TouchSelectionControllerImpl virtual ~TouchSelectionControllerImpl(); // TextSelectionController. - virtual void SelectionChanged() OVERRIDE; + virtual void SelectionChanged(const gfx::Point& p1, + const gfx::Point& p2) OVERRIDE; + + virtual void ClientViewLostFocus() OVERRIDE; private: friend class TouchSelectionControllerImplTest; class SelectionHandleView; + class TouchContextMenuView; // Callback to inform the client view that the selection handle has been // dragged, hence selection may need to be updated. @@ -42,18 +43,11 @@ class VIEWS_EXPORT TouchSelectionControllerImpl // system to that of the client view. void ConvertPointToClientView(SelectionHandleView* source, gfx::Point* point); - // Overridden from TouchEditingMenuController. - bool IsCommandIdEnabled(int command_id) const OVERRIDE; - void ExecuteCommand(int command_id) OVERRIDE; - void OpenContextMenu() OVERRIDE; - void OnMenuClosed(TouchEditingMenuView* menu) OVERRIDE; + // Checks if the client view supports a context menu command. + bool IsCommandIdEnabled(int command_id) const; - // Overridden from WidgetObserver. We will observe the widget backing the - // |client_view_| so that when its moved/resized, we can update the selection - // handles appropriately. - void OnWidgetClosing(Widget* widget) OVERRIDE; - void OnWidgetBoundsChanged(Widget* widget, - const gfx::Rect& new_bounds) OVERRIDE; + // Sends a context menu command to the client view. + void ExecuteCommand(int command_id); // Time to show context menu. void ContextMenuTimerFired(); @@ -71,10 +65,9 @@ class VIEWS_EXPORT TouchSelectionControllerImpl bool IsSelectionHandle2Visible(); ui::TouchEditable* client_view_; - Widget* client_widget_; scoped_ptr<SelectionHandleView> selection_handle_1_; scoped_ptr<SelectionHandleView> selection_handle_2_; - TouchEditingMenuView* context_menu_; + scoped_ptr<TouchContextMenuView> context_menu_; // Timer to trigger |context_menu| (|context_menu| is not shown if the // selection handles are being updated. It appears only when the handles are @@ -87,15 +80,6 @@ class VIEWS_EXPORT TouchSelectionControllerImpl DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl); }; -class VIEWS_EXPORT ViewsTouchSelectionControllerFactory - : public ui::TouchSelectionControllerFactory { - public: - ViewsTouchSelectionControllerFactory(); - - // Overridden from ui::TouchSelectionControllerFactory. - ui::TouchSelectionController* create(ui::TouchEditable* client_view) OVERRIDE; -}; - } // namespace views #endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_ diff --git a/ui/views/views.gyp b/ui/views/views.gyp index f74b094..abd8943 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -309,10 +309,6 @@ 'repeat_controller.h', 'round_rect_painter.cc', 'round_rect_painter.h', - 'touchui/touch_editing_menu.cc', - 'touchui/touch_editing_menu.h', - 'touchui/touch_selection_controller_impl.cc', - 'touchui/touch_selection_controller_impl.h', 'view.cc', 'view.h', 'view_constants.cc', @@ -325,7 +321,6 @@ 'view_text_utils.cc', 'view_text_utils.h', 'view_win.cc', - 'views_delegate.cc', 'views_delegate.h', 'widget/aero_tooltip_manager.cc', 'widget/aero_tooltip_manager.h', diff --git a/ui/views/views_delegate.cc b/ui/views/views_delegate.cc deleted file mode 100644 index cf51e24..0000000 --- a/ui/views/views_delegate.cc +++ /dev/null @@ -1,16 +0,0 @@ -// 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/views_delegate.h" - -#include "ui/views/touchui/touch_selection_controller_impl.h" - -namespace views { - -ViewsDelegate::ViewsDelegate() { - ui::TouchSelectionControllerFactory::SetInstance( - new views::ViewsTouchSelectionControllerFactory); -} - -} // namespace views diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h index b569da9..105bab0 100644 --- a/ui/views/views_delegate.h +++ b/ui/views/views_delegate.h @@ -49,8 +49,6 @@ class VIEWS_EXPORT ViewsDelegate { // The active ViewsDelegate used by the views system. static ViewsDelegate* views_delegate; - ViewsDelegate(); - virtual ~ViewsDelegate() {} // Saves the position, size and "show" state for the window with the |