1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2010-2011 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 #ifndef __FRET_H__
14 #define __FRET_H__
15 
16 #include "element.h"
17 #include "harmony.h"
18 
19 namespace Ms {
20 
21 class StringData;
22 class Chord;
23 
24 enum class Orientation : signed char {
25       VERTICAL,
26       HORIZONTAL
27       };
28 
29 // Keep this in order - not used directly for comparisons, but the dots will appear in
30 // this order in fret multidot mode. See fretproperties.cpp.
31 enum class FretDotType : signed char {
32       NORMAL = 0,
33       CROSS,
34       SQUARE,
35       TRIANGLE = 3
36       };
37 
38 
39 enum class FretMarkerType : signed char {
40       NONE,
41       CIRCLE,
42       CROSS
43       };
44 
45 
46 class FretItem {
47    public:
48       struct Barre {
49             int startString;
50             int endString;
51 
BarreBarre52             Barre() { startString = endString = -1; }
BarreBarre53             Barre(int s, int e) : startString(s), endString(e) {}
existsBarre54             bool exists() const { return startString > -1; }
55             };
56 
57       struct Dot {
58             int fret                { 0 };
59             FretDotType dtype       { FretDotType::NORMAL };
60             int fingering           { 0 }; // NOTE:JT - possible future feature?
61 
DotDot62             Dot() {}
fretDot63             Dot(int f, FretDotType t = FretDotType::NORMAL) : fret(f), dtype(t) {}
existsDot64             bool exists() const { return fret > 0; }
65             };
66 
67       struct Marker {
68             FretMarkerType mtype;
69 
MarkerMarker70             Marker() { mtype = FretMarkerType::NONE; }
MarkerMarker71             Marker(FretMarkerType t) : mtype(t) {}
existsMarker72             bool exists() const { return mtype != FretMarkerType::NONE; }
73             };
74 
75       struct MarkerTypeNameItem {
76             FretMarkerType mtype;
77             const char* name;
78             };
79 
80       struct DotTypeNameItem {
81             FretDotType dtype;
82             const char* name;
83             };
84 
85       static const std::vector<FretItem::MarkerTypeNameItem> markerTypeNameMap;
86       static const std::vector<FretItem::DotTypeNameItem> dotTypeNameMap;
87 
88       static QChar markerToChar(FretMarkerType t);
89       static QString markerTypeToName(FretMarkerType t);
90       static FretMarkerType nameToMarkerType(QString n);
91       static QString dotTypeToName(FretDotType t);
92       static FretDotType nameToDotType(QString n);
93       };
94 
95 
96 // The three main storage containers used by fret diagrams
97 typedef std::map<int, FretItem::Barre> BarreMap;
98 typedef std::map<int, FretItem::Marker> MarkerMap;
99 typedef std::map<int, std::vector<FretItem::Dot>> DotMap;
100 
101 
102 class FretUndoData {
103       FretDiagram* _diagram         { nullptr };
104       BarreMap _barres;
105       MarkerMap _markers;
106       DotMap _dots;
107 
108    public:
FretUndoData()109       FretUndoData() {}
110       FretUndoData(FretDiagram* fd);
111 
112       void updateDiagram();
113       };
114 
115 //---------------------------------------------------------
116 //   @@ FretDiagram
117 ///    Fretboard diagram
118 //
119 //   @P userMag    qreal
120 //   @P strings    int  number of strings
121 //   @P frets      int  number of frets
122 //   @P fretOffset int
123 //
124 //   Note that, while strings are zero-indexed, frets are one-indexed
125 //---------------------------------------------------------
126 
127 class FretDiagram final : public Element {
128       int _strings       { 6  };
129       int _frets         { 4  };
130       int _fretOffset    { 0  };
131       int _maxFrets      { 24 };
132       bool _showNut      { true };
133       Orientation _orientation      { Orientation::VERTICAL };
134 
135       // Barres are stored in the format: K: fret, V: barre struct
136       BarreMap _barres;
137 
138       // Dots stored as K: string, V: dot struct
139       DotMap _dots;
140 
141       // Markers stored as K: string, V: marker struct
142       MarkerMap _markers;
143 
144       Harmony* _harmony  { nullptr };
145 
146       qreal stringLw;
147       qreal nutLw;
148       qreal stringDist;
149       qreal fretDist;
150       QFont font;
151       qreal _userMag     { 1.0   };             // allowed 0.1 - 10.0
152       qreal markerSize;
153       int _numPos;
154 
155       void removeDot(int s, int f = 0);
156       void removeBarre(int f);
157       void removeBarres(int string, int fret = 0);
158       void removeMarker(int s);
159       void removeDotsMarkers(int ss, int es, int fret);
160 
161    public:
162       FretDiagram(Score* s);
163       FretDiagram(const FretDiagram&);
164       ~FretDiagram();
165 
166       void draw(QPainter*) const override;
167       Element* linkedClone() override;
clone()168       FretDiagram* clone() const override { return new FretDiagram(*this); }
169 
segment()170       Segment* segment() { return toSegment(parent()); }
171 
172       static FretDiagram* fromString(Score* score, const QString &s);
173 
type()174       ElementType type() const override { return ElementType::FRET_DIAGRAM; }
175       void layout() override;
176       void write(XmlWriter& xml) const override;
177       void writeNew(XmlWriter& xml) const;
178       void writeOld(XmlWriter& xml) const;
179       void read(XmlReader&) override;
180       void readNew(XmlReader&);
181       QVector<QLineF> dragAnchorLines() const override;
182       QPointF pagePos() const override;
183 
184       // read / write MusicXML
185       void readMusicXML(XmlReader& de);
186       void writeMusicXML(XmlWriter& xml) const;
187 
strings()188       int  strings() const    { return _strings; }
frets()189       int  frets()   const    { return _frets; }
190       void setStrings(int n);
setFrets(int n)191       void setFrets(int n)        { _frets = n; }
192 
193       void setDot(int string, int fret, bool add = false, FretDotType dtype = FretDotType::NORMAL);
194       void setBarre(int startString, int endString, int fret);
195       void setBarre(int string, int fret, bool add = false);
196       void setMarker(int string, FretMarkerType marker);
197       /*void setFingering(int string, int finger);*/
198       void clear();
199       void undoSetFretDot(int _string, int _fret, bool _add = false, FretDotType _dtype = FretDotType::NORMAL);
200       void undoSetFretMarker(int _string, FretMarkerType _mtype);
201       void undoSetFretBarre(int _string, int _fret, bool _add = false);
202       void undoFretClear();
fretOffset()203       int  fretOffset() const     { return _fretOffset; }
setFretOffset(int val)204       void setFretOffset(int val) { _fretOffset = val;  }
maxFrets()205       int  maxFrets() const       { return _maxFrets;   }
setMaxFrets(int val)206       void setMaxFrets(int val)   { _maxFrets = val;    }
showNut()207       bool showNut() const        { return _showNut;    }
setShowNut(bool val)208       void setShowNut(bool val)   { _showNut = val;     }
209 
harmonyText()210       QString harmonyText() const { return _harmony ? _harmony->plainText() : QString(); }
211       qreal centerX() const;
212       void setHarmony(QString harmonyText);
213 
214       std::vector<FretItem::Dot> dot(int s, int f = 0) const;
215       FretItem::Marker marker(int s) const;
216       FretItem::Barre barre(int fret) const;
217 #if 0 // NOTE:JT possible future feature
218       int fingering(int s) const       { return _fingering ? _fingering[s] : 0; }
219 #endif
220 
barres()221       BarreMap barres() const             { return _barres; }
dots()222       DotMap dots() const                 { return _dots; }
markers()223       MarkerMap markers() const           { return _markers; }
224 
harmony()225       Harmony* harmony() const { return _harmony; }
226 
227       void init(Ms::StringData*, Chord*);
228 
229       void add(Element*) override;
230       void remove(Element*) override;
231 
232       bool acceptDrop(EditData&) const override;
233       Element* drop(EditData&) override;
234 
235       void endEditDrag(EditData& editData) override;
236       void scanElements(void* data, void (*func)(void*, Element*), bool all=true) override;
237 
238       QVariant getProperty(Pid propertyId) const override;
239       bool setProperty(Pid propertyId, const QVariant&) override;
propertyDefault(Pid)240       QVariant propertyDefault(Pid) const override;
241 
242       qreal userMag() const         { return _userMag;   }
setUserMag(qreal m)243       void setUserMag(qreal m)      { _userMag = m;      }
244 
245       virtual QString accessibleInfo() const override;
246       virtual QString screenReaderInfo() const override;
247 
248       friend class FretUndoData;
249       };
250 
251 
252 }     // namespace Ms
253 #endif
254