Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <cfloat>
24 :
25 : #include "notationselectionrange.h"
26 :
27 : #include "utilities/scorerangeutilities.h"
28 :
29 : #include "engraving/dom/chordrest.h"
30 : #include "engraving/dom/measure.h"
31 : #include "engraving/dom/score.h"
32 : #include "engraving/dom/segment.h"
33 : #include "engraving/dom/select.h"
34 : #include "engraving/dom/staff.h"
35 :
36 : using namespace mu::notation;
37 : using namespace mu::engraving;
38 :
39 0 : NotationSelectionRange::NotationSelectionRange(IGetScore* getScore)
40 0 : : m_getScore(getScore)
41 : {
42 0 : }
43 :
44 0 : staff_idx_t NotationSelectionRange::startStaffIndex() const
45 : {
46 0 : const mu::engraving::Selection& selection = score()->selection();
47 0 : return selection.staffStart();
48 : }
49 :
50 0 : Fraction NotationSelectionRange::startTick() const
51 : {
52 0 : const mu::engraving::Selection& selection = score()->selection();
53 0 : return selection.tickStart();
54 : }
55 :
56 0 : staff_idx_t NotationSelectionRange::endStaffIndex() const
57 : {
58 0 : const mu::engraving::Selection& selection = score()->selection();
59 0 : return selection.staffEnd();
60 : }
61 :
62 0 : Fraction NotationSelectionRange::endTick() const
63 : {
64 0 : const mu::engraving::Selection& selection = score()->selection();
65 0 : return selection.tickEnd();
66 : }
67 :
68 0 : NotationSelectionRange::MeasureBaseRange NotationSelectionRange::measureBaseRange() const
69 : {
70 0 : MeasureBaseRange range;
71 0 : score()->selection().measureBaseRange(&range.startMeasureBase, &range.endMeasureBase);
72 :
73 0 : return range;
74 : }
75 :
76 0 : std::vector<muse::RectF> NotationSelectionRange::boundingArea() const
77 : {
78 0 : return ScoreRangeUtilities::boundingArea(score(),
79 0 : rangeStartSegment(), rangeEndSegment(),
80 0 : startStaffIndex(), endStaffIndex(),
81 0 : rangeStartBox(), rangeEndBox());
82 : }
83 :
84 0 : bool NotationSelectionRange::containsPoint(const PointF& point) const
85 : {
86 0 : for (const muse::RectF& area : boundingArea()) {
87 0 : if (area.contains(point)) {
88 0 : return true;
89 : }
90 0 : }
91 :
92 0 : return false;
93 : }
94 :
95 : /// When `item` is a Measure, use `staffIdx` to query whether a specific staff is contained in the selection.
96 0 : bool NotationSelectionRange::containsItem(const EngravingItem* item, engraving::staff_idx_t staffIdx) const
97 : {
98 0 : Fraction itemTick = item->tick();
99 0 : Fraction selectionStartTick = startTick();
100 0 : Fraction selectionEndTick = endTick();
101 :
102 0 : if (itemTick < selectionStartTick || itemTick >= selectionEndTick) {
103 0 : return false;
104 : }
105 :
106 0 : if (item->isMeasure()) {
107 0 : if (staffIdx != muse::nidx) {
108 0 : return startStaffIndex() <= staffIdx && staffIdx < endStaffIndex();
109 : }
110 :
111 0 : return true;
112 : }
113 :
114 0 : track_idx_t itemTrack = item->track();
115 0 : track_idx_t selectionStartTrack = VOICES * startStaffIndex();
116 0 : track_idx_t selectionEndTrack = VOICES * (endStaffIndex() - 1) + VOICES;
117 :
118 0 : return itemTrack >= selectionStartTrack && itemTrack < selectionEndTrack;
119 : }
120 :
121 0 : bool NotationSelectionRange::containsMultiNoteChords() const
122 : {
123 0 : const mu::engraving::Selection& selection = score()->selection();
124 0 : return selection.rangeContainsMultiNoteChords();
125 : }
126 :
127 0 : std::vector<const Part*> NotationSelectionRange::selectedParts() const
128 : {
129 0 : std::vector<const Part*> result;
130 :
131 0 : if (!score()->selection().isRange()) {
132 0 : return result;
133 : }
134 :
135 0 : staff_idx_t startStaffIndex = this->startStaffIndex();
136 0 : staff_idx_t endStaffIndex = this->endStaffIndex();
137 :
138 0 : for (staff_idx_t i = startStaffIndex; i < endStaffIndex; ++i) {
139 0 : const Staff* staff = score()->staff(i);
140 :
141 0 : if (staff && staff->part()) {
142 0 : result.push_back(staff->part());
143 : }
144 : }
145 :
146 0 : return result;
147 0 : }
148 :
149 0 : mu::engraving::Score* NotationSelectionRange::score() const
150 : {
151 0 : return m_getScore->score();
152 : }
153 :
154 0 : mu::engraving::Segment* NotationSelectionRange::rangeStartSegment() const
155 : {
156 0 : mu::engraving::Segment* startSegment = score()->selection().startSegment();
157 :
158 0 : if (!startSegment) {
159 0 : return nullptr;
160 : }
161 :
162 0 : if (!startSegment->enabled()) {
163 0 : startSegment = startSegment->next1MMenabled();
164 : }
165 :
166 0 : if (!startSegment->measure()->system()) {
167 0 : const Measure* mmr = startSegment->measure()->coveringMMRestOrThis();
168 0 : if (!mmr || mmr->system()) {
169 0 : return nullptr;
170 : }
171 0 : startSegment = mmr->first(mu::engraving::SegmentType::ChordRest);
172 : }
173 :
174 0 : return startSegment;
175 : }
176 :
177 0 : mu::engraving::Box* NotationSelectionRange::rangeStartBox() const
178 : {
179 0 : return score()->selection().startBox();
180 : }
181 :
182 0 : mu::engraving::Segment* NotationSelectionRange::rangeEndSegment() const
183 : {
184 0 : mu::engraving::Segment* endSegment = score()->selection().endSegment();
185 :
186 0 : if (endSegment && !endSegment->enabled()) {
187 0 : endSegment = endSegment->next1MMenabled();
188 : }
189 :
190 0 : if (!endSegment) {
191 0 : endSegment = score()->lastSegmentMM();
192 : }
193 :
194 0 : return endSegment;
195 : }
196 :
197 0 : mu::engraving::Box* NotationSelectionRange::rangeEndBox() const
198 : {
199 0 : return score()->selection().endBox();
200 : }
|