1
package org.herac.tuxguitar.gui.editors.piano;
3
import java.util.ArrayList;
4
import java.util.Iterator;
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;
37
public class Piano extends Composite{
39
private static final boolean TYPE_NOTES[] = new boolean[]{true,false,true,false,true,true,false,true,false,true,false,true};
41
private static final int NATURAL_NOTES = 7;
43
private static final int MAX_OCTAVES = 8;
45
private static final int NATURAL_WIDTH = 15;
47
private static final int SHARP_WIDTH = 8;
49
private static final int NATURAL_HEIGHT = 60;
51
private static final int SHARP_HEIGHT = 40;
53
private static final int MOUSE_MOVE_DELAY = 10;
55
private PianoListener listener;
59
private Composite pianoComposite;
61
private Composite toolComposite;
63
private Label durationLabel;
67
private List components;
69
private long lastMouseMoveTime;
71
private boolean scaleChanges;
73
public Piano(Composite parent, int 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();
86
private void initToolBar() {
87
GridLayout layout = new GridLayout();
88
layout.makeColumnsEqualWidth = false;
89
layout.numColumns = 0;
91
toolComposite = new Composite(this, SWT.NONE);
95
Button goLeft = new Button(toolComposite, SWT.ARROW | SWT.LEFT);
96
goLeft.addSelectionListener(TuxGuitar.instance().getAction(GoLeftAction.NAME));
99
Button goRight = new Button(toolComposite, SWT.ARROW | SWT.RIGHT);
100
goRight.addSelectionListener(TuxGuitar.instance().getAction(GoRightAction.NAME));
103
layout.numColumns ++;
104
makeToolSeparator(toolComposite);
107
layout.numColumns ++;
108
Button decrement = new Button(toolComposite, SWT.ARROW | SWT.MIN);
109
decrement.addSelectionListener(TuxGuitar.instance().getAction(DecrementDurationAction.NAME));
111
layout.numColumns ++;
112
durationLabel = new Label(toolComposite, SWT.BORDER);
113
durationLabel.setImage(getDurationImage());
115
layout.numColumns ++;
116
Button increment = new Button(toolComposite, SWT.ARROW | SWT.MAX);
117
increment.addSelectionListener(TuxGuitar.instance().getAction(IncrementDurationAction.NAME));
120
layout.numColumns ++;
121
makeToolSeparator(toolComposite);
124
layout.numColumns ++;
125
scale = new Button(toolComposite, SWT.PUSH);
126
scale.setText(TuxGuitar.getProperty("scale"));
127
scale.addSelectionListener(TuxGuitar.instance().getAction(SelectScaleAction.NAME));
130
toolComposite.setLayout(layout);
131
toolComposite.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,true));
135
private void makeToolSeparator(Composite parent){
136
Label separator = new Label(parent,SWT.SEPARATOR);
137
separator.setLayoutData(new GridData(20,20));
140
private Image getDurationImage() {
141
Duration duration = (Duration) TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getDuration().clone();
142
return SystemImages.getDuration(duration.getValue());
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);
157
* Crea la imagen del piano
161
private Image makePianoImage(){
162
Image image = new Image(getDisplay(),(NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT);
163
GC gc = new GC(image);
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 ++){
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);
176
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
177
gc.fillRectangle(x - (SHARP_WIDTH / 2),y,SHARP_WIDTH,SHARP_HEIGHT);
187
* Pinta la nota a partir del indice
192
private void paintScale(GC gc){
194
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_RED));
195
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_RED));
199
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
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));
207
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
208
width -= ((SHARP_WIDTH / 2));
214
if(TuxGuitar.instance().getScaleManager().getScale().getNote(i)){
215
if(TYPE_NOTES[i % TYPE_NOTES.length] ){
217
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
218
x -= ((SHARP_WIDTH / 2));
221
int size = SHARP_WIDTH;
222
gc.fillRectangle( (x + 1 + (((NATURAL_WIDTH - size) / 2))) ,(NATURAL_HEIGHT - size - (((NATURAL_WIDTH - size) / 2))),size,size);
224
int size = width - 2;
225
gc.fillRectangle(posX + 1, SHARP_HEIGHT - SHARP_WIDTH + 1,SHARP_WIDTH - 2,SHARP_WIDTH - 2);
236
* Pinta la nota a partir del indice
241
private void paintNote(GC gc,int value){
242
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
246
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
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));
254
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
255
width -= ((SHARP_WIDTH / 2));
262
if(TYPE_NOTES[i % TYPE_NOTES.length]){
263
gc.fillRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT);
266
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
267
x -= ((SHARP_WIDTH / 2));
269
gc.fillRectangle(x + 1,(y + SHARP_HEIGHT) + 1,NATURAL_WIDTH - 1,(NATURAL_HEIGHT - SHARP_HEIGHT) - 1);
271
gc.fillRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT - 1);
281
* Retorna el indice de la nota seleccionada
286
private int getSelection(Point point){
289
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
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));
297
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
298
width -= ((SHARP_WIDTH / 2));
304
if(point.x >= posX && point.x < (posX + width) ){
314
private void hit(int x, int y) {
315
int value = getSelection(new Point(x,y));
317
if (!removeNote(value)) {
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();
332
Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
333
SongManager manager = TuxGuitar.instance().getSongManager();
334
manager.getMeasureManager().removeNote(caret.getMeasureCoords().getMeasure(),note.getNote());
337
TuxGuitar.instance().getTablatureEditor().getUndoManager().addEdit(undoable.endUndo());
346
private boolean addNote(int value) {
347
Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
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;
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()) {
364
//comienza el undoable
365
UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
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());
370
SongManager manager = TuxGuitar.instance().getSongManager();
371
manager.getMeasureManager().addNote(caret.getMeasureCoords().getMeasure(),note);
374
TuxGuitar.instance().getTablatureEditor().getUndoManager().addEdit(undoable.endUndo());
376
//reprodusco las notas en el pulso
377
caret.getMeasureCoords().playBeat(note.getStart());
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);
395
public boolean isScaleChanges(){
396
return this.scaleChanges;
399
public void setScaleChanges(boolean changes){
400
this.scaleChanges = changes;
403
private void updateEditor(){
405
if(isScaleChanges()){
406
this.image.dispose();
407
this.image = makePianoImage();
409
SongManager manager = TuxGuitar.instance().getSongManager();
410
if(TuxGuitar.instance().getPlayer().isRunning()){
411
this.components = TuxGuitar.instance().getEditorCache().getPlayingComponents();
413
this.components = TuxGuitar.instance().getEditorCache().getCaretComponents();
418
public void redraw() {
419
if(!super.isDisposed()){
421
this.pianoComposite.redraw();
422
this.durationLabel.setImage(getDurationImage());
426
public void redrawPlayingMode(){
427
if(!super.isDisposed()){
428
this.pianoComposite.redraw();
432
public void dispose(){
434
this.image.dispose();
437
public void loadProperties(){
438
this.scale.setText(TuxGuitar.getProperty("scale"));
442
private class PianoListener implements PaintListener,MouseListener {
444
public void paintControl(PaintEvent e) {
446
e.gc.drawImage(image,0,0);
448
Iterator it = components.iterator();
450
MeasureComponent component = (MeasureComponent)it.next();
451
if (component instanceof NoteCoords) {
452
NoteCoords note = (NoteCoords) component;
453
paintNote(e.gc,note.getRealValue());
459
public void mouseUp(MouseEvent e) {
464
TuxGuitar.instance().getAction(GoRightAction.NAME).process(e);
468
public void mouseDoubleClick(MouseEvent e) {
471
public void mouseDown(MouseEvent e) {