Selection mode in Editing text 81/159681/2
authorPawel Kurowski <p.kurowski2@samsung.com>
Fri, 10 Nov 2017 11:56:13 +0000 (12:56 +0100)
committerPawel Kurowski <p.kurowski2@samsung.com>
Fri, 10 Nov 2017 13:16:38 +0000 (14:16 +0100)
Change-Id: I578b76666fa51e6ea89cebcc10bb2cebdba63076

src/Atspi.cpp
src/Atspi.hpp
src/EditTextActivity.cpp

index b37bc0a..9f8d124 100644 (file)
@@ -1110,6 +1110,8 @@ void Atspi::setTextSelection(const AtspiTextPtr &textInterface, TextRange range,
                ERROR("Incorrect range - start: %d, end: %d", range.start, range.end);
                return;
        }
+       if (range.start == range.end)
+               removeTextSelection(textInterface, selectionNum);
        GError *error = nullptr;
        if (!atspi_text_set_selection(textInterface.get(), selectionNum, range.start, range.end, &error))
                ERROR("atspi_text_set_selection failed");
index f8dc984..7cf6e47 100644 (file)
@@ -23,6 +23,7 @@ using AtspiTextPtr = std::shared_ptr<AtspiText>;
 using AtspiEditableTextPtr = std::shared_ptr<AtspiEditableText>;
 
 struct TextRange {
+       TextRange(size_t v1, size_t v2) : start(std::min(v1, v2)), end(std::max(v1, v2)) {}
        size_t start;
        size_t end;
 };
index 50583e9..95540b9 100644 (file)
@@ -122,11 +122,11 @@ public:
        using EditTextActivity<DerivedType>::atspiText;
        using EditTextActivity<DerivedType>::getAtspiInterfaces;
        using EditTextActivity<DerivedType>::markAsCompleted;
+
        void process() override
        {
-               //TODO SelectionMode
                getAtspiInterfaces();
-               move(DerivedType::DIRECTION, getGranularity());
+               move(DerivedType::DIRECTION, getGranularity(), getMode());
                markAsCompleted();
        }
 
@@ -136,19 +136,37 @@ protected:
                NEXT = true
        };
 
+       enum class Mode {
+               EDITION = 1,
+               SELECTION
+       };
+
        Atspi::Granularity getGranularity()
        {
-               auto vconfValue = Singleton<VConfInterface>::instance().get(VCONF_KEY_GRANULARITY_UNIT, 1);
-               auto ret = static_cast<Atspi::Granularity>(vconfValue);
-               if (ret >= Atspi::Granularity::CHAR && ret <= Atspi::Granularity::PARAGRAPH)
-                       return ret;
-               else
-                       return Atspi::Granularity::CHAR;
+               return valueInBounds(
+                                  static_cast<Atspi::Granularity>(Singleton<VConfInterface>::instance().get(VCONF_KEY_GRANULARITY_UNIT, 1)),
+                                  Atspi::Granularity::CHAR,
+                                  Atspi::Granularity::PARAGRAPH,
+                                  Atspi::Granularity::CHAR);
+       }
+
+       Mode getMode()
+       {
+               return valueInBounds(
+                                  static_cast<Mode>(Singleton<VConfInterface>::instance().get(VCONF_KEY_TEXT_EDITION_MODE, 1)),
+                                  Mode::EDITION,
+                                  Mode::SELECTION,
+                                  Mode::EDITION);
        }
 
-       void move(const Direction direction, const Atspi::Granularity granularity)
+       void move(const Direction direction, const Atspi::Granularity granularity, const Mode mode = Mode::EDITION)
        {
                const auto currentSelectionRange = atspi->getTextSelection(atspiText);
+               if (mode == Mode::SELECTION) {
+                       selectByGranularityUnit(direction, granularity, currentSelectionRange);
+                       return;
+               }
+
                if (currentSelectionRange)
                        moveToSelectionLimit(direction, granularity, *currentSelectionRange);
                else
@@ -156,6 +174,15 @@ protected:
        }
 
 private:
