Index: Source/core/editing/GranularityStrategy.cpp |
diff --git a/Source/core/editing/GranularityStrategy.cpp b/Source/core/editing/GranularityStrategy.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5a5fd9ee30330abf12efdd949c68fff152dc0636 |
--- /dev/null |
+++ b/Source/core/editing/GranularityStrategy.cpp |
@@ -0,0 +1,128 @@ |
+// Copyright 2015 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 "config.h" |
+#include "core/editing/GranularityStrategy.h" |
+ |
+#include "core/editing/htmlediting.h" |
+ |
+namespace blink { |
+ |
+GranularityStrategy::GranularityStrategy() { } |
+ |
+GranularityStrategy::~GranularityStrategy() { } |
+ |
+CharacterGranularityStrategy::CharacterGranularityStrategy() { } |
+ |
+CharacterGranularityStrategy::~CharacterGranularityStrategy() { } |
+ |
+SelectionStrategy CharacterGranularityStrategy::GetType() const |
+{ |
+ return SelectionStrategy::Character; |
+} |
+ |
+void CharacterGranularityStrategy::Clear() { }; |
+ |
+VisibleSelection CharacterGranularityStrategy::updateExtent(const VisiblePosition& extentPosition, const VisibleSelection& selection) |
+{ |
+ return VisibleSelection(selection.visibleBase(), extentPosition); |
+} |
+ |
+DirectionGranularityStrategy::DirectionGranularityStrategy() |
+ : m_granularity(CharacterGranularity) |
+ , m_lastMoveShrunkSelection(false) { } |
+ |
+DirectionGranularityStrategy::~DirectionGranularityStrategy() { } |
+ |
+SelectionStrategy DirectionGranularityStrategy::GetType() const |
+{ |
+ return SelectionStrategy::Direction; |
+} |
+ |
+void DirectionGranularityStrategy::Clear() |
+{ |
+ m_granularity = CharacterGranularity; |
+ m_lastMoveShrunkSelection = false; |
+} |
+ |
+VisiblePosition DirectionGranularityStrategy::nextWordBound( |
+ const VisiblePosition& pos, |
+ SearchDirection direction, |
+ BoundAdjust wordBoundAdjust) |
+{ |
+ bool nextBoundIfOnBound = wordBoundAdjust == BoundAdjust::NextBoundIfOnBound; |
+ if (direction == SearchDirection::SearchForward) { |
+ EWordSide wordSide = nextBoundIfOnBound ? RightWordIfOnBoundary : LeftWordIfOnBoundary; |
+ return endOfWord(pos, wordSide); |
+ } |
+ EWordSide wordSide = nextBoundIfOnBound ? LeftWordIfOnBoundary : RightWordIfOnBoundary; |
+ return startOfWord(pos, wordSide); |
+} |
+ |
+VisibleSelection DirectionGranularityStrategy::updateExtent(const VisiblePosition& extentPosition, const VisibleSelection& selection) |
+{ |
+ if (extentPosition == selection.visibleExtent()) |
+ return selection; |
+ |
+ const VisiblePosition base = selection.visibleBase(); |
+ const VisiblePosition oldExtentWithGranularity = selection.isBaseFirst() ? selection.visibleEnd() : selection.visibleStart(); |
+ |
+ int extentBaseOrder = comparePositions(extentPosition, base); |
+ int oldExtentBaseOrder = comparePositions(oldExtentWithGranularity, base); |
+ |
+ bool extentBaseOrderSwitched = (extentBaseOrder > 0 && oldExtentBaseOrder < 0) |
+ || (extentBaseOrder < 0 && oldExtentBaseOrder > 0); |
+ |
+ // Determine the boundary of the 'current word', i.e. the boundary extending |
+ // beyond which should change the granularity to WordGranularity. |
+ // If the last move has shrunk the selection and is now exactly on the word |
+ // boundary - we need to take the next bound as the bound of the "current |
+ // word". |
+ VisiblePosition currentWordBoundary = nextWordBound( |
+ oldExtentWithGranularity, |
+ oldExtentBaseOrder > 0 ? SearchDirection::SearchForward : SearchDirection::SearchBackwards, |
+ m_lastMoveShrunkSelection ? BoundAdjust::NextBoundIfOnBound : BoundAdjust::CurrentPosIfOnBound); |
+ |
+ bool thisMoveShrunkSelection = (extentBaseOrder > 0 && comparePositions(extentPosition, selection.visibleExtent()) < 0) |
+ || (extentBaseOrder < 0 && comparePositions(extentPosition, selection.visibleExtent()) > 0); |
+ // If the extent-base order was switched, then the selection is now |
+ // expanding in a different direction than before. Therefore we need to |
+ // calculate the boundary of the 'current word' in this new direction in |
+ // order to be able to tell if the selection expanded beyond it. |
+ if (extentBaseOrderSwitched) { |
+ currentWordBoundary = nextWordBound( |
+ base, |
+ extentBaseOrder > 0 ? SearchDirection::SearchForward : SearchDirection::SearchBackwards, |
+ BoundAdjust::NextBoundIfOnBound); |
+ m_granularity = CharacterGranularity; |
+ // When the base/extent order switches it doesn't count as shrinking selection. |
+ thisMoveShrunkSelection = false; |
+ } |
+ |
+ bool expandedBeyondWordBoundary; |
+ if (extentBaseOrder > 0) |
+ expandedBeyondWordBoundary = comparePositions(extentPosition, currentWordBoundary) > 0; |
+ else |
+ expandedBeyondWordBoundary = comparePositions(extentPosition, currentWordBoundary) < 0; |
+ if (expandedBeyondWordBoundary) { |
+ m_granularity = WordGranularity; |
+ } else if (thisMoveShrunkSelection) { |
+ m_granularity = CharacterGranularity; |
+ m_lastMoveShrunkSelection = true; |
+ } |
+ |
+ m_lastMoveShrunkSelection = thisMoveShrunkSelection; |
+ VisibleSelection newSelection = selection; |
+ newSelection.setExtent(extentPosition); |
+ if (m_granularity == WordGranularity) { |
+ if (extentBaseOrder > 0) |
+ newSelection.setEndRespectingGranularity(m_granularity, LeftWordIfOnBoundary); |
+ else |
+ newSelection.setStartRespectingGranularity(m_granularity, RightWordIfOnBoundary); |
+ } |
+ |
+ return newSelection; |
+} |
+ |
+} // namespace blink |