~s-cecilio/lenmus/v5.3

206 by cecilios
1
//--------------------------------------------------------------------------------------
2
//    LenMus Phonascus: The teacher of music
3
//    Copyright (c) 2002-2007 Cecilio Salmeron
4
//
5
//    This program is free software; you can redistribute it and/or modify it under the 
6
//    terms of the GNU General Public License as published by the Free Software Foundation;
7
//    either version 2 of the License, or (at your option) any later version.
8
//
9
//    This program is distributed in the hope that it will be useful, but WITHOUT ANY 
10
//    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
11
//    PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
//
13
//    You should have received a copy of the GNU General Public License along with this 
14
//    program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, 
15
//    Fifth Floor, Boston, MA  02110-1301, USA.
16
//
17
//    For any comment, suggestion or feature request, please contact the manager of 
18
//    the project at cecilios@users.sourceforge.net
19
//
20
//-------------------------------------------------------------------------------------
21
22
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
23
#pragma implementation "MetronomeMark.h"
24
#endif
25
26
// For compilers that support precompilation, includes "wx.h".
27
#include "wx/wxprec.h"
28
29
#ifdef __BORLANDC__
30
#pragma hdrstop
31
#endif
32
33
#include "Score.h"
34
#include "MetronomeMark.h"
35
#include "../graphic/Shape.h"
36
37
// 'note_symbol = 80'
38
lmMetronomeMark::lmMetronomeMark(lmVStaff* pVStaff, ENoteType nNoteType, int nDots,
39
                    int nTicksPerMinute, bool fParentheses, bool fVisible)
40
    : lmStaffObj(pVStaff, eSFOT_MetronomeMark, pVStaff, 1, fVisible, lmDRAGGABLE)
41
{
42
    m_nMarkType = eMMT_Note_Value;
43
    m_nLeftNoteType = nNoteType;
44
    m_nLeftDots = nDots;
45
    m_nTicksPerMinute = nTicksPerMinute;
46
    m_fParentheses = fParentheses;
47
    wxString sText = wxString::Format(_T(" = %d"), m_nTicksPerMinute);
48
    m_pTextShape = new lmShapeText(this, sText, (wxFont*)NULL);
49
50
    m_pRightNoteShape = (lmShapeGlyph*)NULL;
51
    m_pLeftNoteShape = new lmShapeGlyph(this, SelectGlyph(nNoteType, nDots), m_pFont);
52
53
}
54
55
// 'm.m. = 80'
56
lmMetronomeMark::lmMetronomeMark(lmVStaff* pVStaff, int nTicksPerMinute,
57
                    bool fParentheses, bool fVisible)
58
    : lmStaffObj(pVStaff, eSFOT_MetronomeMark, pVStaff, 1, fVisible, lmDRAGGABLE)
59
{
60
    m_nMarkType = eMMT_MM_Value;
61
    m_nTicksPerMinute = nTicksPerMinute;
62
    m_fParentheses = fParentheses;
63
    wxString sText = wxString::Format(_T("m.m. = %d"), m_nTicksPerMinute);
64
    m_pTextShape = new lmShapeText(this, sText, (wxFont*)NULL);
65
66
    m_pLeftNoteShape = (lmShapeGlyph*)NULL;
67
    m_pRightNoteShape = (lmShapeGlyph*)NULL;
68
}
69
70
// 'note_symbol = note_symbol'
71
lmMetronomeMark::lmMetronomeMark(lmVStaff* pVStaff,          
72
                    ENoteType nLeftNoteType, int nLeftDots,
73
                    ENoteType nRightNoteType, int nRightDots,
74
                    bool fParentheses, bool fVisible)
75
    : lmStaffObj(pVStaff, eSFOT_MetronomeMark, pVStaff, 1, fVisible, lmDRAGGABLE)
76
{
77
    m_nMarkType = eMMT_Note_Note;
78
    m_nLeftNoteType = nLeftNoteType;
79
    m_nLeftDots = nLeftDots;
80
    m_nRightNoteType = nRightNoteType;
81
    m_nRightDots = nRightDots;
82
    m_nTicksPerMinute = 0;
83
    m_fParentheses = fParentheses;
84
    m_pTextShape = new lmShapeText(this, _T(" =  "), (wxFont*)NULL);
85
86
    m_pLeftNoteShape = new lmShapeGlyph(this, SelectGlyph(nLeftNoteType, nLeftDots), m_pFont);
87
    m_pRightNoteShape = new lmShapeGlyph(this, SelectGlyph(nRightNoteType, nRightDots), m_pFont);
88
}
89
90
lmMetronomeMark::~lmMetronomeMark()
91
{
92
    if (m_pLeftNoteShape) delete m_pLeftNoteShape;
93
    if (m_pRightNoteShape) delete m_pRightNoteShape;
94
}
95
96
97
//-----------------------------------------------------------------------------------------
98
// implementation of virtual methods defined in base abstract class lmStaffObj
99
//-----------------------------------------------------------------------------------------
100
101
wxBitmap* lmMetronomeMark::GetBitmap(double rScale)
102
{
103
    //todo
104
    return (wxBitmap*)NULL; //PrepareBitMap(rScale, m_sText);
105
}
106
107
void lmMetronomeMark::DrawObject(bool fMeasuring, lmPaper* pPaper, wxColour colorC,
108
                                  bool fHighlight)
