~ubuntu-branches/ubuntu/oneiric/tuxguitar/oneiric

« back to all changes in this revision

Viewing changes to src/org/herac/tuxguitar/gui/editors/piano/Piano.java

  • Committer: Bazaar Package Importer
  • Author(s): Philippe Coval
  • Date: 2008-06-19 00:30:30 UTC
  • mto: (5.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20080619003030-h719szrhsngou7c6
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.herac.tuxguitar.gui.editors.piano;
2
 
 
3
 
import java.util.ArrayList;
4
 
import java.util.Iterator;
5
 
import java.util.List;
6
 
 
7
 
import org.eclipse.swt.SWT;
8
 
import org.eclipse.swt.events.MouseEvent;
9
 
import org.eclipse.swt.events.MouseListener;
10
 
import org.eclipse.swt.events.PaintEvent;
11
 
import org.eclipse.swt.events.PaintListener;
12
 
import org.eclipse.swt.graphics.GC;
13
 
import org.eclipse.swt.graphics.Image;
14
 
import org.eclipse.swt.graphics.Point;
15
 
import org.eclipse.swt.layout.GridData;
16
 
import org.eclipse.swt.layout.GridLayout;
17
 
import org.eclipse.swt.widgets.Button;
18
 
import org.eclipse.swt.widgets.Composite;
19
 
import org.eclipse.swt.widgets.Label;
20
 
import org.herac.tuxguitar.gui.SystemImages;
21
 
import org.herac.tuxguitar.gui.TuxGuitar;
22
 
import org.herac.tuxguitar.gui.actions.caret.GoLeftAction;
23
 
import org.herac.tuxguitar.gui.actions.caret.GoRightAction;
24
 
import org.herac.tuxguitar.gui.actions.duration.DecrementDurationAction;
25
 
import org.herac.tuxguitar.gui.actions.duration.IncrementDurationAction;
26
 
import org.herac.tuxguitar.gui.actions.tools.SelectScaleAction;
27
 
import org.herac.tuxguitar.gui.editors.tab.Caret;
28
 
import org.herac.tuxguitar.gui.editors.tab.MeasureComponent;
29
 
import org.herac.tuxguitar.gui.editors.tab.NoteCoords;
30
 
import org.herac.tuxguitar.gui.undo.undoables.measure.UndoableMeasureGeneric;
31
 
import org.herac.tuxguitar.song.managers.SongManager;
32
 
import org.herac.tuxguitar.song.models.Duration;
33
 
import org.herac.tuxguitar.song.models.InstrumentString;
34
 
import org.herac.tuxguitar.song.models.Note;
35
 
import org.herac.tuxguitar.song.models.NoteEffect;
36
 
 
37
 
public class Piano extends Composite{
38
 
 
39
 
        private static final boolean TYPE_NOTES[] = new boolean[]{true,false,true,false,true,true,false,true,false,true,false,true};
40
 
        
41
 
        private static final int NATURAL_NOTES = 7;
42
 
        
43
 
        private static final int MAX_OCTAVES = 8;
44
 
        
45
 
        private static final int NATURAL_WIDTH = 15;
46
 
        
47
 
        private static final int SHARP_WIDTH = 8;
48
 
        
49
 
        private static final int NATURAL_HEIGHT = 60;
50
 
        
51
 
        private static final int SHARP_HEIGHT = 40;                             
52
 
        
53
 
        private static final int MOUSE_MOVE_DELAY = 10;
54
 
 
55
 
        private PianoListener listener;
56
 
        
57
 
        private Image image;            
58
 
        
59
 
        private Composite pianoComposite;
60
 
        
61
 
        private Composite toolComposite;
62
 
 
63
 
        private Label durationLabel;    
64
 
        
65
 
        private Button scale;
66
 
        
67
 
        private List components;
68
 
        
69
 
        private long lastMouseMoveTime; 
70
 
        
71
 
        private boolean scaleChanges;
72
 
        
73
 
        public Piano(Composite parent, int style) {
74
 
                super(parent, style);
75
 
                this.setLayout(new GridLayout());
76
 
                this.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
77
 
                this.listener =  new PianoListener();
78
 
                this.components = new ArrayList();
79
 
                
80
 
                initToolBar();
81
 
                makePiano();
82
 
        }
83
 
 
84
 
        
85
 
 
86
 
        private void initToolBar() {
87
 
                GridLayout layout = new GridLayout();
88
 
                layout.makeColumnsEqualWidth = false;
89
 
                layout.numColumns = 0;
90
 
                
91
 
            toolComposite = new Composite(this, SWT.NONE);          
92
 
                    
93
 
                // position
94
 
            layout.numColumns ++;
95
 
                Button goLeft = new Button(toolComposite, SWT.ARROW | SWT.LEFT);
96
 
                goLeft.addSelectionListener(TuxGuitar.instance().getAction(GoLeftAction.NAME));
97
 
                
98
 
                layout.numColumns ++;
99
 
                Button goRight = new Button(toolComposite, SWT.ARROW | SWT.RIGHT);
100
 
                goRight.addSelectionListener(TuxGuitar.instance().getAction(GoRightAction.NAME));
101
 
                
102
 
                // separator            
103
 
                layout.numColumns ++;
104
 
                makeToolSeparator(toolComposite);
105
 
                
106
 
                // duration 
107
 
                layout.numColumns ++;
108
 
                Button decrement = new Button(toolComposite, SWT.ARROW | SWT.MIN);
109
 
                decrement.addSelectionListener(TuxGuitar.instance().getAction(DecrementDurationAction.NAME));
110
 
 
111
 
                layout.numColumns ++;
112
 
                durationLabel = new Label(toolComposite, SWT.BORDER);
113
 
                durationLabel.setImage(getDurationImage());
114
 
                
115
 
                layout.numColumns ++;
116
 
                Button increment = new Button(toolComposite, SWT.ARROW | SWT.MAX);
117
 
                increment.addSelectionListener(TuxGuitar.instance().getAction(IncrementDurationAction.NAME));
118
 
                
119
 
                // separator
120
 
                layout.numColumns ++;
121
 
                makeToolSeparator(toolComposite);
122
 
                
123
 
                // escala
124
 
                layout.numColumns ++;
125
 
                scale = new Button(toolComposite, SWT.PUSH);
126
 
                scale.setText(TuxGuitar.getProperty("scale"));
127
 
                scale.addSelectionListener(TuxGuitar.instance().getAction(SelectScaleAction.NAME));             
128
 
 
129
 
                                
130
 
                toolComposite.setLayout(layout);            
131
 
                toolComposite.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,true));
132
 
        }       
