~s-cecilio/lenmus/v5.1.x

« back to all changes in this revision

Viewing changes to src/html/TheoSideReadingCtrolParms.h

  • Committer: cecilios
  • Date: 2006-03-05 11:33:10 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:trunk:2
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// RCS-ID: $Id: TheoSideReadingCtrolParms.h,v 1.14 2006/03/03 15:01:11 cecilios Exp $
 
2
//--------------------------------------------------------------------------------------
 
3
//    LenMus Phonascus: The teacher of music
 
4
//    Copyright (c) 2002-2006 Cecilio Salmeron
 
5
//
 
6
//    This program is free software; you can redistribute it and/or modify it under the 
 
7
//    terms of the GNU General Public License as published by the Free Software Foundation;
 
8
//    either version 2 of the License, or (at your option) any later version.
 
9
//
 
10
//    This program is distributed in the hope that it will be useful, but WITHOUT ANY 
 
11
//    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 
12
//    PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 
13
//
 
14
//    You should have received a copy of the GNU General Public License along with this 
 
15
//    program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, 
 
16
//    Fifth Floor, Boston, MA  02110-1301, USA.
 
17
//
 
18
//    For any comment, suggestion or feature request, please contact the manager of 
 
19
//    the project at cecilios@users.sourceforge.net
 
20
//
 
21
//-------------------------------------------------------------------------------------
 
22
/*! @file TheoSideReadingCtrolParms.h
 
23
    @brief Header file for class lmTheoSideReadingCtrolParms
 
24
    @ingroup html_controls
 
25
*/
 
26
#ifdef __GNUG__
 
27
// #pragma interface
 
28
#endif
 
29
 
 
30
#ifndef __THEOSIDEREADINGCTROLPARMS_H__        //to avoid nested includes
 
31
#define __THEOSIDEREADINGCTROLPARMS_H__
 
32
 
 
33
// For compilers that support precompilation, includes "wx/wx.h".
 
34
#include "wx/wxprec.h"
 
35
 
 
36
#ifdef __BORLANDC__
 
37
#pragma hdrstop
 
38
#endif
 
39
 
 
40
#ifndef WX_PRECOMP
 
41
#include "wx/wx.h"
 
42
#endif
 
43
 
 
44
#include "ObjectParams.h"
 
45
#include "../exercises/ScoreConstrains.h"
 
46
#include "../ldp_parser/AuxString.h"
 
47
 
 
48
//! enum assigning name to the score generation settings source.
 
49
/*
 
50
    Four different ways for choosing the settings:
 
51
 
 
52
    1. By level and lesson: Useful for what? It was necessary with old non-html 
 
53
        organization. Now for each lesson there will be an html page and the
 
54
        score object will have all necessary information for that lesson. So method
 
55
        3 will replace this one.
 
56
 
 
57
    2. Personal settings dialog: the user selects the rithmic patterns to generate.
 
58
        Valid only to generate simple repetitive patterns. Composer must have
 
59
        knowledge for completing bars with rest or single notes.
 
60
 
 
61
    3. Pararameters in html object: the parameters must include all necesary data.
 
62
        Score generation based only on received fragments.
 
63
 
 
64
    4. Reading notes exercises: the parameters are fixed for this exercise (parameters
 
65
        the html object) but certain values (clefs, notes range) would need 
 
66
        user settings
 
67
 
 
68
    Free exercises page will be based only on method 2 in coherence with its purpose
 
69
    (free exercises, user customizable). For practising an specific level/lesson the
 
70
    user must choose the corresponding book/page. In these pages it would be allowed
 
71
    to customize settings by adding/removing fragments or changing clefs and note ranges.
 
72
 
 
73
*/
 
74
 
 
75
/*! This class pack all parameters to set up a Side Reading exercise.
 
76
    The contained lmScoreConstrains object has the constrains for the 'ByProgram'
 
77
    settings mode (default mode). For other modes ('UserSettings' and 'ReadingNotes')
 
78
    the settings must be read/setup by the TheoSideReadingCtrol object.
 
79
*/
 
80
class lmTheoSideReadingCtrolParms : public lmObjectParams
 
81
{
 
82
public:
 
83
    lmTheoSideReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
 
84
                              int nPercent, long nStyle);
 
85
    ~lmTheoSideReadingCtrolParms();
 
86
 
 
87
    void AddParam(const wxHtmlTag& tag);
 
88
    void CreateHtmlCell(wxHtmlWinParser *pHtmlParser);
 