109
{
110
    lmLUnits yPos = pPaper->GetCursorY() - m_pVStaff->TenthsToLogical(50, m_nStaffNum);
111
    lmLUnits xPos = pPaper->GetCursorX();
112
    lmLUnits uWidth = DrawMetronomeMark(fMeasuring, pPaper, xPos, yPos, colorC);
113
114
    if (fMeasuring) {
115
        // store selection rectangle measures and position
116
        m_selRect.width = uWidth;
117
        m_selRect.height = m_pVStaff->TenthsToLogical(32, m_nStaffNum); //todo
118
        m_selRect.x = xPos - m_paperPos.x;        //relative to m_paperPos
119
        m_selRect.y = yPos - m_paperPos.y;;
120
121
        // set total width to zero: metronome marks does not consume staff space
122
        m_nWidth = 0;   // uWidth;
123
124
        // store glyph position (relative to paper pos). 
125
        m_glyphPos.x = 0;
126
        m_glyphPos.y = pPaper->GetCursorY() - yPos;
127
    }
128
129
}
130
131
// returns the width of the metronome mark (in logical units)
132
lmLUnits lmMetronomeMark::DrawMetronomeMark(bool fMeasuring, lmPaper* pPaper,
133
                                lmLUnits xPos, lmLUnits yPos, wxColour colorC)
134
{
135
    lmLUnits xStart = xPos;
136
    switch(m_nMarkType)
137
    {
138
        case eMMT_MM_Value:         // 'm.m. = 80'
139
            return DrawText(fMeasuring, pPaper, xPos, yPos, colorC);
140
            break;
141
            
142
        case eMMT_Note_Note:        // 'note_symbol = note_symbol'
143
            xPos += DrawSymbol(fMeasuring, pPaper, m_pLeftNoteShape, xPos, yPos, colorC);
144
            xPos += DrawText(fMeasuring, pPaper, xPos, yPos, colorC);
145
            xPos += DrawSymbol(fMeasuring, pPaper, m_pRightNoteShape, xPos, yPos, colorC);
146
            return xPos - xStart;
147
            break;
148
149
        case eMMT_Note_Value:       // 'note_symbol = 80'
150
            xPos += DrawSymbol(fMeasuring, pPaper, m_pLeftNoteShape, xPos, yPos, colorC);
151
            xPos += DrawText(fMeasuring, pPaper, xPos, yPos, colorC);
152
            return xPos - xStart;
153
            break;
154
 
155
        default:
156
            wxASSERT(false);
157
            return 0;            // to keep compiler happy
158
            
159
    }
160
}
161
162
lmLUnits lmMetronomeMark::DrawText(bool fMeasuring, lmPaper* pPaper,
163
                               lmLUnits xPos, lmLUnits yPos, wxColour colorC)
164
{
165
    // returns the width of the text (in logical units)
166
167
    if (fMeasuring) {
168
        int nWeight = wxNORMAL;
169
        int nStyle = wxNORMAL;
170
        int nFontSize = PointsToLUnits(8);
171
        wxFont* pFont = pPaper->GetFont(nFontSize, _T("Times New Roman"), wxDEFAULT, nStyle, nWeight, false);
172
        if (!pFont) {
173
            wxMessageBox(_("Sorry, an error has occurred while allocating the font."),
174
                _T("lmScoreText::SetFont"), wxOK);
175
            ::wxExit();
176
        }
177
        m_pTextShape->SetFont(pFont);
178
        lmUPoint offset(xPos - m_paperPos.x,
179
                        yPos - m_paperPos.y + m_pVStaff->TenthsToLogical(10, m_nStaffNum));
180
        m_pTextShape->Measure(pPaper, m_pVStaff->GetStaff(m_nStaffNum), offset);
181
    }
182
    else {
183
        m_pTextShape->Render(pPaper, m_paperPos, colorC);
184
    }
185
    return m_pTextShape->GetWidth();
186
187
}
188
189
lmLUnits lmMetronomeMark::DrawSymbol(bool fMeasuring, lmPaper* pPaper, lmShapeGlyph* pShape,
190
                                     lmLUnits xPos, lmLUnits yPos, wxColour colorC)