133
 
        
134
 
 
135
 
        private void makeToolSeparator(Composite parent){
136
 
                Label separator = new Label(parent,SWT.SEPARATOR);
137
 
                separator.setLayoutData(new GridData(20,20));
138
 
        }
139
 
        
140
 
        private Image getDurationImage() {
141
 
                Duration duration = (Duration) TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getDuration().clone();
142
 
                return SystemImages.getDuration(duration.getValue());           
143
 
        }
144
 
 
145
 
        
146
 
        private void makePiano(){
147
 
                final Point position = new Point(0,0);          
148
 
                this.image = makePianoImage();          
149
 
                this.pianoComposite = new Composite(this,SWT.BORDER | SWT.DOUBLE_BUFFERED);             
150
 
                this.pianoComposite.setLayout(new GridLayout());
151
 
                this.pianoComposite.setLayoutData(new GridData((NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT));
152
 
                this.pianoComposite.addPaintListener(this.listener);            
153
 
                this.pianoComposite.addMouseListener(this.listener);
154
 
        }
155
 
 
156
 
        /**
157
 
         * Crea la imagen del piano
158
 
         *
159
 
         * @return
160
 
         */
161
 
        private Image makePianoImage(){
162
 
                Image image = new Image(getDisplay(),(NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT);
163
 
                GC gc = new GC(image);
164
 
                                
165
 
                int x = 0;
166
 
                int y = 0;              
167
 
                gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
168
 
                gc.fillRectangle(x,y,(NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT);
169
 
                for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
170
 
                        
171
 
                        if(TYPE_NOTES[i % TYPE_NOTES.length]){
172
 
                                gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
173
 
                                gc.drawRectangle(x,y,NATURAL_WIDTH,NATURAL_HEIGHT);
174
 
                                x += NATURAL_WIDTH;
175
 
                        }else{
176
 
                                gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));                                                 
177
 
                                gc.fillRectangle(x - (SHARP_WIDTH / 2),y,SHARP_WIDTH,SHARP_HEIGHT);             
178
 
                        }                       
179
 
                }
180
 
                paintScale(gc);
181
 
                
182
 
                gc.dispose();
183
 
                return image;
184
 
        }
