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 "bsymbol.h"
24 :
25 : #include <cmath>
26 :
27 : #include "containers.h"
28 :
29 : #include "measure.h"
30 : #include "page.h"
31 : #include "score.h"
32 : #include "segment.h"
33 : #include "system.h"
34 :
35 : #include "log.h"
36 :
37 : using namespace mu;
38 : using namespace mu::engraving;
39 :
40 : namespace mu::engraving {
41 : //---------------------------------------------------------
42 : // BSymbol
43 : //---------------------------------------------------------
44 :
45 1415 : BSymbol::BSymbol(const ElementType& type, EngravingObject* parent, ElementFlags f)
46 1415 : : EngravingItem(type, parent, f)
47 : {
48 1415 : m_align = { AlignH::LEFT, AlignV::BASELINE };
49 1415 : }
50 :
51 438 : BSymbol::BSymbol(const BSymbol& s)
52 438 : : EngravingItem(s)
53 : {
54 438 : m_align = s.m_align;
55 439 : for (EngravingItem* e : s.m_leafs) {
56 1 : EngravingItem* ee = e->clone();
57 1 : ee->setOwnershipParent(this);
58 1 : m_leafs.push_back(ee);
59 : }
60 438 : }
61 :
62 : //---------------------------------------------------------
63 : // add
64 : //---------------------------------------------------------
65 :
66 7 : void BSymbol::add(EngravingItem* e)
67 : {
68 7 : if (e->isSymbol() || e->isImage()) {
69 7 : e->setOwnershipParent(this);
70 7 : e->setTrack(track());
71 7 : m_leafs.push_back(e);
72 7 : toBSymbol(e)->setZ(z() - 1); // draw on top of parent
73 7 : e->added();
74 : } else {
75 0 : LOGD("BSymbol::add: unsupported type %s", e->typeName());
76 : }
77 7 : }
78 :
79 : //---------------------------------------------------------
80 : // scanElements
81 : //---------------------------------------------------------
82 :
83 44 : void BSymbol::scanElements(std::function<void(EngravingItem*)> func)
84 : {
85 44 : func(this);
86 54 : for (EngravingItem* e : m_leafs) {
87 10 : e->scanElements(func);
88 : }
89 44 : }
90 :
91 : //---------------------------------------------------------
92 : // remove
93 : //---------------------------------------------------------
94 :
95 0 : void BSymbol::remove(EngravingItem* e)
96 : {
97 0 : if (e->isSymbol() || e->isImage()) {
98 0 : if (muse::remove(m_leafs, e)) {
99 0 : e->removed();
100 : } else {
101 0 : LOGD("BSymbol::remove: element <%s> not found", e->typeName());
102 : }
103 : } else {
104 0 : LOGD("BSymbol::remove: unsupported type %s", e->typeName());
105 : }
106 0 : }
107 :
108 : //---------------------------------------------------------
109 : // acceptDrop
110 : //---------------------------------------------------------
111 :
112 0 : bool BSymbol::acceptDrop(EditData& data) const
113 : {
114 0 : return data.dropElement->isSymbol() || data.dropElement->isImage();
115 : }
116 :
117 : //---------------------------------------------------------
118 : // drop
119 : //---------------------------------------------------------
120 :
121 0 : EngravingItem* BSymbol::drop(Transaction&, EditData& data)
122 : {
123 0 : EngravingItem* el = data.dropElement;
124 0 : if (el->isSymbol() || el->isImage()) {
125 0 : el->setOwnershipParent(this);
126 0 : PointF p = data.pos - pageBoundingRect().topLeft() - data.dragOffset;
127 0 : if (p == PointF()) {
128 : // offset position so newly added child is visible
129 0 : p = PointF(width(), height());
130 : }
131 0 : el->setOffset(p);
132 0 : score()->undoAddElement(el);
133 0 : return el;
134 : } else {
135 0 : delete el;
136 : }
137 0 : return 0;
138 : }
139 :
140 : //---------------------------------------------------------
141 : // drag
142 : //---------------------------------------------------------
143 :
144 0 : RectF BSymbol::drag(EditData& ed)
145 : {
146 0 : RectF r(canvasBoundingRect());
147 0 : for (const EngravingItem* e : m_leafs) {
148 0 : r.unite(e->canvasBoundingRect());
149 : }
150 :
151 0 : double x = ed.delta.x();
152 0 : double y = ed.delta.y();
153 :
154 0 : double _spatium = spatium();
155 0 : if (ed.hRaster) {
156 0 : double hRaster = _spatium / MScore::hRaster();
157 0 : int n = lrint(x / hRaster);
158 0 : x = hRaster * n;
159 : }
160 0 : if (ed.vRaster) {
161 0 : double vRaster = _spatium / MScore::vRaster();
162 0 : int n = lrint(y / vRaster);
163 0 : y = vRaster * n;
164 : }
165 :
166 0 : setOffset(PointF(x, y));
167 :
168 0 : r.unite(canvasBoundingRect());
169 0 : for (const EngravingItem* e : m_leafs) {
170 0 : r.unite(e->canvasBoundingRect());
171 : }
172 0 : return r;
173 : }
174 :
175 : //---------------------------------------------------------
176 : // dragAnchorLines
177 : //---------------------------------------------------------
178 :
179 0 : std::vector<LineF> BSymbol::dragAnchorLines() const
180 : {
181 0 : return genericDragAnchorLines();
182 : }
183 :
184 : //---------------------------------------------------------
185 : // pagePos
186 : //---------------------------------------------------------
187 :
188 6 : PointF BSymbol::pagePos() const
189 : {
190 6 : if (ownershipParent() && (ownershipParent()->isSegment())) {
191 0 : PointF p(pos());
192 0 : System* system = segment()->measure()->system();
193 0 : if (system) {
194 0 : p.ry() += system->staff(staffIdx())->y() + system->y();
195 : }
196 0 : p.rx() = pageX();
197 0 : return p;
198 : } else {
199 6 : return EngravingItem::pagePos();
200 : }
201 : }
202 :
203 : //---------------------------------------------------------
204 : // canvasPos
205 : //---------------------------------------------------------
206 :
207 1040 : PointF BSymbol::canvasPos() const
208 : {
209 1040 : if (ownershipParent() && (ownershipParent()->isSegment())) {
210 0 : PointF p(pos());
211 0 : Segment* s = toSegment(ownershipParent());
212 :
213 0 : System* system = s->measure()->system();
214 0 : if (system) {
215 0 : staff_idx_t si = staffIdx();
216 0 : p.ry() += system->staff(si)->y() + system->y();
217 0 : Page* page = system->page();
218 0 : if (page) {
219 0 : p.ry() += page->y();
220 : }
221 : }
222 0 : p.rx() = canvasX();
223 0 : return p;
224 : } else {
225 1040 : return EngravingItem::canvasPos();
226 : }
227 : }
228 : }
|