191
{
192
    // returns the width of the note (in logical units)
193
194
    wxASSERT(pShape);
195
    if (fMeasuring) {
196
        lmUPoint offset(xPos - m_paperPos.x, yPos - m_paperPos.y - m_pVStaff->TenthsToLogical(35, m_nStaffNum));
197
        pShape->SetFont(m_pFont);
198
        pShape->Measure(pPaper, m_pVStaff->GetStaff(m_nStaffNum), offset);
199
    }
200
    else {
201
        pShape->Render(pPaper, m_paperPos, colorC);
202
    }
203
    return pShape->GetWidth();
204
}
205
206
lmEGlyphIndex lmMetronomeMark::SelectGlyph(ENoteType nNoteType, int nDots)
207
{
208
    lmEGlyphIndex nGlyph = GLYPH_SMALL_QUARTER_NOTE;
209
    switch (nNoteType) {
210
        case eQuarter:
211
            if (nDots == 0)
212
                nGlyph = GLYPH_SMALL_QUARTER_NOTE;
213
            else
214
                nGlyph = GLYPH_SMALL_QUARTER_NOTE_DOTTED;
215
            break;
216
        case eEighth:
217
            if (nDots == 0)
218
                nGlyph = GLYPH_SMALL_EIGHTH_NOTE;
219
            else
220
                nGlyph = GLYPH_SMALL_EIGHTH_NOTE_DOTTED;
221
            break;
222
        default:
223
            wxASSERT(false);
224
    }
225
    return nGlyph;
226
227
}
228
229
wxString lmMetronomeMark::Dump()
230
{
231
    wxString sDump = wxString::Format(
232
        _T("%d\tMetronome %d\tTicksPerMinute=%d, fParentheses=%s,")
233
        _T(" TimePos=%.2f, fixed=%s\n"),
234
        m_nId, m_nMarkType, m_nTicksPerMinute, (m_fParentheses ? _T("yes") : _T("no")),
235
        m_rTimePos, (m_fFixedPos ? _T("yes") : _T("no")) );
236
    return sDump;
237
}
238
239
wxString lmMetronomeMark::SourceLDP()
240
{
241
    wxString sSource = _T("         (metronome");
242
243
    switch (m_nMarkType)
244
    {
245
        case eMMT_MM_Value:
246
            sSource += wxString::Format(_T(" %d"), m_nTicksPerMinute);
247
            break;
248
        case eMMT_Note_Note:
249
            sSource += GetLDPNote(m_nLeftNoteType, m_nLeftDots);
250
            sSource += GetLDPNote(m_nRightNoteType, m_nRightDots);
251
            break;
252
        case eMMT_Note_Value:
253
            sSource += GetLDPNote(m_nLeftNoteType, m_nLeftDots);
254
            sSource += wxString::Format(_T(" %d"), m_nTicksPerMinute);
255
            break;
256
        default:
257
            wxASSERT(false);
258
    }
259
260
    if (m_fParentheses) sSource += _T(" parentheses");
261
    if (!m_fVisible) sSource += _T(" noVisible");
262
    sSource += _T(")\n");
263
    return sSource;
264
}
265
266
wxString lmMetronomeMark::SourceXML()
267
{
268
    //! @todo all
269
    wxString sSource = _T("TODO: lmMetronomeMark XML Source code generation methods");
270
    return sSource;
271
}
272
273
wxString lmMetronomeMark::GetLDPNote(ENoteType nNoteType, int nDots)
274
{
275
    // returns LDP data (English) starting with an space
276
277
    wxString sNote = _T(" ");
278
    switch (nNoteType)
279
    {
280
        case eWhole:
281
            sNote += _T("w");
282
            break;
283
        case eHalf:
284
            sNote += _T("h");
285
            break;
286
        case eQuarter:
287
            sNote += _T("q");
288
            break;
289
        case eEighth:
290
            sNote += _T("e");
291
            break;
292
        case e16th:
293
            sNote += _T("s");
294
            break;
295
        case e32th:
296
            sNote += _T("t");
297
            break;
298
        case e64th:
299
            sNote += _T("i");
300
            break;
301
        case e128th:
302
            sNote += _T("o");
303
            break;
304
        case e256th:
305
            sNote += _T("f");
306
            break;
307
    }
308
309
    for(int i=0; i < nDots; i++) sNote += _T(".");
310
311
    return sNote;
312
}