Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions src/notation/inotationinteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,35 @@ class INotationInteraction
virtual void setHitElementContext(const HitElementContext& context) = 0;

// Select
virtual INotationSelectionPtr selection() const = 0;
virtual muse::async::Notification selectionChanged() const = 0;
virtual void select(const std::vector<EngravingItem*>& elements, SelectType type = SelectType::REPLACE, staff_idx_t staffIndex = 0) = 0;
virtual void select(SelectionTarget target) = 0;

virtual void moveChordNoteSelection(MoveDirection d) = 0;
virtual void select(const std::vector<EngravingItem*>& elements, SelectType type = SelectType::REPLACE,
engraving::staff_idx_t staffIndex = 0) = 0;

virtual void selectAndStartEditIfNeeded(EngravingItem* element) = 0;
virtual void selectAll() = 0;
virtual void selectSection() = 0;
virtual void selectFirstElement(bool frame = true) = 0;
virtual void selectLastElement() = 0;
virtual INotationSelectionPtr selection() const = 0;

virtual void clearSelection() = 0;
virtual muse::async::Notification selectionChanged() const = 0;

virtual void selectTopOrBottomOfChord(MoveDirection d) = 0;
virtual void findAndSelectChordRest(const Fraction& tick) = 0;

// Change selection
virtual bool moveSelectionAvailable(MoveSelectionType type) const = 0;
virtual void moveSelection(MoveDirection d, MoveSelectionType type) = 0;

virtual void moveLyrics(MoveDirection d) = 0;
virtual void expandSelection(ExpandSelectionMode mode) = 0;
virtual void addToSelection(MoveDirection d, MoveSelectionType type) = 0;
virtual void selectTopStaff() = 0;
virtual void selectEmptyTrailingMeasure() = 0;
virtual void moveSegmentSelection(MoveDirection d) = 0;

virtual EngravingItem* contextItem() const = 0;

// SelectionFilter
Expand Down Expand Up @@ -138,17 +153,6 @@ class INotationInteraction
virtual void redo() = 0;
virtual void undoRedoToIndex(size_t idx) = 0;

// Change selection
virtual bool moveSelectionAvailable(MoveSelectionType type) const = 0;
virtual void moveSelection(MoveDirection d, MoveSelectionType type) = 0;

virtual void moveLyrics(MoveDirection d) = 0;
virtual void expandSelection(ExpandSelectionMode mode) = 0;
virtual void addToSelection(MoveDirection d, MoveSelectionType type) = 0;
virtual void selectTopStaff() = 0;
virtual void selectEmptyTrailingMeasure() = 0;
virtual void moveSegmentSelection(MoveDirection d) = 0;

// Move/nudge elements
virtual void movePitch(MoveDirection d, PitchMode mode) = 0;
virtual void nudge(MoveDirection d, bool quickly) = 0;
Expand Down
205 changes: 195 additions & 10 deletions src/notation/internal/notationinteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
#include "notationselection.h"
#include "notationselectionfilter.h"
#include "scorecallbacks.h"
#include "inotationelements.h"

#include "utilities/scorerangeutilities.h"

Expand Down Expand Up @@ -948,6 +949,128 @@ void NotationInteraction::moveSegmentSelection(MoveDirection d)
showItem(e);
}

FilterElementsOptions NotationInteraction::elementsFilterOptions(const EngravingItem* element) const
{
TRACEFUNC;
FilterElementsOptions options;
options.elementType = element->type();

if (element->isNote()) {
const mu::engraving::Note* note = dynamic_cast<const mu::engraving::Note*>(element);
if (note->chord()->isGrace()) {
options.subtype = -1;
} else {
options.subtype = element->subtype();
}
} else if (element->isHairpinSegment() || element->isHarmony()) {
options.subtype = element->subtype();
options.bySubtype = true;
}

return options;
}

