35 define_declared_event(CurrentIndexChanged, current_index_changed,
const optional_item_presentation_model_index& ,
const optional_item_presentation_model_index& )
86 if (iModel == &aModel)
92 i_item_presentation_model* oldModel = iModel;
98 iCurrentIndex = std::nullopt;
101 iSink +=
presentation_model().item_added([
this](item_presentation_model_index
const& aIndex)
110 iSink +=
presentation_model().item_removing([
this](item_presentation_model_index
const& aIndex)
115 iCurrentIndex = std::nullopt;
119 iCurrentIndex->set_row(aIndex.row() - 1u);
123 iSink +=
presentation_model().item_expanded([
this](item_presentation_model_index
const& aIndex)
126 iCurrentIndex = std::nullopt;
129 iSink +=
presentation_model().item_collapsed([
this](item_presentation_model_index
const& aIndex)
132 iCurrentIndex = std::nullopt;
144 if (iSavedModelIndex != std::nullopt)
146 iSavedModelIndex = std::nullopt;
158 if (iSavedModelIndex != std::nullopt &&
presentation_model().has_item_model_index(*iSavedModelIndex))
162 iSavedModelIndex = std::nullopt;
167 auto oldModel = iModel;
169 iCurrentIndex = std::nullopt;
170 iSavedModelIndex = std::nullopt;
172 PresentationModelRemoved.trigger(*oldModel);
175 if (oldModel ==
nullptr)
216 item_presentation_model_index
relative_to_index(item_presentation_model_index
const& aIndex,
index_location aRelativeLocation,
bool aSelectable =
true,
bool aEditable =
false)
const override
218 item_presentation_model_index result = aIndex;
219 auto acceptable = [
this, aSelectable, aEditable](item_presentation_model_index aIndex)
223 switch (aRelativeLocation)
227 result = item_presentation_model_index{ 0u, 0u };
228 while (!acceptable(result) && (result =
next_cell(result)) != item_presentation_model_index{ 0u, 0u })
247 result.set_column(0u);
248 while (!acceptable(result) && (result += item_presentation_model_index{ 0u, 1u }).column() !=
presentation_model().columns() - 1u)
253 while (!acceptable(result) && (result -= item_presentation_model_index{ 0u, 1u }).column() != 0u)
258 while (!acceptable(result) && (result += item_presentation_model_index{ 1u, 0u }).column() !=
presentation_model().rows() - 1u)
263 while (!acceptable(result) && (result -= item_presentation_model_index{ 1, 0 }).
row() != 0u)
267 if (result.column() > 0u)
269 result -= item_presentation_model_index{ 0u, 1u };
270 while (!acceptable(result) && result.column() > 0u)
271 result -= item_presentation_model_index{ 0u, 1u };
277 result += item_presentation_model_index{ 0u, 1u };
279 result += item_presentation_model_index{ 0u, 1u };
283 if (result.row() > 0u)
285 result -= item_presentation_model_index{ 1u, 0u };
286 while (!acceptable(result) && result.row() > 0u)
287 result -= item_presentation_model_index{ 1u, 0u };
293 result += item_presentation_model_index{ 1u, 0u };
295 result += item_presentation_model_index{ 1u, 0u };
299 return acceptable(result) ? result : aIndex;
367 iOperationQueue.push_back(std::make_pair(aIndex, aOperation));
382 if (aSelection.empty())
383 return aSelection.end();
384 auto iterExisting = aSelection.lower_bound(aIndex.with_column(0u));
385 if (iterExisting == aSelection.end())
387 if (iterExisting != aSelection.begin())
390 if (previous->second().topLeft.row() <= aIndex.row() &&
391 previous->second().bottomRight.row() >= aIndex.row())
394 if (iterExisting->second().topLeft.row() <= aIndex.row() &&
395 iterExisting->second().bottomRight.row() >= aIndex.row())
397 return aSelection.end();
399 static auto find_adjacent = [](item_presentation_model_index
const& aIndex,
concrete_item_selection& aSelection)
401 if (aSelection.empty())
402 return aSelection.end();
403 auto iterExisting = find(aIndex.with_row(aIndex.row() - 1u), aSelection);
404 if (iterExisting != aSelection.end())
406 return find(aIndex.with_row(aIndex.row() + 1u), aSelection);
421 struct selection_clearer : i_item_presentation_model::i_meta_visitor
423 void visit(i_item_presentation_model::cell_meta_type& aMeta)
override
434 if (find(aIndex, aSelection) == aSelection.end())
436 auto iterAdjacent = find_adjacent(aIndex, aSelection);
437 if (iterAdjacent == aSelection.end())
438 aSelection.
emplace(aIndex.with_column(0u),
selection_area{ aIndex.with_column(0u), aIndex.with_column(presentation_model().columns() - 1u) });
441 auto& adjacent = *iterAdjacent;
442 if (adjacent.second().bottomRight.row() == aIndex.row() - 1u)
443 adjacent.second().bottomRight = aIndex.with_column(
presentation_model().columns() - 1u);
446 aSelection.
emplace(aIndex.with_column(0u),
selection_area{ aIndex.with_column(0u), adjacent.second().bottomRight });
447 aSelection.erase(iterAdjacent);
452 for (
auto& cellIndex : *
this)
453 if (cellIndex.row() == aIndex.row() &&
is_selectable(cellIndex))
459 for (
auto& cellIndex : *
this)
460 if (cellIndex.row() == aIndex.row())
462 auto iterExisting = find(aIndex, aSelection);
463 if (iterExisting != aSelection.end())
465 auto& existing = *iterExisting;
466 if (existing.second().topLeft.row() == existing.second().bottomRight.row())
467 aSelection.erase(iterExisting);
468 else if (existing.second().topLeft.row() == aIndex.row())
470 aSelection.
emplace(aIndex.with_row(aIndex.row() + 1u).with_column(0u),
selection_area{ aIndex.with_row(aIndex.row() + 1u).with_column(0u), existing.second().bottomRight });
471 aSelection.erase(iterExisting);
473 else if (existing.second().bottomRight.row() == aIndex.row())
474 existing.second().bottomRight.set_row(aIndex.row() - 1u);
477 aSelection.
emplace(aIndex.with_row(aIndex.row() + 1u).with_column(0u),
selection_area{ aIndex.with_row(aIndex.row() + 1u).with_column(0u), existing.second().bottomRight });
478 existing.second().bottomRight.set_row(aIndex.row() - 1u);
483 update(iSelection,
true);
487 SelectionChanged.trigger(iSelection, iPreviousSelection);
489 update(iPreviousSelection,
false);