1
// RCS-ID: $Id: ColStaffObjs.cpp,v 1.3 2006/02/23 19:22:56 cecilios Exp $
2
//--------------------------------------------------------------------------------------
3
// LenMus Phonascus: The teacher of music
4
// Copyright (c) 2002-2006 Cecilio Salmeron
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.
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.
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.
18
// For any comment, suggestion or feature request, please contact the manager of
19
// the project at cecilios@users.sourceforge.net
21
//-------------------------------------------------------------------------------------
22
/*! @file ColStaffObjs.cpp
23
@brief Implementation file for class lmColStaffObjs
27
//----------------------------------------------------------------------------------------------------
28
/*! @class lmColStaffObjs
30
@brief A Collection of StaffObjs
32
Esta clase encapsula las estructuras de datos y sus m�todos de mantenimiento y acceso, para soportar
33
la representaci�n interna de una colecci�n de StaffObjs (una CStaff, con sus compases y StaffObjs).
35
Inicialmente se modelizaba dentro de CStaff. El problema era que a medida que se complicaba el modelo
36
de objetos se veian afectadas muchas funciones de CStaff. Para independizar
37
a las funciones de la implementaci�n concreta de la secuencia de StaffObjs se ha creado esta
38
clase. As�, podr� cambiarse en el futuro su implenetaci�n (por ejemplo, para mejorar rendimiento)
39
sin que se vea afectado el resto de clases.
41
Lo �nico que hay que respetar son las siguientes restricciones:
42
- Un compas termina siempre con un lmStaffObj de tipo Barra.
43
- Cualquiera que sea el tipo de recorrido elegido, respeta que los StaffObjs de un compas no se
44
recuperan antes que los del siguiente compas. Adem�s, respeta que la barra de fin de compas sea
45
el �ltimo elemento que se recupera de un compas.
47
Para facilitar las futuras modificaciones en las estructuras de datos que implementan esta
48
clase, cuando se crea un iterador se especifica el tipo de recorrido necesario. La implementaci�n
49
debe siempre respetar esos criterios. Los c�digos y sus significados son:
52
Se recorren por el orden en que se encuentran definidos en las estructuras de datos.
53
No tiene que respetar ninguna restricci�n, sino que debe proporcionar los StaffObjs
54
en el orden en que realmente se encuentren almacenados.
55
Esta ordenaci�n se utiliza para depuraci�n, en el m�todo Dump.
56
Tambi�n se usa cuando hay que acceder a todos los StaffObjs de la CStaff y el orden
57
de acceso es totalmente indiferente, ya que siempre ser� el acceso m�s r�pido. Por
58
ejemplo en CStaff.EstablecerPapel
61
The StaffObjs are recovered ordered by increasing time pos
64
the recovery order inside a measure is not important. So use the ordering that results in
65
the fastest access time
67
- Cualquiera que sea el tipo de recorrido elegido, respeta que los StaffObjs de un compas no se
68
recuperan antes que los del siguiente compas. Adem�s, respeta que la barra de fin de compas sea
69
el �ltimo elemento que se recupera de un compas.
72
//----------------------------------------------------------------------------------------------------
75
// #pragma implementation
78
// For compilers that support precompilation, includes "wx/wx.h".
79
#include "wx/wxprec.h"
93
//====================================================================================================
94
//Constructors and destructors
95
//====================================================================================================
96
lmColStaffObjs::lmColStaffObjs()
98
m_fStartMeasure = true;
99
m_rTimePos = 0; //reset time counters
103
lmColStaffObjs::~lmColStaffObjs()
105
//wxLogMessage(wxString::Format(
106
// _T("[lmColStaffObjs::~lmColStaffObjs] Deleting lmColStaffObjs: num objs = %d"), GetNumStaffObjs() ) );
107
m_cStaffobjs.DeleteContents(true);
108
m_cStaffobjs.Clear();
110
m_aStartMeasure.Clear();
111
//wxLogMessage(wxString::Format(
112
// _T("[lmColStaffObjs::~lmColStaffObjs] After deleting lmColStaffObjs: num objs = %d"), GetNumStaffObjs() ) );
117
//====================================================================================================
118
//Funciones de creaci�n, inserci�n y borrado
119
//====================================================================================================
122
void lmColStaffObjs::Store(lmStaffObj *pSO)
125
Stores a lmStaffObj in this StaffObjs collection.
126
Controls division into bars and assign time position to the lmStaffObj
129
pSO: pointer to the lmStaffObj to store
133
//store time position
134
pSO->SetTimePos(m_rTimePos);
136
//increment time counters
137
if (pSO->GetType() == eTPO_NoteRest) {
138
//only NoteRests increment time counters
139
lmNoteRest* pNR = (lmNoteRest*)pSO;
141
m_rTimePos += pNR->GetDuration();
143
//It is a note. Verify if it is part of a chord
144
lmNote* pNote = (lmNote*)pSO;
145
if (!pNote->IsInChord()) {
146
//@attention time counter is going to be incremented also for chord base notes,
148
//As we are in the process of building the score object from the source code,
149
//chord base notes have not yet being marked as "InChord". This is because
150
//the chord is created when the next note is processed.
151
m_rTimePos += pNote->GetDuration();
153
//for (the same reason, this point is reached only by notes that are in a chord
154
//(but not the base note).
155
//Assing to this note the time position of the note base. Do not increment
156
//time counter as it has been already incremented when storing the base note.
157
lmNote* pNoteBase = (pNote->GetChord())->GetBaseNote();
158
pSO->SetTimePos(pNoteBase->GetTimePos());
163
//it is not a lmNoteRest. Increment time counter in the amount coded in the lmStaffObj
164
m_rTimePos += pSO->GetTimePosIncrement();
167
//Time counter update. Update now the maximun value reached.
168
m_rMaxTimePos = wxMax(m_rMaxTimePos, m_rTimePos);
170
//if (the lmStaffObj being stored is a barline it is necessary to ensure that
171
//its time position match up the measure duration, as there could have been back and forward
173
if (pSO->GetType() == eTPO_Barline) {
174
//the object is a barline. Assing to it the maximum time position
175
pSO->SetTimePos(m_rMaxTimePos);
178
//store the lmStaffObj in the collection. StaffObjs are stored by arrival order
179
wxStaffObjsListNode* pNode = m_cStaffobjs.Append(pSO);
181
//if this lmStaffObj is the first one of a measure, store a pointer to the node in the
185
m_fStartMeasure = false;
186
m_aStartMeasure.Add(pNode);
189
//store, inside the lmStaffObj, the measure number in which the lmStaffObj is included
190
pSO->SetNumMeasure((wxInt32)m_aStartMeasure.GetCount() );
192
//Finally, if this lmStaffObj is a barline, signal that a new measure must be started
193
//for the next lmStaffObj and reset time counters
194
if (pSO->GetType() == eTPO_Barline)
196
m_fStartMeasure = true;
197
m_rTimePos = 0; //reset time counters
203
////====================================================================================================
204
////Methods for accesing specific items and information about the collection
205
////====================================================================================================
207
//lmStaffObj* lmColStaffObjs::GetFirst()
209
// m_pNode = m_cStaffobjs.GetFirst();
210
// return (m_pNode ? (lmStaffObj *)m_pNode->GetData() : (lmStaffObj *)m_pNode);
213
//lmStaffObj* lmColStaffObjs::GetNext()
215
// m_pNode = m_pNode->GetNext();
216
// return (m_pNode ? (lmStaffObj *)m_pNode->GetData() : (lmStaffObj *)m_pNode);
220
int lmColStaffObjs::GetNumStaffObjs()
222
//returns the number of StaffObjs in the collection
223
return m_cStaffobjs.GetCount();
226
wxInt32 lmColStaffObjs::GetNumMeasures()
228
//returns the number of bars in the collection
229
return (wxInt32)m_aStartMeasure.GetCount();
233
wxStaffObjsListNode* lmColStaffObjs::GetFirstInMeasure(int nMeasure)
235
//returns the first lmStaffObj in measure number nMeasure (1..n)
236
//This is not a walking method but an access method as:
237
// - the collection is not accessed
238
// - It does not either instantiate an iterator nor return any index to instantiate an
240
//---------------------------------------------------------------------------------------
241
wxASSERT(nMeasure > 0 && nMeasure <= (wxInt32)m_aStartMeasure.GetCount());
242
wxStaffObjsListNode* pNode = m_aStartMeasure.Item(nMeasure-1);
248
wxStaffObjsListNode* lmColStaffObjs::GetFirst()
250
return m_cStaffobjs.GetFirst();
253
wxStaffObjsListNode* lmColStaffObjs::GetLast()
255
return m_cStaffobjs.GetLast();
259
//====================================================================================================
261
//====================================================================================================
263
lmStaffObjIterator* lmColStaffObjs::CreateIterator(ETraversingOrder nOrder)
265
//creates and returns an iterator
266
lmStaffObjIterator* pIter = new lmStaffObjIterator(nOrder, this);
271
void lmColStaffObjs::ShiftTime(float rTimeShift)
274
Shifts time counters, forward or backwards
277
//update time counters and check that shift is inside current measure
278
m_rTimePos += rTimeShift;
279
if (m_rTimePos < 0) { m_rTimePos = 0; } //can not jump back before the start of current measure
280
//! @todo Check that does not go to the next measure
281
//! @todo Display error message if jump out of current measure boundaries
282
// if (m_rTimePos > m_rMaxTimePos) { m_rTimePos = m_rMaxTimePos //can not jump out of this bar