void NotationInteraction::selectAllSimilarElements()
{
TRACEFUNC;
auto notationElements = m_notation->elements();
if (!notationElements) {
return;
}

EngravingItem* selectedElement = selection()->element();
if (!selectedElement) {
return;
}

FilterElementsOptions options = elementsFilterOptions(selectedElement);
std::vector<EngravingItem*> elements = notationElements->elements(options);
if (elements.empty()) {
return;
}

clearSelection();

select(elements, SelectType::ADD);
}

void NotationInteraction::selectAllSimilarElementsInStaff()
{
TRACEFUNC;
auto notationElements = m_notation->elements();
if (!notationElements) {
return;
}

EngravingItem* selectedElement = selection()->element();
if (!selectedElement) {
return;
}

FilterElementsOptions options = elementsFilterOptions(selectedElement);
options.staffStart = static_cast<int>(selectedElement->staffIdx());
options.staffEnd = options.staffStart + 1;

std::vector<EngravingItem*> elements = notationElements->elements(options);
if (elements.empty()) {
return;
}

clearSelection();

select(elements, SelectType::ADD);
}

void NotationInteraction::selectAllSimilarElementsInRange()
{
auto elements = m_notation->elements();
if (!elements) {
return;
}

mu::engraving::EngravingItem* lastHit = selection()->lastElementHit();
if (!lastHit) {
return;
}

mu::engraving::Score* score = elements->msScore();
score->selectSimilarInRange(lastHit);
if (score->selectionChanged()) {
selectionChanged().notify();
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

void NotationInteraction::selectAllNotesInChord()
{
TRACEFUNC;

const std::vector<EngravingItem*>& selectedElements = selection()->elements();
if (selectedElements.empty()) {
return;
}

std::set<const Chord*> chords;
for (const EngravingItem* item : selectedElements) {
if (item->isNote()) {
chords.insert(toNote(item)->chord());
}
}

if (chords.empty()) {
return;
}

std::vector<EngravingItem*> allNotes;
for (const Chord* chord : chords) {
for (Note* note : chord->notes()) {
allNotes.push_back(note);
}
}

clearSelection();
select(allNotes, SelectType::ADD);
}

EngravingItem* NotationInteraction::contextItem() const
{
EngravingItem* item = selection()->element();
Expand Down Expand Up @@ -1114,6 +1237,78 @@ void NotationInteraction::doSelect(const std::vector<EngravingItem*>& elements,
score()->select(elements, type, staffIndex);
}

void NotationInteraction::select(SelectionTarget target)
{
//! TODO It's better to change the implementation,
// instead of calling different methods, it's better to do this:
// 1. get target elements
// 2. call select method with the elements
switch (target) {
case SelectionTarget::Undefined:
break;
case SelectionTarget::FirstItem:
selectFirstElement();
break;
case SelectionTarget::LastItem:
selectLastElement();
break;
case SelectionTarget::NextItem:
moveSelection(MoveDirection::Right, MoveSelectionType::EngravingItem);
break;
case SelectionTarget::PrevItem:
moveSelection(MoveDirection::Left, MoveSelectionType::EngravingItem);
break;
case SelectionTarget::NextTrack:
moveSelection(MoveDirection::Right, MoveSelectionType::Track);
break;
case SelectionTarget::PrevTrack:
moveSelection(MoveDirection::Left, MoveSelectionType::Track);
break;
case SelectionTarget::NextFrame:
moveSelection(MoveDirection::Right, MoveSelectionType::Frame);
break;
case SelectionTarget::PrevFrame:
moveSelection(MoveDirection::Left, MoveSelectionType::Frame);
break;
case SelectionTarget::NextSystem:
moveSelection(MoveDirection::Right, MoveSelectionType::System);
break;
case SelectionTarget::PrevSystem:
moveSelection(MoveDirection::Left, MoveSelectionType::System);
break;
case SelectionTarget::UpNoteInChord:
moveChordNoteSelection(MoveDirection::Up);
break;
case SelectionTarget::DownNoteInChord:
moveChordNoteSelection(MoveDirection::Down);
break;
case SelectionTarget::TopNoteInChord:
selectTopOrBottomOfChord(MoveDirection::Up);
break;
case SelectionTarget::BottomNoteInChord:
selectTopOrBottomOfChord(MoveDirection::Down);
break;
case SelectionTarget::Similar:
selectAllSimilarElements();
break;
case SelectionTarget::SimilarInStaff:
selectAllSimilarElementsInStaff();
break;
case SelectionTarget::SimilarInRange:
selectAllSimilarElementsInRange();
break;
case SelectionTarget::NotesInChord:
selectAllNotesInChord();
break;
case SelectionTarget::All:
selectAll();
break;
case SelectionTarget::Section:
selectSection();
break;
}
}

void NotationInteraction::selectElementsWithSameTypeOnSegment(mu::engraving::ElementType elementType, mu::engraving::Segment* segment)
{
TRACEFUNC;
Expand Down Expand Up @@ -4187,16 +4382,6 @@ void NotationInteraction::toggleSnapToNext()

void NotationInteraction::moveElementSelection(MoveDirection d)
{
if (d == MoveDirection::First) {
selectFirstElement(false);
return;
}

if (d == MoveDirection::Last) {
selectLastElement();
return;
}

EngravingItem* el = score()->selection().element();
if (!el && !score()->selection().elements().empty()) {
el = score()->selection().elements().back();
Expand Down
34 changes: 22 additions & 12 deletions src/notation/internal/notationinteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,39 @@ class NotationInteraction : public INotationInteraction, public muse::Contextabl
void setHitElementContext(const HitElementContext& context) override;

// Select
INotationSelectionPtr selection() const override;
muse::async::Notification selectionChanged() const override;
void select(const std::vector<EngravingItem*>& elements, SelectType type = SelectType::REPLACE, staff_idx_t staffIndex = 0) override;
void select(SelectionTarget target) override;

void moveChordNoteSelection(MoveDirection d) override;
void select(const std::vector<EngravingItem*>& elements, SelectType type = SelectType::REPLACE,
engraving::staff_idx_t staffIndex = 0) override;

void selectAndStartEditIfNeeded(EngravingItem* element) override;
void selectAll() override;
void selectSection() override;
void selectFirstElement(bool frame = false) override;
void selectLastElement() override;
INotationSelectionPtr selection() const override;

void clearSelection() override;
muse::async::Notification selectionChanged() const override;

void selectTopOrBottomOfChord(MoveDirection d) override;
void findAndSelectChordRest(const Fraction& tick) override;
void moveSegmentSelection(MoveDirection d) override;

FilterElementsOptions elementsFilterOptions(const EngravingItem* element) const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make it private

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next PR I will clean up this interface and class

void selectAllSimilarElements();
void selectAllSimilarElementsInStaff();
void selectAllSimilarElementsInRange();
void selectAllNotesInChord();

// Change selection
bool moveSelectionAvailable(MoveSelectionType type) const override;
void moveSelection(MoveDirection d, MoveSelectionType type) override;
void expandSelection(ExpandSelectionMode mode) override;
void addToSelection(MoveDirection d, MoveSelectionType type) override;
void selectTopStaff() override;
void selectEmptyTrailingMeasure() override;

EngravingItem* contextItem() const override;

// SelectionFilter
Expand Down Expand Up @@ -152,14 +170,6 @@ class NotationInteraction : public INotationInteraction, public muse::Contextabl
void redo() override;
void undoRedoToIndex(size_t idx) override;

// Change selection
bool moveSelectionAvailable(MoveSelectionType type) const override;
void moveSelection(MoveDirection d, MoveSelectionType type) override;
void expandSelection(ExpandSelectionMode mode) override;
void addToSelection(MoveDirection d, MoveSelectionType type) override;
void selectTopStaff() override;
void selectEmptyTrailingMeasure() override;

// Move
void movePitch(MoveDirection d, PitchMode mode) override;
void nudge(MoveDirection d, bool quickly) override;
Expand Down
Loading
Loading