+       template<typename T>
+       T valueInBounds(T value, const T &lowerLimit, const T &upperLimit, const T &defaultValue)
+       {
+               if (value < lowerLimit || value > upperLimit)
+                       value = defaultValue;
+
+               return value;
+       }
+
        void moveToSelectionLimit(const Direction direction, const Atspi::Granularity granularity, const TextRange currentSelectionRange)
        {
                auto selectionMarker = (direction == Direction::NEXT) ? currentSelectionRange.end : currentSelectionRange.start;
@@ -167,14 +194,52 @@ private:
        void moveByGranularityUnit(const Direction direction, const Atspi::Granularity granularity)
        {
                const auto offset = atspi->getTextCaretOffset(atspiText);
-               const auto limit = atspi->countTextCharacters(atspiText);
-               if (!offset || !limit)
+               if (!offset)
+                       return;
+
+               const auto finalOffset = getLimitOfAdjoiningGranularityUnit(direction, granularity, *offset);
+               DEBUG("Moving caret from: %d to: %d", *offset, finalOffset);
+               atspi->setTextCaretOffset(atspiText, finalOffset);
+       }
+
+       void selectByGranularityUnit(const Direction direction, const Atspi::Granularity granularity, const Optional<TextRange> range)
+       {
+               const auto offset = atspi->getTextCaretOffset(atspiText);
+               if (!offset)
                        return;
 
-               auto currentOffset = *offset;
+               const auto finalOffset = getLimitOfAdjoiningGranularityUnit(direction, granularity, *offset);
+               const auto newSelection = TextRange {*offset, finalOffset};
+               const auto finalSelection = range ? compareNewSelectionWithOldOne(direction, newSelection, *range) : newSelection;
+
+               DEBUG("Selectiong from from: %d to: %d", finalSelection.start, finalSelection.end);
+               atspi->setTextSelection(atspiText, finalSelection);
+               atspi->setTextCaretOffset(atspiText, finalOffset);
+       }
+
+       TextRange compareNewSelectionWithOldOne(const Direction direction, TextRange newSelection, const TextRange oldSelection)
+       {
+               if (direction == Direction::PREV)
+                       return (newSelection.end == oldSelection.end) ?
+                                  TextRange {oldSelection.start, newSelection.start} :
+                                  TextRange {newSelection.start, oldSelection.end};
+
+               return (newSelection.start == oldSelection.start) ?
+                          TextRange {newSelection.end, oldSelection.end} :
+                          TextRange {oldSelection.start, newSelection.end};
+
+       }
+
+       size_t getLimitOfAdjoiningGranularityUnit(const Direction direction, const Atspi::Granularity granularity, const size_t offset)
+       {
+               auto currentOffset = offset;
+               const auto limit = atspi->countTextCharacters(atspiText);
+               if (!limit)
+                       return offset;
+
                auto range = atspi->getTextRangeAtOffset(atspiText, currentOffset, granularity);
                if (!range)
-                       return;
+                       return offset;
 
                auto finalOffset = range->end;
 
@@ -186,7 +251,7 @@ private:
                                }
                                range = atspi->getTextRangeAtOffset(atspiText, currentOffset, granularity);
                                if (!range)
-                                       return;
+                                       return offset;
 
                                finalOffset = range->end;
                        } while (currentOffset > finalOffset);
@@ -196,13 +261,12 @@ private:
 
                        range = atspi->getTextRangeAtOffset(atspiText, currentOffset, granularity);
                        if (!range)
-                               return;
+                               return offset;
 
                        finalOffset = range->start;
                }
 
-               DEBUG("Moving caret from: %d to: %d", *offset, finalOffset);
-               atspi->setTextCaretOffset(atspiText, finalOffset);
+               return finalOffset;
        }
 };