Skip to content

Commit

Permalink
Restore list and range selection on undo if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrio95 committed Oct 25, 2019
1 parent 7dc8ca5 commit 710cd6a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 18 deletions.
54 changes: 39 additions & 15 deletions libmscore/undo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,52 +401,76 @@ void UndoStack::redo(EditData* ed)
// UndoMacro
//---------------------------------------------------------

Element* UndoMacro::selectedElement(const Selection& sel)
void UndoMacro::fillSelectionInfo(SelectionInfo& info, const Selection& sel)
{
if (sel.isSingle()) {
Element* e = sel.element();
Q_ASSERT(e); // otherwise it shouldn't be "single" selection
if (e->isNote() || e->isChordRest() || (e->isTextBase() && !e->isInstrumentName()) || e->isFretDiagram())
return e;
info.staffStart = info.staffEnd = -1;
info.elements.clear();

if (sel.isList()) {
for (Element* e : sel.elements()) {
if (e->isNote() || e->isChordRest() || (e->isTextBase() && !e->isInstrumentName()) || e->isFretDiagram())
info.elements.push_back(e);
else {
// don't remember selection we are unable to restore
info.elements.clear();
return;
}
}
}
else if (sel.isRange()) {
info.staffStart = sel.staffStart();
info.staffEnd = sel.staffEnd();
info.tickStart = sel.tickStart();
info.tickEnd = sel.tickEnd();
}
}

void UndoMacro::applySelectionInfo(const SelectionInfo& info, Selection& sel)
{
if (!info.elements.empty()) {
for (Element* e : info.elements)
sel.add(e);
}
else if (info.staffStart != -1) {
sel.setRangeTicks(info.tickStart, info.tickEnd, info.staffStart, info.staffEnd);
}
return nullptr;
}

UndoMacro::UndoMacro(Score* s)
: undoInputState(s->inputState()),
undoSelectedElement(selectedElement(s->selection())), score(s)
: undoInputState(s->inputState()), score(s)
{
fillSelectionInfo(undoSelectionInfo, s->selection());
}

void UndoMacro::undo(EditData* ed)
{
redoInputState = score->inputState();
redoSelectedElement = selectedElement(score->selection());
fillSelectionInfo(redoSelectionInfo, score->selection());
score->deselectAll();

// Undo for child commands.
UndoCommand::undo(ed);

score->setInputState(undoInputState);
if (undoSelectedElement) {
if (undoSelectionInfo.isValid()) {
score->deselectAll();
score->selection().add(undoSelectedElement);
applySelectionInfo(undoSelectionInfo, score->selection());
}
}

void UndoMacro::redo(EditData* ed)
{
undoInputState = score->inputState();
undoSelectedElement = selectedElement(score->selection());
fillSelectionInfo(undoSelectionInfo, score->selection());
score->deselectAll();

// Redo for child commands.
UndoCommand::redo(ed);

score->setInputState(redoInputState);
if (redoSelectedElement) {
if (redoSelectionInfo.isValid()) {
score->deselectAll();
score->selection().add(redoSelectedElement);
applySelectionInfo(redoSelectionInfo, score->selection());
}
}

Expand Down
18 changes: 15 additions & 3 deletions libmscore/undo.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,25 @@ class UndoCommand {
//---------------------------------------------------------

class UndoMacro : public UndoCommand {
struct SelectionInfo {
std::vector<Element*> elements;
Fraction tickStart;
Fraction tickEnd;
int staffStart = -1;
int staffEnd = -1;

bool isValid() const { return !elements.empty() || staffStart != -1; }
};

InputState undoInputState;
InputState redoInputState;
Element* undoSelectedElement = nullptr;
Element* redoSelectedElement = nullptr;
SelectionInfo undoSelectionInfo;
SelectionInfo redoSelectionInfo;

Score* score;

static Element* selectedElement(const Selection&);
static void fillSelectionInfo(SelectionInfo&, const Selection&);
static void applySelectionInfo(const SelectionInfo&, Selection&);

public:
UndoMacro(Score* s);
Expand Down

0 comments on commit 710cd6a

Please sign in to comment.