89
 
 
90
protected:
 
91
    bool AnalyzeClef(wxString sLine);
 
92
    bool AnalyzeTime(wxString sLine);
 
93
    bool AnalyzeKeys(wxString sLine);
 
94
    bool AnalyzeFragments(wxString sLine);
 
95
 
 
96
        // Member variables:
 
97
 
 
98
    // html object window attributes
 
99
    long                        m_nWindowStyle;
 
100
    lmScoreConstrains*          m_pConstrains;
 
101
    lmSideReadingCtrolOptions*  m_pOptions;
 
102
    wxString                    m_sParamErrors;
 
103
 
 
104
    DECLARE_NO_COPY_CLASS(lmTheoSideReadingCtrolParms)
 
105
};
 
106
 
 
107
 
 
108
 
 
109
lmTheoSideReadingCtrolParms::lmTheoSideReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
 
110
                                   int nPercent, long nStyle)
 
111
    : lmObjectParams(tag, nWidth, nHeight, nPercent)
 
112
{
 
113
 
 
114
    // html object window attributes
 
115
    m_nWindowStyle = nStyle;
 
116
 
 
117
    // construct constrains object
 
118
    m_pConstrains = new lmScoreConstrains();
 
119
 
 
120
    // object options
 
121
    m_pOptions = new lmSideReadingCtrolOptions();
 
122
 
 
123
    // initializations
 
124
    m_sParamErrors = _T("");    //no errors
 
125
 
 
126
}
 
127
 
 
128
 
 
129
lmTheoSideReadingCtrolParms::~lmTheoSideReadingCtrolParms()
 
130
{
 
131
    //Constrains and options will be deleted by the Ctrol. DO NOT DELETE THEM HERE
 
132
    //IF THE CONTROL HAS BEEN CREATED
 
133
    if (m_sParamErrors != _T("")) {
 
134
        if (m_pConstrains) delete m_pConstrains;
 
135
        if (m_pOptions) delete m_pOptions;
 
136
    }
 
137
 
 
138
}
 
139
 
 
140
void lmTheoSideReadingCtrolParms::AddParam(const wxHtmlTag& tag)
 
