diff options
Diffstat (limited to 'ui/base/touch')
-rw-r--r-- | ui/base/touch/touch_editing_controller.cc | 39 | ||||
-rw-r--r-- | ui/base/touch/touch_editing_controller.h | 47 | ||||
-rw-r--r-- | ui/base/touch/touch_editing_controller_unittest.cc | 99 |
3 files changed, 177 insertions, 8 deletions
diff --git a/ui/base/touch/touch_editing_controller.cc b/ui/base/touch/touch_editing_controller.cc index 1b84ed9..f3c4c24 100644 --- a/ui/base/touch/touch_editing_controller.cc +++ b/ui/base/touch/touch_editing_controller.cc @@ -10,6 +10,45 @@ namespace { TouchSelectionControllerFactory* g_shared_instance = NULL; } // namespace +SelectionBound::SelectionBound() + : type(ui::SelectionBound::EMPTY) { +} + +SelectionBound::~SelectionBound() { +} + +int SelectionBound::GetHeight() const { + return edge_bottom.y() - edge_top.y(); +} + +bool operator==(const SelectionBound& lhs, const SelectionBound& rhs) { + return lhs.type == rhs.type && lhs.edge_top == rhs.edge_top && + lhs.edge_bottom == rhs.edge_bottom; +} + +bool operator!=(const SelectionBound& lhs, const SelectionBound& rhs) { + return !(lhs == rhs); +} + +gfx::Rect RectBetweenSelectionBounds(const SelectionBound& b1, + const SelectionBound& b2) { + int all_x[] ={ + b1.edge_top.x(), b2.edge_top.x(), b1.edge_bottom.x(), b2.edge_bottom.x() + }; + int all_y[] = { + b1.edge_top.y(), b2.edge_top.y(), b1.edge_bottom.y(), b2.edge_bottom.y() + }; + const int num_elements = arraysize(all_x); + COMPILE_ASSERT(arraysize(all_y) == num_elements, array_size_mismatch); + + int left = *std::min_element(all_x, all_x + num_elements); + int top = *std::min_element(all_y, all_y + num_elements); + int right = *std::max_element(all_x, all_x + num_elements); + int bottom = *std::max_element(all_y, all_y + num_elements); + + return gfx::Rect(left, top, right - left, bottom - top); +} + TouchSelectionController* TouchSelectionController::create( TouchEditable* client_view) { if (g_shared_instance) diff --git a/ui/base/touch/touch_editing_controller.h b/ui/base/touch/touch_editing_controller.h index 00d8d49..c8c531d 100644 --- a/ui/base/touch/touch_editing_controller.h +++ b/ui/base/touch/touch_editing_controller.h @@ -11,6 +11,36 @@ namespace ui { +// Bound of a selected region. +struct UI_BASE_EXPORT SelectionBound { + public: + enum Type { + LEFT, + RIGHT, + CENTER, + EMPTY, + LAST = EMPTY + }; + + SelectionBound(); + ~SelectionBound(); + + int GetHeight() const; + + Type type; + + gfx::Point edge_top; + gfx::Point edge_bottom; +}; + +UI_BASE_EXPORT bool operator==(const SelectionBound& lhs, + const SelectionBound& rhs); +UI_BASE_EXPORT bool operator!=(const SelectionBound& lhs, + const SelectionBound& rhs); + +UI_BASE_EXPORT gfx::Rect RectBetweenSelectionBounds(const SelectionBound& b1, + const SelectionBound& b2); + // An interface implemented by widget that has text that can be selected/edited // using touch. class UI_BASE_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { @@ -26,17 +56,18 @@ class UI_BASE_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { // Move the caret to |point|. |point| is in local coordinates. virtual void MoveCaretTo(const gfx::Point& point) = 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 (in local - // coordinates): + // Gets the end points of the current selection. The end points |anchor| and + // |focus| must be the cursor rect for the logical start and logical end of + // selection (in local coordinates): // ____________________________________ // | textfield with |selected text| | // ------------------------------------ - // ^p1 ^p2 + // ^anchor ^focus // - // 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; + // Visually, anchor could be to the right of focus in the figure above - it + // depends on the selection direction. + virtual void GetSelectionEndPoints(ui::SelectionBound* anchor, + ui::SelectionBound* focus) = 0; // Gets the bounds of the client view in its local coordinates. virtual gfx::Rect GetBounds() = 0; @@ -94,6 +125,6 @@ class UI_BASE_EXPORT TouchSelectionControllerFactory { virtual ~TouchSelectionControllerFactory() {} }; -} // namespace views +} // namespace ui #endif // UI_BASE_TOUCH_TOUCH_EDITING_CONTROLLER_H_ diff --git a/ui/base/touch/touch_editing_controller_unittest.cc b/ui/base/touch/touch_editing_controller_unittest.cc new file mode 100644 index 0000000..d6b047e --- /dev/null +++ b/ui/base/touch/touch_editing_controller_unittest.cc @@ -0,0 +1,99 @@ +// Copyright 2014 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/base/touch/touch_editing_controller.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace ui { + +namespace { + +} + +TEST(TouchEditingControllerTest, SelectionBound) { + SelectionBound b1, b2; + // Simple case of aligned vertical bounds of equal height + b1.edge_top = gfx::Point(0, 20); + b1.edge_bottom = gfx::Point(0, 25); + b2.edge_top = gfx::Point(110, 20); + b2.edge_bottom = gfx::Point(110, 25); + EXPECT_EQ(gfx::Rect(b1.edge_top, + gfx::Size(b2.edge_top.x() - b1.edge_top.x(), + b2.edge_bottom.y() - b2.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + // Parallel vertical bounds of different heights + b1.edge_top = gfx::Point(10, 20); + b1.edge_bottom = gfx::Point(10, 25); + b2.edge_top = gfx::Point(110, 0); + b2.edge_bottom = gfx::Point(110, 35); + EXPECT_EQ(gfx::Rect(gfx::Point(b1.edge_top.x(), b2.edge_top.y()), + gfx::Size(b2.edge_top.x() - b1.edge_top.x(), + b2.edge_bottom.y() - b2.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + b1.edge_top = gfx::Point(10, 20); + b1.edge_bottom = gfx::Point(10, 30); + b2.edge_top = gfx::Point(110, 25); + b2.edge_bottom = gfx::Point(110, 45); + EXPECT_EQ(gfx::Rect(b1.edge_top, + gfx::Size(b2.edge_top.x() - b1.edge_top.x(), + b2.edge_bottom.y() - b1.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + b1.edge_top = gfx::Point(10, 20); + b1.edge_bottom = gfx::Point(10, 30); + b2.edge_top = gfx::Point(110, 40); + b2.edge_bottom = gfx::Point(110, 60); + EXPECT_EQ(gfx::Rect(b1.edge_top, + gfx::Size(b2.edge_top.x() - b1.edge_top.x(), + b2.edge_bottom.y() - b1.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + // Overlapping vertical bounds + b1.edge_top = gfx::Point(10, 20); + b1.edge_bottom = gfx::Point(10, 30); + b2.edge_top = gfx::Point(10, 25); + b2.edge_bottom = gfx::Point(10, 40); + EXPECT_EQ(gfx::Rect(b1.edge_top, + gfx::Size(0, b2.edge_bottom.y() - b1.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + // Non-vertical bounds: "\ \" + b1.edge_top = gfx::Point(10, 20); + b1.edge_bottom = gfx::Point(20, 30); + b2.edge_top = gfx::Point(110, 40); + b2.edge_bottom = gfx::Point(120, 60); + EXPECT_EQ(gfx::Rect(b1.edge_top, + gfx::Size(b2.edge_bottom.x() - b1.edge_top.x(), + b2.edge_bottom.y() - b1.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); + + // Non-vertical bounds: "/ \" + b1.edge_top = gfx::Point(20, 30); + b1.edge_bottom = gfx::Point(0, 40); + b2.edge_top = gfx::Point(110, 30); + b2.edge_bottom = gfx::Point(120, 40); + EXPECT_EQ(gfx::Rect(gfx::Point(b1.edge_bottom.x(), b1.edge_top.y()), + gfx::Size(b2.edge_bottom.x() - b1.edge_bottom.x(), + b2.edge_bottom.y() - b2.edge_top.y())), + RectBetweenSelectionBounds(b1, b2)); + EXPECT_EQ(RectBetweenSelectionBounds(b1, b2), + RectBetweenSelectionBounds(b2, b1)); +} + +} // namespace ui |