Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/Selection.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/Selection.cpp b/third_party/WebKit/Source/core/editing/Selection.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8e836e9e26acd2e0fcd8dae5733203dac4bf9ce7 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/editing/Selection.cpp |
| @@ -0,0 +1,255 @@ |
| +// Copyright 2016 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 "core/editing/Selection.h" |
| + |
| +#include "wtf/Assertions.h" |
| +#include <ostream> // NOLINT |
| + |
| +namespace blink { |
| + |
| +template <typename Strategy> |
| +SelectionTemplate<Strategy>::SelectionTemplate(const SelectionTemplate& other) |
| + : m_base(other.m_base), |
| + m_extent(other.m_extent), |
| + m_affinity(other.m_affinity), |
| + m_granularity(other.m_granularity), |
| + m_hasTrailingWhitespace(other.m_hasTrailingWhitespace), |
| + m_isDirectional(other.m_isDirectional) |
| +#if ENABLE(ASSERT) |
|
tkent
2016/10/07 00:13:27
ENABLE(ASSERT) -> DCHECK_IS_ON()
|
| + , |
| + m_domTreeVersion(other.m_domTreeVersion) |
| +#endif |
| +{ |
| + other.assertValid(); |
| + if (!m_hasTrailingWhitespace) |
| + return; |
| + DCHECK_EQ(m_granularity, WordGranularity) << *this; |
| +} |
| + |
| +template <typename Strategy> |
| +SelectionTemplate<Strategy>::SelectionTemplate() = default; |
| + |
| +template <typename Strategy> |
| +bool SelectionTemplate<Strategy>::operator==( |
| + const SelectionTemplate& other) const { |
| + assertValid(); |
| + other.assertValid(); |
| + if (isNone()) |
| + return other.isNone(); |
| + if (other.isNone()) |
| + return false; |
| + DCHECK_EQ(m_base.document(), other.document()) << *this << ' ' << other; |
| + return m_base == other.m_base && m_extent == other.m_extent && |
| + m_affinity == other.m_affinity && |
| + m_granularity == other.m_granularity && |
| + m_hasTrailingWhitespace == other.m_hasTrailingWhitespace && |
| + m_isDirectional == other.m_isDirectional; |
| +} |
| + |
| +template <typename Strategy> |
| +bool SelectionTemplate<Strategy>::operator!=( |
| + const SelectionTemplate& other) const { |
| + return !operator==(other); |
| +} |
| + |
| +template <typename Strategy> |
| +const PositionTemplate<Strategy>& SelectionTemplate<Strategy>::base() const { |
| + assertValid(); |
| + DCHECK(!m_base.isOrphan()) << m_base; |
| + return m_base; |
| +} |
| + |
| +template <typename Strategy> |
| +Document* SelectionTemplate<Strategy>::document() const { |
| + assertValid(); |
| + return m_base.document(); |
| +} |
| + |
| +template <typename Strategy> |
| +const PositionTemplate<Strategy>& SelectionTemplate<Strategy>::extent() const { |
| + assertValid(); |
| + DCHECK(!m_extent.isOrphan()) << m_extent; |
| + return m_extent; |
| +} |
| + |
| +template <typename Strategy> |
| +void SelectionTemplate<Strategy>::assertValidFor( |
| + const Document& document) const { |
| + assertValid(); |
| + if (m_base.isNull()) |
| + return; |
| + DCHECK_EQ(m_base.document(), document) << *this; |
| +} |
| + |
| +#if ENABLE(ASSERT) |
|
tkent
2016/10/07 00:13:27
ENABLE(ASSERT) -> DCHECK_IS_ON()
|
| +template <typename Strategy> |
| +void SelectionTemplate<Strategy>::assertValid() const { |
| + if (m_base.isNull()) |
| + return; |
| + DCHECK_EQ(m_base.document()->domTreeVersion(), m_domTreeVersion) << *this; |
| + DCHECK(!m_base.isOrphan()) << *this; |
| + DCHECK(!m_extent.isOrphan()) << *this; |
| +} |
| +#else |
| +template <typename Strategy> |
| +void SelectionTemplate<Strategy>::assertValid() const {} |
| +#endif |
| + |
| +template <typename Strategy> |
| +void SelectionTemplate<Strategy>::printTo(std::ostream* ostream, |
| + const char* type) const { |
| + if (isNone()) { |
| + *ostream << "()"; |
| + return; |
| + } |
| + *ostream << type << '('; |
| +#if ENABLE(ASSERT) |
|
tkent
2016/10/07 00:13:27
ENABLE(ASSERT) -> DCHECK_IS_ON()
|
| + if (m_domTreeVersion != m_base.document()->domTreeVersion()) { |
| + *ostream << "Dirty: " << m_domTreeVersion; |
| + *ostream << " != " << m_base.document()->domTreeVersion() << ' '; |
| + } |
| +#endif |
| + *ostream << "base: " << m_base << ", extent: " << m_extent << ')'; |
| +} |
| + |
| +std::ostream& operator<<(std::ostream& ostream, const Selection& selection) { |
| + selection.printTo(&ostream, "Selection"); |
| + return ostream; |
| +} |
| + |
| +std::ostream& operator<<(std::ostream& ostream, |
| + const SelectionInFlatTree& selection) { |
| + selection.printTo(&ostream, "SelectionInFlatTree"); |
| + return ostream; |
| +} |
| + |
| +// -- |
| + |
| +template <typename Strategy> |
| +SelectionTemplate<Strategy>::Builder::Builder( |
| + const SelectionTemplate<Strategy>& selection) |
| + : m_selection(selection) {} |
| + |
| +template <typename Strategy> |
| +SelectionTemplate<Strategy>::Builder::Builder() = default; |
| + |
| +template <typename Strategy> |
| +SelectionTemplate<Strategy> SelectionTemplate<Strategy>::Builder::build() |
| + const { |
| + return m_selection; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::collapse( |
| + const PositionTemplate<Strategy>& position) { |
| + DCHECK(position.isNotNull()); |
| + m_selection.m_base = position; |
| + m_selection.m_extent = position; |
| +#if ENABLE(ASSERT) |
|
tkent
2016/10/07 00:13:27
ENABLE(ASSERT) -> DCHECK_IS_ON()
|
| + m_selection.m_domTreeVersion = position.document()->domTreeVersion(); |
| +#endif |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::collapse( |
| + const PositionWithAffinityTemplate<Strategy>& positionWithAffinity) { |
| + collapse(positionWithAffinity.position()); |
| + setAffinity(positionWithAffinity.affinity()); |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::extend( |
|
Xiaocheng
2016/10/06 08:02:33
We should check m_selection's validity to ensure t
|
| + const PositionTemplate<Strategy>& position) { |
| + DCHECK(position.isNotNull()); |
| + DCHECK(m_selection.base().isNotNull()); |
| + m_selection.m_extent = position; |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setAffinity(TextAffinity affinity) { |
| + m_selection.m_affinity = affinity; |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setBaseAndExtent( |
| + const EphemeralRangeTemplate<Strategy>& range) { |
| + if (range.isNull()) { |
| + m_selection.m_base = PositionTemplate<Strategy>(); |
| + m_selection.m_extent = PositionTemplate<Strategy>(); |
| +#if ENABLE(ASSERT) |
|
tkent
2016/10/07 00:13:27
ENABLE(ASSERT) -> DCHECK_IS_ON()
|
| + m_selection.m_domTreeVersion = 0; |
| +#endif |
| + return *this; |
| + } |
| + return collapse(range.startPosition()).extend(range.endPosition()); |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setBaseAndExtent( |
| + const PositionTemplate<Strategy>& base, |
| + const PositionTemplate<Strategy>& extent) { |
| + if (base.isNull()) { |
| + DCHECK(extent.isNull()) << extent; |
| + return setBaseAndExtent(EphemeralRangeTemplate<Strategy>()); |
| + } |
| + DCHECK(extent.isNotNull()); |
| + return collapse(base).extend(extent); |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setBaseAndExtentDeprecated( |
| + const PositionTemplate<Strategy>& base, |
| + const PositionTemplate<Strategy>& extent) { |
| + if (base.isNotNull() && extent.isNotNull()) { |
| + return setBaseAndExtent(base, extent); |
| + } |
| + if (base.isNotNull()) |
| + return collapse(base); |
| + if (extent.isNotNull()) |
| + return collapse(extent); |
| + m_selection.m_base = PositionTemplate<Strategy>(); |
| + m_selection.m_extent = PositionTemplate<Strategy>(); |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setGranularity( |
| + TextGranularity granularity) { |
| + m_selection.m_granularity = granularity; |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setHasTrailingWhitespace( |
| + bool hasTrailingWhitespace) { |
| + m_selection.m_hasTrailingWhitespace = hasTrailingWhitespace; |
| + return *this; |
| +} |
| + |
| +template <typename Strategy> |
| +typename SelectionTemplate<Strategy>::Builder& |
| +SelectionTemplate<Strategy>::Builder::setIsDirectional(bool isDirectional) { |
| + m_selection.m_isDirectional = isDirectional; |
| + return *this; |
| +} |
| + |
| +template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingStrategy>; |
| +template class CORE_TEMPLATE_EXPORT |
| + SelectionTemplate<EditingInFlatTreeStrategy>; |
| + |
| +} // namespace blink |