90 lines
2.7 KiB
C++
90 lines
2.7 KiB
C++
![]() |
#pragma once
|
||
|
|
||
|
#include "xtr/viewmodel/vmTextEdit.h"
|
||
|
|
||
|
#include <set>
|
||
|
|
||
|
class MockTextEditCtrl : public xtr::viewmodel::ITextEdit {
|
||
|
public:
|
||
|
struct rangeComparator {
|
||
|
constexpr bool operator()(const xtr::viewmodel::HighlightItem& rng1,
|
||
|
const xtr::viewmodel::HighlightItem& rng2) const noexcept {
|
||
|
return rng1.rng.start < rng2.rng.start;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
CString text{};
|
||
|
std::set<xtr::viewmodel::HighlightItem, rangeComparator> items{};
|
||
|
|
||
|
private:
|
||
|
[[nodiscard]] CString GetText() const override {
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
void SetText(const CString newText) override {
|
||
|
text = newText;
|
||
|
items.clear();
|
||
|
}
|
||
|
|
||
|
void ReplaceRange(const StrRange range, const CString replacement) override {
|
||
|
CString newText{};
|
||
|
if (range.start > 0) {
|
||
|
newText.Append(text.Left(range.start - 1));
|
||
|
}
|
||
|
newText.Append(replacement);
|
||
|
if (range.finish < text.GetLength()) {
|
||
|
newText.Append(text.Right(text.GetLength() - range.finish));
|
||
|
}
|
||
|
text = newText;
|
||
|
|
||
|
std::set<xtr::viewmodel::HighlightItem, rangeComparator> newItems{};
|
||
|
const auto shift = replacement.GetLength() - range.length();
|
||
|
for (auto refIt = begin(items); refIt != end(items); ++refIt) {
|
||
|
const auto& refPosition = refIt->rng;
|
||
|
if (refPosition.Meets(range) || refPosition.IsBefore(range)) {
|
||
|
newItems.emplace(*refIt);
|
||
|
} else if (range.Meets(refPosition) || refPosition.IsAfter(range)) {
|
||
|
auto newRef = *refIt;
|
||
|
newRef.rng.Shift(shift);
|
||
|
newItems.emplace(newRef);
|
||
|
} else if (range.Contains(refPosition)) {
|
||
|
continue;
|
||
|
} else {
|
||
|
auto newRef = *refIt;
|
||
|
if (refPosition.start < range.start) {
|
||
|
newRef.rng.SetLength(refPosition.length() - refPosition.Intersect(range)->length());
|
||
|
} else {
|
||
|
newRef.rng = StrRange::FromLength(range.start, std::max(0,
|
||
|
refPosition.length() - refPosition.Intersect(range)->length()));
|
||
|
}
|
||
|
newItems.emplace(newRef);
|
||
|
}
|
||
|
}
|
||
|
items = newItems;
|
||
|
}
|
||
|
|
||
|
void Highlight(xtr::viewmodel::HighlightItem item) override {
|
||
|
items.insert(item);
|
||
|
}
|
||
|
|
||
|
[[nodiscard]] std::optional<xtr::viewmodel::HighlightItem> NextHighlighted(const StrPos start) override {
|
||
|
if (start == 0) {
|
||
|
if (empty(items)) {
|
||
|
return std::nullopt;
|
||
|
} else {
|
||
|
return *begin(items);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (auto it = std::find_if(begin(items), end(items),
|
||
|
[&](const xtr::viewmodel::HighlightItem& item) { return item.rng.start == start; });
|
||
|
it == end(items)) {
|
||
|
return std::nullopt;
|
||
|
} else if (++it; it == end(items)) {
|
||
|
return std::nullopt;
|
||
|
} else {
|
||
|
return *it;
|
||
|
}
|
||
|
}
|
||
|
};
|