185
 
        
186
 
        /**
187
 
         * Pinta la nota a partir del indice
188
 
         *       
189
 
         * @param gc
190
 
         * @param value
191
 
         */
192
 
        private void paintScale(GC gc){
193
 
                
194
 
                gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_RED));
195
 
                gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_RED));   
196
 
                int posX = 0;
197
 
                int y = 0;
198
 
                
199
 
                for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){                    
200
 
                        int width = 0;
201
 
 
202
 
                        if(TYPE_NOTES[i % TYPE_NOTES.length]){
203
 
                                width = NATURAL_WIDTH;
204
 
                                if(i > 0 && !TYPE_NOTES[(i - 1)  % TYPE_NOTES.length]){
205
 
                                        width -= ((SHARP_WIDTH / 2));
206
 
                                }
207
 
                                if(!TYPE_NOTES[(i + 1)  % TYPE_NOTES.length]){
208
 
                                        width -= ((SHARP_WIDTH / 2));
209
 
                                }                       
210
 
                        }else{
211
 
                                width = SHARP_WIDTH;
212
 
                        }
213
 
                                                
214
 
                        if(TuxGuitar.instance().getScaleManager().getScale().getNote(i)){                       
215
 
                                if(TYPE_NOTES[i % TYPE_NOTES.length] ){                                 
216
 
                                        int x = posX;
217
 
                                        if(i > 0 && !TYPE_NOTES[(i - 1)  % TYPE_NOTES.length]){
218
 
                                                x -= ((SHARP_WIDTH / 2));
219
 
                                        }
220
 
                                        
221
 
                                        int size = SHARP_WIDTH;
222
 
                                        gc.fillRectangle( (x + 1 + (((NATURAL_WIDTH - size) / 2))) ,(NATURAL_HEIGHT - size - (((NATURAL_WIDTH - size) / 2))),size,size);                                        
223
 
                                }else{
224
 
                                        int size = width - 2;
225
 
                                        gc.fillRectangle(posX + 1, SHARP_HEIGHT - SHARP_WIDTH + 1,SHARP_WIDTH - 2,SHARP_WIDTH - 2);                                     
226
 
                                }                                                                       
227
 
                        }
228
 
                                                
229
 
                        posX += width;
230
 
                }
231
 
                        
232
 
        }       
233
 
                
234
 
        
235
 
        /**
236
 
         * Pinta la nota a partir del indice
237
 
         *       
238
 
         * @param gc
239
 
         * @param value
240
 
         */
241
 
        private void paintNote(GC gc,int value){
242
 
                gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));          
243
 
                int posX = 0;
244
 
                int y = 0;
245
 
                
246
 
                for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){                    
247
 
                        int width = 0;
248
 
 
249
 
                        if(TYPE_NOTES[i % TYPE_NOTES.length]){
250
 
                                width = NATURAL_WIDTH;
251
 
                                if(i > 0 && !TYPE_NOTES[(i - 1)  % TYPE_NOTES.length]){
252
 
                                        width -= ((SHARP_WIDTH / 2));
253
 
                                }
254
 
                                if(!TYPE_NOTES[(i + 1)  % TYPE_NOTES.length]){
255
 
                                        width -= ((SHARP_WIDTH / 2));
256
 
                                }                       
257
 
                        }else{
258
 
                                width = SHARP_WIDTH;
259
 
                        }
260
 
                                                
261
 
                        if(i == value){                 
262
 
                                if(TYPE_NOTES[i % TYPE_NOTES.length]){                                  
263
 
                                        gc.fillRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT);
264
 
                                        
265
 
                                        int x = posX;
266
 
                                        if(i > 0 && !TYPE_NOTES[(i - 1)  % TYPE_NOTES.length]){
267
 
                                                x -= ((SHARP_WIDTH / 2));
268
 
                                        }
269
 
                                        gc.fillRectangle(x + 1,(y + SHARP_HEIGHT) + 1,NATURAL_WIDTH - 1,(NATURAL_HEIGHT - SHARP_HEIGHT) - 1);                                   
270
 
                                }else{
271
 
                                        gc.fillRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT - 1);
272
 
                                }                                                                       
