1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2013 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #include "marker.h"
14 #include "score.h"
15 #include "sym.h"
16 #include "xml.h"
17 #include "measure.h"
18 
19 namespace Ms {
20 
21 //---------------------------------------------------------
22 //   markerStyle
23 //---------------------------------------------------------
24 
25 static const ElementStyle markerStyle {
26       { Sid::repeatLeftPlacement, Pid::PLACEMENT },
27       { Sid::repeatMinDistance,   Pid::MIN_DISTANCE },
28       };
29 
30 //must be in sync with Marker::Type enum
31 const MarkerTypeItem markerTypeTable[] = {
32       { Marker::Type::SEGNO    , QT_TRANSLATE_NOOP("markerType", "Segno")           },
33       { Marker::Type::VARSEGNO , QT_TRANSLATE_NOOP("markerType", "Segno variation") },
34       { Marker::Type::CODA     , QT_TRANSLATE_NOOP("markerType", "Coda")            },
35       { Marker::Type::VARCODA  , QT_TRANSLATE_NOOP("markerType", "Varied coda")     },
36       { Marker::Type::CODETTA  , QT_TRANSLATE_NOOP("markerType", "Codetta")         },
37       { Marker::Type::FINE     , QT_TRANSLATE_NOOP("markerType", "Fine")            },
38       { Marker::Type::TOCODA   , QT_TRANSLATE_NOOP("markerType", "To Coda")         },
39       { Marker::Type::TOCODASYM, QT_TRANSLATE_NOOP("markerType", "To Coda (Symbol)")},
40       { Marker::Type::USER     , QT_TRANSLATE_NOOP("markerType", "Custom")          }
41       };
42 
markerTypeTableSize()43 int markerTypeTableSize()
44       {
45       return sizeof(markerTypeTable)/sizeof(MarkerTypeItem) - 1; //-1 for the user defined
46       }
47 
48 //---------------------------------------------------------
49 //   Marker
50 //---------------------------------------------------------
51 
Marker(Score * s)52 Marker::Marker(Score* s)
53    : Marker(s, Tid::REPEAT_LEFT)
54       {
55       }
56 
Marker(Score * s,Tid tid)57 Marker::Marker(Score* s, Tid tid)
58    : TextBase(s, tid, ElementFlag::MOVABLE | ElementFlag::ON_STAFF | ElementFlag::SYSTEM)
59       {
60       initElementStyle(&markerStyle);
61       _markerType = Type::FINE;
62       setLayoutToParentWidth(true);
63       }
64 
65 //---------------------------------------------------------
66 //   setMarkerType
67 //---------------------------------------------------------
68 
setMarkerType(Type t)69 void Marker::setMarkerType(Type t)
70       {
71       _markerType = t;
72       const char* txt = 0;
73       switch (t) {
74             case Type::SEGNO:
75                   txt = "<sym>segno</sym>";
76                   setLabel("segno");
77                   break;
78 
79             case Type::VARSEGNO:
80                   txt = "<sym>segnoSerpent1</sym>";
81                   setLabel("varsegno");
82                   break;
83 
84             case Type::CODA:
85                   txt = "<sym>coda</sym>";
86                   setLabel("codab");
87                   break;
88 
89             case Type::VARCODA:
90                   txt = "<sym>codaSquare</sym>";
91                   setLabel("varcoda");
92                   break;
93 
94             case Type::CODETTA:
95                   txt = "<sym>coda</sym><sym>coda</sym>";
96                   setLabel("codetta");
97                   break;
98 
99             case Type::FINE:
100                   txt = "Fine";
101                   initTid(Tid::REPEAT_RIGHT, true);
102                   setLabel("fine");
103                   break;
104 
105             case Type::TOCODA:
106                   txt = "To Coda";
107                   initTid(Tid::REPEAT_RIGHT, true);
108                   setLabel("coda");
109                   break;
110 
111             case Type::TOCODASYM:
112                   txt = "To <font size=\"20\"/><sym>coda</sym>";
113                   initTid(Tid::REPEAT_RIGHT, true);
114                   setLabel("coda");
115                   break;
116 
117             case Type::USER:
118                   break;
119 
120             default:
121                   qDebug("unknown marker type %d", int(t));
122                   break;
123             }
124       if (empty() && txt)
125             setXmlText(txt);
126       }
127 
128 //---------------------------------------------------------
129 //   markerTypeUserName
130 //---------------------------------------------------------
131 
markerTypeUserName() const132 QString Marker::markerTypeUserName() const
133       {
134       return qApp->translate("markerType", markerTypeTable[static_cast<int>(_markerType)].name.toUtf8().constData());
135       }
136 
137 //---------------------------------------------------------
138 //   styleChanged
139 //---------------------------------------------------------
140 
styleChanged()141 void Marker::styleChanged()
142       {
143       setMarkerType(_markerType);
144       TextBase::styleChanged();
145       }
146 
147 //---------------------------------------------------------
148 //   markerType
149 //---------------------------------------------------------
150 
markerType(const QString & s) const151 Marker::Type Marker::markerType(const QString& s) const
152       {
153       if (s == "segno")
154             return Type::SEGNO;
155       else if (s == "varsegno")
156             return Type::VARSEGNO;
157       else if (s == "codab")
158             return Type::CODA;
159       else if (s == "varcoda")
160             return Type::VARCODA;
161       else if (s == "codetta")
162             return Type::CODETTA;
163       else if (s == "fine")
164             return Type::FINE;
165       else if (s == "coda")
166             return Type::TOCODA;
167       else
168             return Type::USER;
169       }
170 
171 //---------------------------------------------------------
172 //   layout
173 //---------------------------------------------------------
174 
layout()175 void Marker::layout()
176       {
177       TextBase::layout();
178 
179       // although normally laid out to parent (measure) width,
180       // force to center over barline if left-aligned
181 
182       if (layoutToParentWidth() && !(align() & (Align::RIGHT | Align::HCENTER)))
183             rxpos() -= width() * 0.5;
184 
185       autoplaceMeasureElement();
186       }
187 
188 //---------------------------------------------------------
189 //   read
190 //---------------------------------------------------------
191 
read(XmlReader & e)192 void Marker::read(XmlReader& e)
193       {
194       Type mt = Type::SEGNO;
195 
196       while (e.readNextStartElement()) {
197             const QStringRef& tag(e.name());
198             if (tag == "label") {
199                   QString s(e.readElementText());
200                   setLabel(s);
201                   mt = markerType(s);
202                   }
203             else if (!TextBase::readProperties(e))
204                   e.unknown();
205             }
206       setMarkerType(mt);
207       }
208 
209 //---------------------------------------------------------
210 //   write
211 //---------------------------------------------------------
212 
write(XmlWriter & xml) const213 void Marker::write(XmlWriter& xml) const
214       {
215       xml.stag(this);
216       TextBase::writeProperties(xml);
217       xml.tag("label", _label);
218       xml.etag();
219       }
220 
221 //---------------------------------------------------------
222 //   undoSetLabel
223 //---------------------------------------------------------
224 
undoSetLabel(const QString & s)225 void Marker::undoSetLabel(const QString& s)
226       {
227       undoChangeProperty(Pid::LABEL, s);
228       }
229 
230 //---------------------------------------------------------
231 //   undoSetMarkerType
232 //---------------------------------------------------------
233 
undoSetMarkerType(Type t)234 void Marker::undoSetMarkerType(Type t)
235       {
236       undoChangeProperty(Pid::MARKER_TYPE, int(t));
237       }
238 
239 //---------------------------------------------------------
240 //   getProperty
241 //---------------------------------------------------------
242 
getProperty(Pid propertyId) const243 QVariant Marker::getProperty(Pid propertyId) const
244       {
245       switch (propertyId) {
246             case Pid::LABEL:
247                   return label();
248             case Pid::MARKER_TYPE:
249                   return int(markerType());
250             default:
251                   break;
252             }
253       return TextBase::getProperty(propertyId);
254       }
255 
256 //---------------------------------------------------------
257 //   setProperty
258 //---------------------------------------------------------
259 
setProperty(Pid propertyId,const QVariant & v)260 bool Marker::setProperty(Pid propertyId, const QVariant& v)
261       {
262       switch (propertyId) {
263             case Pid::LABEL:
264                   setLabel(v.toString());
265                   break;
266             case Pid::MARKER_TYPE:
267                   setMarkerType(Type(v.toInt()));
268                   break;
269             default:
270                   if (!TextBase::setProperty(propertyId, v))
271                         return false;
272                   break;
273             }
274       triggerLayoutAll();
275       return true;
276       }
277 
278 //---------------------------------------------------------
279 //   propertyDefault
280 //---------------------------------------------------------
281 
propertyDefault(Pid propertyId) const282 QVariant Marker::propertyDefault(Pid propertyId) const
283       {
284       switch (propertyId) {
285             case Pid::LABEL:
286                   return QString();
287             case Pid::MARKER_TYPE:
288                   return int(Type::FINE);
289             case Pid::PLACEMENT:
290                   return int(Placement::ABOVE);
291             default:
292                   break;
293             }
294       return TextBase::propertyDefault(propertyId);
295       }
296 
297 
298 //---------------------------------------------------------
299 //   nextSegmentElement
300 //---------------------------------------------------------
301 
nextSegmentElement()302 Element* Marker::nextSegmentElement()
303       {
304       Segment* seg;
305       if (markerType() == Marker::Type::FINE) {
306             seg = measure()->last();
307             return seg->firstElement(staffIdx());
308             }
309       Measure* prevMeasure = measure()->prevMeasureMM();
310       if (prevMeasure) {
311             seg = prevMeasure->last();
312             return seg->firstElement(staffIdx());
313             }
314       return Element::nextSegmentElement();
315       }
316 
317 //---------------------------------------------------------
318 //   prevSegmentElement
319 //---------------------------------------------------------
320 
prevSegmentElement()321 Element* Marker::prevSegmentElement()
322       {
323       //it's the same barline
324       return nextSegmentElement();
325       }
326 
327 //---------------------------------------------------------
328 //   accessibleInfo
329 //---------------------------------------------------------
330 
accessibleInfo() const331 QString Marker::accessibleInfo() const
332       {
333       return QString("%1: %2").arg(Element::accessibleInfo(), markerTypeUserName());
334       }
335 
336 }
337 
338