Chromium Code Reviews| 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..a2ac47b34639a7d0c1e9fef09524695345aaf161 |
| --- /dev/null |
| +++ b/Source/core/editing/GranularityStrategy.cpp |
| @@ -0,0 +1,126 @@ |
| +/* |
|
yosin_UTC9
2015/04/21 01:59:51
nit: Let's use the short version of licence commen
mfomitchev
2015/04/21 18:44:25
Done.
|
| + * Copyright 2015, Google Inc. All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are |
| + * met: |
| + * |
| + * * Redistributions of source code must retain the above copyright |
| + * notice, this list of conditions and the following disclaimer. |
| + * * Redistributions in binary form must reproduce the above |
| + * copyright notice, this list of conditions and the following disclaimer |
| + * in the documentation and/or other materials provided with the |
| + * distribution. |
| + * * Neither the name of Google Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived from |
| + * this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#include "config.h" |
| +#include "core/editing/GranularityStrategy.h" |
| + |
| +#include "core/editing/htmlediting.h" |
| + |
| +namespace blink { |
| + |
| +VisibleSelection CharacterGranularityStrategy::updateExtent(const VisiblePosition& extentPosition, const VisibleSelection& selection) |
| +{ |
| + return VisibleSelection(selection.visibleBase(), extentPosition); |
| +} |
| + |
| +DirectionGranularityStrategy::DirectionGranularityStrategy() |
| + : m_granularity(CharacterGranularity) |
| + , m_lastMoveShrunkSelection(false) { } |
| + |
| +void DirectionGranularityStrategy::Clear() |
| +{ |
| + m_granularity = CharacterGranularity; |
| + m_lastMoveShrunkSelection = false; |
| +} |
| + |
| +VisiblePosition DirectionGranularityStrategy::nextWordBound( |
| + const VisiblePosition& pos, |
| + ESearchDirection direction, |
| + EBoundAdjust wordBoundAdjust) |
| +{ |
| + if (direction == ESearchDirection::SearchForward) |
|
yosin_UTC9
2015/04/21 01:59:51
Q: How about using if-statement rather than ternar
mfomitchev
2015/04/21 18:44:25
I moved the ternary operator out and added a bool
|
| + return endOfWord(pos, wordBoundAdjust == EBoundAdjust::CurrentPosIfOnBound ? LeftWordIfOnBoundary : RightWordIfOnBoundary); |
| + return startOfWord(pos, wordBoundAdjust == EBoundAdjust::CurrentPosIfOnBound ? RightWordIfOnBoundary : LeftWordIfOnBoundary); |
| +} |
| + |
| +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 ? ESearchDirection::SearchForward : ESearchDirection::SearchBackwards, |
| + m_lastMoveShrunkSelection ? EBoundAdjust::NextBoundIfOnBound : EBoundAdjust::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 ? ESearchDirection::SearchForward : ESearchDirection::SearchBackwards, |
| + EBoundAdjust::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 |