273
 
                        }
274
 
                                                
275
 
                        posX += width;
276
 
                }
277
 
                        
278
 
        }       
279
 
        
280
 
        /**
281
 
         * Retorna el indice de la nota seleccionada
282
 
         * 
283
 
         * @param point
284
 
         * @return
285
 
         */
286
 
        private int getSelection(Point point){          
287
 
                int posX = 0;
288
 
 
289
 
                for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){                    
290
 
                        int width = 0;
291
 
 
292
 
                        if(TYPE_NOTES[i % TYPE_NOTES.length]){
293
 
                                width = NATURAL_WIDTH;
294
 
                                if(i > 0 && !TYPE_NOTES[(i - 1)  % TYPE_NOTES.length]){
295
 
                                        width -= ((SHARP_WIDTH / 2));
296
 
                                }
297
 
                                if(!TYPE_NOTES[(i + 1)  % TYPE_NOTES.length]){
298
 
                                        width -= ((SHARP_WIDTH / 2));
299
 
                                }                       
300
 
                        }else{
301
 
                                width = SHARP_WIDTH;
302
 
                        }
303
 
                        
304
 
                        if(point.x >= posX && point.x < (posX + width)  ){                      
305
 
                                return i;                                                               
306
 
                        }
307
 
                                                
308
 
                        posX += width;
309
 
                }
310
 
                return -1;      
311
 
        }               
312
 
 
313
 
        
314
 
        private void hit(int x, int y) {
315
 
                int value = getSelection(new Point(x,y));
316
 
                
317
 
                if (!removeNote(value)) {
318
 
                        addNote(value);                                 
319
 
                }
320
 
        }
321
 
 
322
 
        private boolean removeNote(int value) {
323
 
                Iterator it = this.components.iterator();
324
 
                while (it.hasNext()) {
325
 
                        MeasureComponent component = (MeasureComponent) it.next();
326
 
                        if (component instanceof NoteCoords) {
327
 
                                NoteCoords note = (NoteCoords) component;
328
 
                                if (note.getRealValue() == value) {
329
 
                                //comienza el undoable
330
 
                                UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();     
331
 
                                        
332
 
                                        Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
333
 
                                        SongManager manager = TuxGuitar.instance().getSongManager(); 
334
 
                                        manager.getMeasureManager().removeNote(caret.getMeasureCoords().getMeasure(),note.getNote());
335
 
                                        
336
 
                                //termia el undoable
337
 
                                        TuxGuitar.instance().getTablatureEditor().getUndoManager().addEdit(undoable.endUndo());                                         
338
 
                                        
339
 
                                        return true;
340
 
                                }
341
 
                        }
342
 
                }
343
 
                return false;
344
 
        }       
345
 
        
346
 
        private boolean addNote(int value) {
347
 
                Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
348
 
                
349
 
                List strings = caret.getSongTrackCoords().getTrack().getStrings();
350
 
                for(int i = 0;i < strings.size();i ++){
351
 
                        InstrumentString string = (InstrumentString)strings.get(i);
352
 
                        if(value >= string.getValue()){
353
 
                                boolean emptyString = true;
354
 
                                
355
 
                                Iterator it = this.components.iterator();
356
 
                                while (it.hasNext()) {
357
 
                                        MeasureComponent component = (MeasureComponent) it.next();
358
 
                                        if (component instanceof NoteCoords && ((NoteCoords) component).getNote().getString() == string.getNumber()) {
359
 
                                                emptyString = false;
360
 
                                                break;
361
 
                                        }
362
 
                                }
363
 
                                if(emptyString){
364
 
                                //comienza el undoable
365
 
                                        UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
366
 
                                                                                
367
 
                                        Duration duration = (Duration) caret.getDuration().clone();
368
 
                                        Note note = new Note((value - string.getValue()), caret.getPosition(), duration, caret.getVelocity(), string.getNumber(), false, new NoteEffect());
369
 
                                        
370
 
                                        SongManager manager = TuxGuitar.instance().getSongManager();
371
 
                                        manager.getMeasureManager().addNote(caret.getMeasureCoords().getMeasure(),note);                                        
372
 
                                        
373
 
                                //termia el undoable
374
 
                                        TuxGuitar.instance().getTablatureEditor().getUndoManager().addEdit(undoable.endUndo());
375
 
                                        
376
 
                                //reprodusco las notas en el pulso
377
 
                                caret.getMeasureCoords().playBeat(note.getStart());
378
 
                                        
379
 
                                        return true;
380
 
                                }
381
 
                        }
382
 
                }
383
 
                
384
 
                
385
 
                return false;
386
 
        }       