141
{
 
142
    /*! @page SideReadingCtrolParams
 
143
        @verbatim    
 
144
 
 
145
        Params for lmScoreCtrol - html object type="Application/LenMusTheoSideReading"
 
146
 
 
147
 
 
148
        optional params to include controls: (not yet implemented marked as [])
 
149
        --------------------------------------
 
150
 
 
151
        control_play    Include 'play' link. Default: do not include it.
 
152
                        Value="play label|stop playing label". i.e.: "Play|Stop" Stop label
 
153
                        is optional. Default labels: "Play|Stop"
 
154
 
 
155
        control_solfa   Include 'solfa' link. Default: do not include it.
 
156
                        Value="side read label|stop side reading label". i.e.: 
 
157
                        "Play|Stop". Stop label is optional.
 
158
                        Default labels: "Read|Stop"
 
159
 
 
160
        control_settings    Value="[key for storing the settings]"  
 
161
                            This param forces to include the 'settings' link. The
 
162
                            key will be used both as the key for saving the user settings
 
163
                            and as a tag to select the Setting Dialog options to allow.
 
164
 
 
165
        control_go_back    URL, i.e.: "v2_L2_SideReading_203.htm"
 
166
 
 
167
 
 
168
        params to set up the score composer:
 
169
        ------------------------------------
 
170
 
 
171
        fragment*   one param for each fragment to use
 
172
 
 
173
        clef*       one param for each allowed clef. It includes the pitch scope.
 
174
 
 
175
        time        a list of allowed time signatures, i.e.: "68,98,128"
 
176
 
 
177
        key         keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
 
178
 
 
179
        maxInterval    a number indicating the maximum allowed interval for two consecutive notes
 
180
                        Default: 4
 
181
 
 
182
        @todo: update the example
 
183
        Example:
 
184
        ------------------------------------
 
185
 
 
186
        <object type="Application/LenMusTheoSideReading" width="100%" height="300" border="0">
 
187
            <param name="control" value="play">
 
188
            <param name="label_play" value="Play|Stop">
 
189
            <param name="control" value="solfa">
 
190
            <param name="mode" value="PersonalSettings">
 
191
            <param name="mode" value="NotesReading">
 
192
            <param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
 
193
                <param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
 
194
                <param name="fragment" value="68,98;(n * n)(n * c)">
 
195
                <param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
 
196
            <param name="clef" value="Sol;a3;a5">
 
197
            <param name="clef" value="Fa4;a2;e4">
 
198
            <param name="time" value="68,98,128">
 
199
            <param name="key" value="all">
 
200
            <param name="maxInterval" value="4">
 
201
        </object>
 
202
 
 
203
        @endverbatim
 
204
 
 
205
    */
 
206
 
 
207
    wxString sName = wxEmptyString;
 
208
    wxString sValue = wxEmptyString;
 
209
 
 
210
    // scan name and value
 
211
    if (!tag.HasParam(wxT("NAME"))) return;        // ignore param tag if no name attribute
 
212
    sName = tag.GetParam(_T("NAME"));
 
213
    sName.UpperCase();        //convert to upper case
 
214
 
 
215
    if (!tag.HasParam(_T("VALUE"))) return;        // ignore param tag if no value attribute
 
216
    
 
217
    // control_play
 
218
    if ( sName == _T("CONTROL_PLAY") ) {
 
219
        m_pOptions->SetControlPlay(true, tag.GetParam(_T("VALUE")) );
 
220
    }
 
221
 
 
222
    // control_solfa
 
223
    else if ( sName == _T("CONTROL_SOLFA") ) {
 
224
        m_pOptions->SetControlSolfa(true, tag.GetParam(_T("VALUE")) );
 
225
    }
 
226
 
 
227
    // "Go back to theory" link
 
228
    else if ( sName == _T("CONTROL_GO_BACK") ) {
 
229
        m_pOptions->SetGoBackURL( tag.GetParam(_T("VALUE") ));
 
230
    }
 
231
 
 
232
    // control_settings
 
233
    else if ( sName == _T("CONTROL_SETTINGS") ) {
 
234
        m_pOptions->SetControlSettings(true, tag.GetParam(_T("VALUE")) );
 
235
        m_pConstrains->SetSection( tag.GetParam(_T("VALUE") ));
 
236
    }
 
237
 
 
238
    //fragments   the list of fragmens to use
 
239
    //  <param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
 
240
        //  <param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
 
241
        //  <param name="fragment" value="68,98;(n * n)(n * c)">
 
242
        //  <param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
 
243
 
 
244
    else if ( sName == _T("FRAGMENT") ) {
 
245
        wxString sFragments = tag.GetParam(_T("VALUE"));
 
246
        AnalyzeFragments(sFragments);
 
247
    }
 
248
 
 
249
    //clef*        one param for each allowed clef. It includes the pitch scope.
 
250
    //  <param name="clef" value="Sol;a3;a5" />
 
251
    //  <param name="clef" value="Fa4;a2;e4" />
 
252
 
 
253
    else if ( sName == _T("CLEF") ) {
 
254
        wxString sClef = tag.GetParam(_T("VALUE"));
 
255
        if (AnalyzeClef(sClef)) {
 
256
            m_sParamErrors += wxString::Format( wxGetTranslation(
 
257
                _T("Invalid param value in:\n<param %s >\n")
 
258
                _T("Invalid value = %s \n")
 
259
                _T("Acceptable format: <Clef,LowerNote,UpperNote> \n")
 
260
                _T("Acceptable clef values: Sol | Fa4 | Fa3 | Do4 | Do3 | Do2 | Do1 \n")
 
261
                _T("Acceptable note pitch: c0 - c9")),
 
262
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
 
263
        }
 
264
    }
 
265
 
 
266
    //time        a list of allowed time signatures, i.e.: "68,98,128"
 
267
    //    <param name="time" value="68,98,128">
 
268
 
 
269
    else if ( sName == _T("TIME") ) {
 
270
        wxString sTime = tag.GetParam(_T("VALUE"));
 
271
        if (AnalyzeTime(sTime)) {
 
272
            m_sParamErrors += wxString::Format( wxGetTranslation(
 
273
                _T("Invalid param value in:\n<param %s >\n")
 
274
                _T("Invalid value = %s \n")
 
275
                _T("Acceptable format: list of time signatures \n")),
 
276
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
 
277
        }
 
278
    }
 
279
 
 
280
    //key         keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
 
281
    //    <param name="key" value="all">
 
282
 
 
283
    else if ( sName == _T("KEY") ) {
 
284
        wxString sKeys = tag.GetParam(_T("VALUE"));
 
285
        if (AnalyzeKeys(sKeys)) {
 
286
            m_sParamErrors += wxString::Format( wxGetTranslation(
 
287
                _T("Invalid param value in:\n<param %s >\n")
 
288
                _T("Invalid value = %s \n")
 
289
                _T("Acceptable format: list of key signatures or keyword 'all' \n")),
 
290
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
 
291
        }
 
292
    }
 
293
 
 
294
    //maxGroupInterval    a number
 
295
    else if ( sName == _T("MAXINTERVAL") ) {
 
296
        wxString sMaxInterval = tag.GetParam(_T("VALUE"));
 
297
        long nMaxInterval;
 
298
        bool fOK = sMaxInterval.ToLong(&nMaxInterval);
 
299
        if (!fOK || nMaxInterval < 0 ) {
 
300
            m_sParamErrors += wxString::Format( wxGetTranslation(
 
301
                _T("Invalid param value in:/n<param %s >/n")
 
302
                _T("Invalid value = %s /n")
 
303
                _T("Acceptable values: numeric, greater than 0\n") ),
 
304
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
 
305
        }
 
306
        else {
 
307
            m_pConstrains->SetMaxInterval((int)nMaxInterval);
 
308
        }
 
309
    }
 
310
 
 
311
    // Unknown param
 
312
    else
 
313
        m_sParamErrors += wxString::Format( 
 
314
            _("lmTheoSideReadingCtrol. Unknown param: <param %s >\n"),
 
315
            tag.GetAllParams() );
 
316
 
 
317
}
 
318
 
 
319
void lmTheoSideReadingCtrolParms::CreateHtmlCell(wxHtmlWinParser *pHtmlParser)
 
320
{
 
321
    //The <object> tag has been read. If param 'control_settings' has been specified
 
322
    // configuration values must be loaded from the specified section key
 
323
    m_pConstrains->LoadSettings();
 
324
 
 
325
    //verify that all necessary html params has been specified
 
326
    wxWindow* pWnd;
 
327
    m_sParamErrors += m_pConstrains->Verify();
 
328
    if (m_sParamErrors != _T("")) {
 
329
        // there are errors: display a text box with the error message
 
330
        pWnd = new wxTextCtrl((wxWindow*)pHtmlParser->GetWindow(), -1, m_sParamErrors,
 
331
            wxPoint(0,0), wxSize(300, 100), wxTE_MULTILINE);
 
332
    }
 
333
    else {
 
334
        // create the TheoSideReadingCtrol
 
335
        pWnd = new lmTheoSideReadingCtrol((wxWindow*)pHtmlParser->GetWindow(), -1, 
 
336
            m_pOptions, m_pConstrains, wxPoint(0,0), wxSize(m_nWidth, m_nHeight), m_nWindowStyle );
 
337
    }
 
338
    pWnd->Show(true);
 
339
    pHtmlParser->GetContainer()->InsertCell(new wxHtmlWidgetCell(pWnd, m_nPercent));
 
340
 
 
341
}
 
342
 
 
343
/// returns true if error
 
344
bool lmTheoSideReadingCtrolParms::AnalyzeClef(wxString sLine)
 
345
{
 
346
    //i.e.: "Sol;c4;c5"
 
347
 
 
348
    //get clef
 
349
    int iSemicolon = sLine.Find(_T(";"));
 
350
    wxString sClef = sLine.Left(iSemicolon);
 
351
    EClefType nClef = LDPNameToClef(sClef);
 
352
    if (nClef == (EClefType)-1) return true;    //error
 
353
 
 
354
    //get lower scope
 
355
    sLine = sLine.Mid(iSemicolon+1);
 
356
    iSemicolon = sLine.Find(_T(";"));
 
357
    wxString sLowerScope = sLine.Left(iSemicolon);
 
358
 
 
359
    //get upper scope
 
360
    wxString sUpperScope = sLine.Mid(iSemicolon + 1);
 
361
 
 
362
    //Update information for this clef
 
363
    lmClefConstrain* pClefs = m_pConstrains->GetClefConstrains();
 
364
    pClefs->SetValid(nClef, true);
 
365
    pClefs->SetLowerPitch(nClef, sLowerScope);
 
366
    pClefs->SetUpperPitch(nClef, sUpperScope);
 
367
 
 
368
    return false;   //no error
 
369
 
 
370
}
 
371
 
 
372
/// returns true if error
 
373
bool lmTheoSideReadingCtrolParms::AnalyzeTime(wxString sLine)
 
374
{
 
375
    //i.e.: "98" , "38,68,128" , "24,44"
 
376
 
 
377
    //build time signatures constrains object
 
378
    lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
 
379
    if (pTimeSigns->SetConstrains(sLine)) return true;
 
380
 
 
381
    //Replace information about allowed time signatures
 
382
    lmTimeSignConstrains* pOldTimeSigns = m_pConstrains->GetTimeSignConstrains();
 
383
    int i;
 
384
    ETimeSignature nTime;
 
385
    for (i=lmMIN_TIME_SIGN; i <= lmMAX_TIME_SIGN; i++) {
 
386
        nTime = (ETimeSignature)i;
 
387
        pOldTimeSigns->SetValid(nTime, pTimeSigns->IsValid(nTime) );
 
388
    }
 
389
    delete pTimeSigns;
 
390
 
 
391
    return false;   //no error
 
392
 
 
393
}
 
394
 
 
395
/// returns true if error
 
396
bool lmTheoSideReadingCtrolParms::AnalyzeKeys(wxString sLine)
 
397
{
 
398
    //i.e.: "all" , "do,sol,fa," 
 
399
 
 
400
    if (sLine == _T("all")) {
 
401
        // allow all key signatures
 
402
        lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
 
403
        int i;
 
404
        for (i=0; i <= earmFa; i++) {
 
405
            pKeys->SetValid((EKeySignatures)i, true);
 
406
        }
 
407
    }
 
408
 
 
409
    else {
 
410
        //analyze and set key signatures
 
411
        lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
 
412
 
 
413
        //loop to get all keys
 
414
        int iColon;
 
415
        wxString sKey;
 
416
        EKeySignatures nKey;
 
417
        while (sLine != _T("")) {
 
418
            //get key
 
419
            iColon = sLine.Find(_T(","));
 
420
            if (iColon != -1) {
 
421
                sKey = sLine.Left(iColon);
 
422
                sLine = sLine.Mid(iColon + 1);      //skip the colon
 
423
            }
 
424
            else {
 
425
                sKey = sLine;
 
426
                sLine = _T("");
 
427
            }
 
428
            nKey = LDPNameToKey(sKey);
 
429
            if (nKey == (EKeySignatures)-1) return true;
 
430
            pKeys->SetValid(nKey, true);
 
431
        }
 
432
    }
 
433
 
 
434
    return false;   //no error
 
435
 
 
436
}
 
437
 
 
438
/// returns true if error
 
439
bool lmTheoSideReadingCtrolParms::AnalyzeFragments(wxString sLine)
 
440
{
 
441
    //i.e.: "24,34;(s c)(n * n)(n * s g+)(n * s )(n * c g-)(s c)"
 
442
 
 
443
    //get time signatures
 
444
    int iSemicolon = sLine.Find(_T(";"));
 
445
    wxString sTimeSign = sLine.Left(iSemicolon);
 
446
 
 
447
    //get fragment
 
448
    wxString sFragment = sLine.Mid(iSemicolon + 1);   //skip the semicolon and take the rest
 
449
 
 
450
    //build time signatures constrains object
 
451
    lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
 
452
    if (pTimeSigns->SetConstrains(sTimeSign)) {
 
453
        m_sParamErrors += wxString::Format(_("Error in fragment. Invalid time signature list '%s'\nIn fragment: '%s'\n"),
 
454
                sTimeSign, sFragment);
 
455
        return true;
 
456
     }
 
457
    // verify fragment to avoid program failures
 
458
    lmLDPParser parserLDP;
 
459
    //! @todo strong verification
 
460
    //lmLDPNode* pRoot = parserLDP.ParseText(sFragment);
 
461
    //if (! pRoot) {
 
462
    if (!parserLDP.ParenthesisMatch(sFragment)) {
 
463
        m_sParamErrors += wxString::Format(_("Invalid fragment. Unmatched parenthesis: '%s'\n"), sFragment);
 
464
        return true;
 
465
     }
 
466
    if (sFragment.Find(_T("(g (")) != -1 || sFragment.Find(_T("(g(")) != -1) {
 
467
        m_sParamErrors += wxString::Format(_("Invalid fragment. Old G syntax: '%s'\n"), sFragment);
 
468
        return true;
 
469
     }
 
470
 
 
471
    // build the entry
 
472
    m_pConstrains->AddFragment(pTimeSigns, sFragment);
 
473
 
 
474
    return false;   //no error
 
475
 
 
476
}
 
477
 
 
478
#endif  // __THEOSIDEREADINGCTROLPARMS_H__