1
package org.herac.tuxguitar.gui.editors.piano;
3
import java.util.Iterator;
6
import org.eclipse.swt.SWT;
7
import org.eclipse.swt.events.MouseEvent;
8
import org.eclipse.swt.events.MouseListener;
9
import org.eclipse.swt.events.PaintEvent;
10
import org.eclipse.swt.events.PaintListener;
11
import org.eclipse.swt.events.SelectionAdapter;
12
import org.eclipse.swt.events.SelectionEvent;
13
import org.eclipse.swt.graphics.GC;
14
import org.eclipse.swt.graphics.Image;
15
import org.eclipse.swt.graphics.Point;
16
import org.eclipse.swt.layout.GridData;
17
import org.eclipse.swt.layout.GridLayout;
18
import org.eclipse.swt.widgets.Button;
19
import org.eclipse.swt.widgets.Composite;
20
import org.eclipse.swt.widgets.Label;
21
import org.herac.tuxguitar.gui.TuxGuitar;
22
import org.herac.tuxguitar.gui.actions.ActionLock;
23
import org.herac.tuxguitar.gui.actions.caret.GoLeftAction;
24
import org.herac.tuxguitar.gui.actions.caret.GoRightAction;
25
import org.herac.tuxguitar.gui.actions.duration.DecrementDurationAction;
26
import org.herac.tuxguitar.gui.actions.duration.IncrementDurationAction;
27
import org.herac.tuxguitar.gui.actions.tools.ScaleAction;
28
import org.herac.tuxguitar.gui.editors.TGPainter;
29
import org.herac.tuxguitar.gui.editors.tab.Caret;
30
import org.herac.tuxguitar.gui.editors.tab.TGNoteImpl;
31
import org.herac.tuxguitar.gui.undo.undoables.measure.UndoableMeasureGeneric;
32
import org.herac.tuxguitar.song.managers.TGSongManager;
33
import org.herac.tuxguitar.song.models.TGBeat;
34
import org.herac.tuxguitar.song.models.TGDuration;
35
import org.herac.tuxguitar.song.models.TGNote;
36
import org.herac.tuxguitar.song.models.TGString;
38
public class Piano extends Composite{
40
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;
42
private static final int MAX_OCTAVES = 8;
43
private static final int NATURAL_WIDTH = 15;
44
private static final int SHARP_WIDTH = 8;
45
private static final int NATURAL_HEIGHT = 60;
46
private static final int SHARP_HEIGHT = 40;
49
private boolean changes;
50
private PianoListener listener;
51
private PianoConfig config;
52
private Composite pianoComposite;
53
private Composite toolComposite;
54
private Label durationLabel;
56
private Button settings;
57
protected TGBeat beat;
58
protected Image image;
60
public Piano(Composite parent, int style) {
62
this.setLayout(new GridLayout());
63
this.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
64
this.listener = new PianoListener();
65
this.config = new PianoConfig();
71
TuxGuitar.instance().getkeyBindingManager().appendListenersTo(this.toolComposite);
72
TuxGuitar.instance().getkeyBindingManager().appendListenersTo(this.pianoComposite);
75
private void initToolBar() {
76
GridLayout layout = new GridLayout();
77
layout.makeColumnsEqualWidth = false;
78
layout.numColumns = 0;
79
layout.marginWidth = 0;
80
layout.marginHeight = 0;
82
this.toolComposite = new Composite(this, SWT.NONE);
86
Button goLeft = new Button(this.toolComposite, SWT.ARROW | SWT.LEFT);
87
goLeft.addSelectionListener(TuxGuitar.instance().getAction(GoLeftAction.NAME));
90
Button goRight = new Button(this.toolComposite, SWT.ARROW | SWT.RIGHT);
91
goRight.addSelectionListener(TuxGuitar.instance().getAction(GoRightAction.NAME));
95
makeToolSeparator(this.toolComposite);
99
Button decrement = new Button(this.toolComposite, SWT.ARROW | SWT.MIN);
100
decrement.addSelectionListener(TuxGuitar.instance().getAction(DecrementDurationAction.NAME));
102
layout.numColumns ++;
103
this.durationLabel = new Label(this.toolComposite, SWT.BORDER);
105
layout.numColumns ++;
106
Button increment = new Button(this.toolComposite, SWT.ARROW | SWT.MAX);
107
increment.addSelectionListener(TuxGuitar.instance().getAction(IncrementDurationAction.NAME));
110
layout.numColumns ++;
111
makeToolSeparator(this.toolComposite);
114
layout.numColumns ++;
115
this.scale = new Button(this.toolComposite, SWT.PUSH);
116
this.scale.setText(TuxGuitar.getProperty("scale"));
117
this.scale.addSelectionListener(TuxGuitar.instance().getAction(ScaleAction.NAME));
120
layout.numColumns ++;
121
this.settings = new Button(this.toolComposite, SWT.PUSH);
122
this.settings.setImage(TuxGuitar.instance().getIconManager().getSettings());
123
this.settings.setToolTipText(TuxGuitar.getProperty("settings"));
124
this.settings.setLayoutData(new GridData(SWT.RIGHT,SWT.FILL,true,true));
125
this.settings.addSelectionListener(new SelectionAdapter() {
126
public void widgetSelected(SelectionEvent e) {
131
this.toolComposite.setLayout(layout);
132
this.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 void loadDurationImage(boolean force) {
141
int duration = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getDuration().getValue();
142
if(force || this.duration != duration){
143
this.duration = duration;
144
this.durationLabel.setImage(TuxGuitar.instance().getIconManager().getDuration(this.duration));
148
private void makePiano(){
149
this.image = makePianoImage();
150
this.pianoComposite = new Composite(this,SWT.BORDER | SWT.DOUBLE_BUFFERED);
151
this.pianoComposite.setLayout(new GridLayout());
152
this.pianoComposite.setLayoutData(new GridData((NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT));
153
this.pianoComposite.addPaintListener(this.listener);
154
this.pianoComposite.addMouseListener(this.listener);
155
this.pianoComposite.setFocus();
159
* Crea la imagen del piano
163
private Image makePianoImage(){
164
Image image = new Image(getDisplay(),(NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT);
165
TGPainter painter = new TGPainter(new GC(image));
169
painter.setBackground(this.config.getColorNatural());
170
painter.initPath(TGPainter.PATH_FILL);
171
painter.addRectangle(x,y,(NATURAL_WIDTH * (MAX_OCTAVES * NATURAL_NOTES) ),NATURAL_HEIGHT);
173
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
175
if(TYPE_NOTES[i % TYPE_NOTES.length]){
176
painter.setForeground(this.config.getColorNotNatural());
178
painter.addRectangle(x,y,NATURAL_WIDTH,NATURAL_HEIGHT);
182
painter.setBackground(this.config.getColorNotNatural());
183
painter.initPath(TGPainter.PATH_FILL);
184
painter.addRectangle(x - (SHARP_WIDTH / 2),y,SHARP_WIDTH,SHARP_HEIGHT);
195
* Pinta la nota a partir del indice
200
private void paintScale(TGPainter painter){
201
painter.setBackground(this.config.getColorScale());
202
painter.setForeground(this.config.getColorScale());
205
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
208
if(TYPE_NOTES[i % TYPE_NOTES.length]){
209
width = NATURAL_WIDTH;
210
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
211
width -= ((SHARP_WIDTH / 2));
213
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
214
width -= ((SHARP_WIDTH / 2));
220
if(TuxGuitar.instance().getScaleManager().getScale().getNote(i)){
221
if(TYPE_NOTES[i % TYPE_NOTES.length] ){
223
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
224
x -= ((SHARP_WIDTH / 2));
227
int size = SHARP_WIDTH;
228
painter.initPath(TGPainter.PATH_FILL);
229
painter.addRectangle( (x + 1 + (((NATURAL_WIDTH - size) / 2))) ,(NATURAL_HEIGHT - size - (((NATURAL_WIDTH - size) / 2))),size,size);
232
painter.initPath(TGPainter.PATH_FILL);
233
painter.addRectangle(posX + 1, SHARP_HEIGHT - SHARP_WIDTH + 1,SHARP_WIDTH - 2,SHARP_WIDTH - 2);
243
* Pinta la nota a partir del indice
248
protected void paintNote(TGPainter painter,int value){
249
painter.setBackground(this.config.getColorNote());
253
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
256
if(TYPE_NOTES[i % TYPE_NOTES.length]){
257
width = NATURAL_WIDTH;
258
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
259
width -= ((SHARP_WIDTH / 2));
261
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
262
width -= ((SHARP_WIDTH / 2));
269
if(TYPE_NOTES[i % TYPE_NOTES.length]){
270
painter.initPath(TGPainter.PATH_FILL);
271
painter.addRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT);
274
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
275
x -= ((SHARP_WIDTH / 2));
277
painter.addRectangle(x + 1,(y + SHARP_HEIGHT) + 1,NATURAL_WIDTH - 1,(NATURAL_HEIGHT - SHARP_HEIGHT) - 1);
280
painter.initPath(TGPainter.PATH_FILL);
281
painter.addRectangle(posX + 1,y + 1,width - 1,SHARP_HEIGHT - 1);
292
* Retorna el indice de la nota seleccionada
297
private int getSelection(Point point){
300
for(int i = 0; i < (MAX_OCTAVES * TYPE_NOTES.length); i ++){
303
if(TYPE_NOTES[i % TYPE_NOTES.length]){
304
width = NATURAL_WIDTH;
305
if(i > 0 && !TYPE_NOTES[(i - 1) % TYPE_NOTES.length]){
306
width -= ((SHARP_WIDTH / 2));
308
if(!TYPE_NOTES[(i + 1) % TYPE_NOTES.length]){
309
width -= ((SHARP_WIDTH / 2));
315
if(point.x >= posX && point.x < (posX + width) ){
324
protected void hit(int x, int y) {
325
int value = getSelection(new Point(x,y));
327
if (!removeNote(value)) {
332
private boolean removeNote(int value) {
333
if(this.beat != null){
334
Iterator it = this.beat.getNotes().iterator();
335
while (it.hasNext()) {
336
TGNoteImpl note = (TGNoteImpl) it.next();
337
if (note.getRealValue() == value) {
338
//comienza el undoable
339
UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
341
TGSongManager manager = TuxGuitar.instance().getSongManager();
342
manager.getMeasureManager().removeNote(note);
345
TuxGuitar.instance().getUndoableManager().addEdit(undoable.endUndo());
346
TuxGuitar.instance().getFileHistory().setUnsavedFile();
355
private boolean addNote(int value) {
356
Caret caret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret();
358
List strings = caret.getTrack().getStrings();
359
for(int i = 0;i < strings.size();i ++){
360
TGString string = (TGString)strings.get(i);
361
if(value >= string.getValue()){
362
boolean emptyString = true;
364
if(this.beat != null){
365
Iterator it = this.beat.getNotes().iterator();
366
while (it.hasNext()) {
367
TGNoteImpl note = (TGNoteImpl) it.next();
368
if (note.getString() == string.getNumber()) {
375
TGSongManager manager = TuxGuitar.instance().getSongManager();
377
//comienza el undoable
378
UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
380
TGNote note = manager.getFactory().newNote();
381
note.setValue((value - string.getValue()));
382
note.setVelocity(caret.getVelocity());
383
note.setString(string.getNumber());
385
TGDuration duration = manager.getFactory().newDuration();
386
caret.getDuration().copy(duration);
388
manager.getMeasureManager().addNote(caret.getMeasure(),caret.getPosition(),note,duration);
391
TuxGuitar.instance().getUndoableManager().addEdit(undoable.endUndo());
392
TuxGuitar.instance().getFileHistory().setUnsavedFile();
394
//reprodusco las notas en el pulso
395
caret.getSelectedBeat().play();
404
protected void afterAction() {
405
int measure = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getMeasure().getNumber();
406
TuxGuitar.instance().getTablatureEditor().getTablature().getViewLayout().fireUpdate(measure);
407
TuxGuitar.instance().updateCache(true);
410
public boolean hasChanges(){
414
public void setChanges(boolean changes){
415
this.changes = changes;
418
protected void updateEditor(){
421
this.image.dispose();
422
this.image = makePianoImage();
424
if(TuxGuitar.instance().getPlayer().isRunning()){
425
this.beat = TuxGuitar.instance().getEditorCache().getPlayBeat();
427
this.beat = TuxGuitar.instance().getEditorCache().getEditBeat();
432
public void redraw() {
433
if(!super.isDisposed() && !TuxGuitar.instance().isLocked()){
435
this.pianoComposite.redraw();
436
this.loadDurationImage(false);
440
public void redrawPlayingMode(){
441
if(!super.isDisposed() && !TuxGuitar.instance().isLocked()){
442
this.pianoComposite.redraw();
446
public void dispose(){
448
this.image.dispose();
449
this.config.dispose();
452
public void loadProperties(){
453
this.scale.setText(TuxGuitar.getProperty("scale"));
454
this.settings.setToolTipText(TuxGuitar.getProperty("settings"));
455
this.layout(true,true);
458
public void loadIcons(){
459
this.getShell().setImage(TuxGuitar.instance().getIconManager().getAppIcon());
460
this.settings.setImage(TuxGuitar.instance().getIconManager().getSettings());
461
this.loadDurationImage(true);
462
this.layout(true,true);
465
protected void configure(){
466
this.config.configure(getShell());
467
this.setChanges(true);
471
public Composite getPianoComposite() {
472
return this.pianoComposite;
475
private class PianoListener implements PaintListener,MouseListener {
477
public PianoListener(){
481
public void paintControl(PaintEvent e) {
482
if(!TuxGuitar.instance().isLocked()){
483
TuxGuitar.instance().lock();
486
TGPainter painter = new TGPainter(e.gc);
487
painter.drawImage(Piano.this.image,0,0);
490
if(Piano.this.beat != null){
491
Iterator it = Piano.this.beat.getNotes().iterator();
493
TGNoteImpl note = (TGNoteImpl)it.next();
494
paintNote(painter,note.getRealValue());
497
TuxGuitar.instance().unlock();
501
public void mouseUp(MouseEvent e) {
502
getPianoComposite().setFocus();
504
if(!TuxGuitar.instance().getPlayer().isRunning() && !TuxGuitar.instance().isLocked() && !ActionLock.isLocked()){
511
TuxGuitar.instance().getAction(GoRightAction.NAME).process(e);
515
public void mouseDoubleClick(MouseEvent e) {
519
public void mouseDown(MouseEvent e) {