387
 
        
388
 
        private void afterAction() {
389
 
                TuxGuitar.instance().getTablatureEditor().getTablature().getViewLayout().fireUpdate(TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getMeasureCoords().getMeasure().getNumber(), false);            
390
 
                TuxGuitar.instance().redraw();
391
 
                TuxGuitar.instance().updateCache(true);
392
 
        }
393
 
 
394
 
 
395
 
        public boolean isScaleChanges(){
396
 
                return this.scaleChanges;
397
 
        }
398
 
        
399
 
        public void setScaleChanges(boolean changes){
400
 
                this.scaleChanges = changes;
401
 
        }
402
 
        
403
 
        private void updateEditor(){
404
 
                if(isVisible()){
405
 
                        if(isScaleChanges()){
406
 
                                this.image.dispose();
407
 
                                this.image = makePianoImage();
408
 
                        }
409
 
                        SongManager manager = TuxGuitar.instance().getSongManager();
410
 
                        if(TuxGuitar.instance().getPlayer().isRunning()){
411
 
                                this.components = TuxGuitar.instance().getEditorCache().getPlayingComponents();
412
 
                        }else{
413
 
                                this.components = TuxGuitar.instance().getEditorCache().getCaretComponents();
414
 
                        }
415
 
                }
416
 
        }
417
 
        
418
 
        public void redraw() {
419
 
            if(!super.isDisposed()){            
420
 
                super.redraw();
421
 
                this.pianoComposite.redraw();
422
 
                this.durationLabel.setImage(getDurationImage());
423
 
            }
424
 
        }
425
 
 
426
 
        public void redrawPlayingMode(){     
427
 
                if(!super.isDisposed()){
428
 
                this.pianoComposite.redraw();
429
 
                }
430
 
         }
431
 
        
432
 
        public void dispose(){
433
 
                super.dispose();
434
 
                this.image.dispose();
435
 
        }
436
 
        
437
 
    public void loadProperties(){
438
 
            this.scale.setText(TuxGuitar.getProperty("scale"));
439
 
            this.layout();
440
 
    }   
441
 
        
442
 
        private class PianoListener implements PaintListener,MouseListener {
443
 
 
444
 
                public void paintControl(PaintEvent e) {
445
 
                        updateEditor();                 
446
 
                        e.gc.drawImage(image,0,0);                      
447
 
                        //pinto notas
448
 
                        Iterator it = components.iterator();
449
 
                        while(it.hasNext()){
450
 
                                MeasureComponent component = (MeasureComponent)it.next();
451
 
                                if (component instanceof NoteCoords) {
452
 
                                        NoteCoords note = (NoteCoords) component;
453
 
                                        paintNote(e.gc,note.getRealValue());
454
 
                                }
455
 
                        }
456
 
                        e.gc.dispose();
457
 
                }
458
 
                
459
 
                public void mouseUp(MouseEvent e) {
460
 
                        if(e.button == 1){                              
461
 
                                hit(e.x, e.y);
462
 
                                afterAction();
463
 
                        }else{
464
 
                                TuxGuitar.instance().getAction(GoRightAction.NAME).process(e);
465
 
                        }
466
 
                }                       
467
 
                
468
 
                public void mouseDoubleClick(MouseEvent e) {            
469
 
                }
470
 
 
471
 
                public void mouseDown(MouseEvent e) {                   
472
 
                }       
473
 
        }       
474
 
}