2
* Created on 28-dic-2005
4
* TODO To change the template for this generated file go to
5
* Window - Preferences - Java - Code Style - Code Templates
7
package org.herac.tuxguitar.gui.editors.fretboard;
9
import java.util.ArrayList;
10
import java.util.Iterator;
11
import java.util.List;
13
import org.eclipse.swt.SWT;
14
import org.eclipse.swt.events.MouseEvent;
15
import org.eclipse.swt.events.MouseListener;
16
import org.eclipse.swt.events.PaintEvent;
17
import org.eclipse.swt.events.PaintListener;
18
import org.eclipse.swt.events.SelectionAdapter;
19
import org.eclipse.swt.events.SelectionEvent;
20
import org.eclipse.swt.graphics.Color;
21
import org.eclipse.swt.graphics.Font;
22
import org.eclipse.swt.graphics.FontData;
23
import org.eclipse.swt.graphics.GC;
24
import org.eclipse.swt.graphics.Image;
25
import org.eclipse.swt.graphics.Point;
26
import org.eclipse.swt.layout.FormAttachment;
27
import org.eclipse.swt.layout.FormData;
28
import org.eclipse.swt.layout.FormLayout;
29
import org.eclipse.swt.layout.GridData;
30
import org.eclipse.swt.layout.GridLayout;
31
import org.eclipse.swt.widgets.Button;
32
import org.eclipse.swt.widgets.Combo;
33
import org.eclipse.swt.widgets.Composite;
34
import org.eclipse.swt.widgets.Label;
35
import org.herac.tuxguitar.gui.SystemImages;
36
import org.herac.tuxguitar.gui.TuxGuitar;
37
import org.herac.tuxguitar.gui.actions.caret.GoLeftAction;
38
import org.herac.tuxguitar.gui.actions.caret.GoRightAction;
39
import org.herac.tuxguitar.gui.actions.duration.DecrementDurationAction;
40
import org.herac.tuxguitar.gui.actions.duration.IncrementDurationAction;
41
import org.herac.tuxguitar.gui.actions.tools.SelectScaleAction;
42
import org.herac.tuxguitar.gui.editors.TablatureEditor;
43
import org.herac.tuxguitar.gui.editors.tab.Caret;
44
import org.herac.tuxguitar.gui.editors.tab.MeasureComponent;
45
import org.herac.tuxguitar.gui.editors.tab.NoteCoords;
46
import org.herac.tuxguitar.gui.system.config.ConfigKeys;
47
import org.herac.tuxguitar.gui.undo.undoables.measure.UndoableMeasureGeneric;
48
import org.herac.tuxguitar.song.managers.SongManager;
49
import org.herac.tuxguitar.song.models.Duration;
50
import org.herac.tuxguitar.song.models.InstrumentString;
51
import org.herac.tuxguitar.song.models.Note;
52
import org.herac.tuxguitar.song.models.NoteEffect;
53
import org.herac.tuxguitar.song.models.SongTrack;
58
* TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
60
public class FretBoard extends Composite {
61
public static final int MAX_FRETS = 24;
63
public static final int TOP_SPAN = 10;
65
public static final int BOTTOM_SPAN = 10;
67
private static final int STRING_SPAN = TuxGuitar.instance().getConfig().getIntConfigValue(ConfigKeys.FRETBOARD_STRING_SPAN);
69
private static final Color COLOR_BACKGROUND = new Color(TuxGuitar.instance().getDisplay(),255, 255, 255);
71
private static final Color COLOR_STRING = new Color(TuxGuitar.instance().getDisplay(),227,217,217);
73
private static final String[] NOTE_NAMES = new String[]{"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
75
private TablatureEditor editor;
77
private FretBoardListener listener;
79
private Composite toolComposite;
81
private Composite fretBoardComposite;
83
private Label durationLabel;
85
private Combo handSelector;
89
private Image fretBoard;
91
private List components;
95
private int[] strings;
99
private boolean changes;
101
private Point lastSize;
103
public FretBoard(Composite parent, TablatureEditor editor) {
104
super(parent, SWT.NONE);
105
this.setLayout(new FormLayout());
106
this.components = new ArrayList();
107
this.listener = new FretBoardListener();
108
this.editor = editor;
111
this.layout(getDisplay().getBounds().width,1);
114
private void initToolBar() {
115
FormData data = new FormData();
116
data.left = new FormAttachment(0, 0);
117
data.right = new FormAttachment(100, 0);
118
data.top = new FormAttachment(0,0);
120
GridLayout layout = new GridLayout();
121
layout.makeColumnsEqualWidth = false;
122
layout.numColumns = 0;
124
layout.marginWidth = 0;
126
toolComposite = new Composite(this, SWT.NONE);
129
layout.numColumns ++;
130
Button goLeft = new Button(toolComposite, SWT.ARROW | SWT.LEFT);
131
goLeft.addSelectionListener(TuxGuitar.instance().getAction(GoLeftAction.NAME));
133
layout.numColumns ++;
134
Button goRight = new Button(toolComposite, SWT.ARROW | SWT.RIGHT);
135
goRight.addSelectionListener(TuxGuitar.instance().getAction(GoRightAction.NAME));
138
layout.numColumns ++;
139
makeToolSeparator(toolComposite);
142
layout.numColumns ++;
143
Button decrement = new Button(toolComposite, SWT.ARROW | SWT.MIN);
144
decrement.addSelectionListener(TuxGuitar.instance().getAction(DecrementDurationAction.NAME));
146
layout.numColumns ++;
147
durationLabel = new Label(toolComposite, SWT.BORDER);
148
durationLabel.setImage(getDurationImage());
150
layout.numColumns ++;
151
Button increment = new Button(toolComposite, SWT.ARROW | SWT.MAX);
152
increment.addSelectionListener(TuxGuitar.instance().getAction(IncrementDurationAction.NAME));
155
layout.numColumns ++;
156
makeToolSeparator(toolComposite);
159
layout.numColumns ++;
160
handSelector = new Combo(toolComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
161
handSelector.add(TuxGuitar.getProperty("fretboard.right-mode"));
162
handSelector.add(TuxGuitar.getProperty("fretboard.left-mode"));
163
handSelector.select(0);
164
handSelector.addSelectionListener(new SelectionAdapter() {
165
public void widgetSelected(SelectionEvent e) {
166
int index = handSelector.getSelectionIndex();
173
fretBoardComposite.redraw();
178
layout.numColumns ++;
179
makeToolSeparator(toolComposite);
182
layout.numColumns ++;
183
scale = new Button(toolComposite, SWT.PUSH);
184
scale.setText(TuxGuitar.getProperty("scale"));
185
scale.addSelectionListener(TuxGuitar.instance().getAction(SelectScaleAction.NAME));
187
toolComposite.setLayoutData(data);
188
toolComposite.setLayout(layout);
191
private void makeToolSeparator(Composite parent){
192
Label separator = new Label(parent,SWT.SEPARATOR);
193
separator.setLayoutData(new GridData(20,20));
196
private void initEditor() {
197
this.lastSize = new Point(0,0);
199
FormData data = new FormData();
200
data.left = new FormAttachment(0, 0);
201
data.right = new FormAttachment(100, 0);
202
data.top = new FormAttachment(toolComposite,0);
203
data.bottom = new FormAttachment(100, 0);
205
this.fretBoardComposite = new Composite(this, SWT.BORDER | SWT.DOUBLE_BUFFERED);
206
this.fretBoardComposite.setLayoutData(data);
207
this.fretBoardComposite.setBackground(COLOR_BACKGROUND);
208
this.fretBoardComposite.addMouseListener(this.listener);
209
this.fretBoardComposite.addPaintListener(this.listener);
212
private Image getDurationImage() {
213
Duration duration = (Duration) editor.getTablature().getCaret().getDuration().clone();
214
return SystemImages.getDuration(duration.getValue());
217
private void calculateFretSpan(int width) {
218
this.fretSpan = (width / MAX_FRETS);
220
for (int i = 0; i < MAX_FRETS; i++) {
223
this.fretSpan += (aux / MAX_FRETS) + 2;
226
private void disposeFretBoardImage(){
227
if(this.fretBoard != null && !this.fretBoard.isDisposed()){
228
this.fretBoard.dispose();
232
private void initFrets(int fromX, int hand) {
233
this.frets = new int[MAX_FRETS];
236
for (int i = 0; i < this.frets.length; i++) {
237
this.frets[i] = nextX;
238
nextX += (this.fretSpan - ((i + 1) * 2));
240
} else if (hand == 2) {
241
for (int i = this.frets.length - 1; i >= 0; i--) {
242
this.frets[i] = nextX;
243
nextX += (this.fretSpan - (i * 2));
248
private void initStrings(int count) {
249
int fromY = TOP_SPAN;
250
this.strings = new int[count];
252
for (int i = 0; i < this.strings.length; i++) {
253
this.strings[i] = fromY + (STRING_SPAN * i);
257
private void updateEditor(){
259
SongManager manager = TuxGuitar.instance().getSongManager();
260
if(TuxGuitar.instance().getPlayer().isRunning()){
261
this.components = TuxGuitar.instance().getEditorCache().getPlayingComponents();
263
this.components = TuxGuitar.instance().getEditorCache().getCaretComponents();
266
if (this.strings.length != getStringCount()) {
267
disposeFretBoardImage();
268
initStrings(getStringCount());
269
//Fuerzo a cambiar el ancho
273
int clientWidth = getClientArea().width;
274
int clientHeight = getClientArea().height;
276
if(lastSize.x != clientWidth || hasChanges()){
277
this.layout(getClientArea().width,this.handSelector.getSelectionIndex() + 1);
280
if(lastSize.y != clientHeight){
281
TuxGuitar.instance().getFretBoardEditor().showFretBoard();
283
this.lastSize.x = clientWidth;
284
this.lastSize.y = clientHeight;
288
private void paintFretBoard(GC gc){
289
if(this.fretBoard == null || this.fretBoard.isDisposed()){
290
this.fretBoard = new Image(getDisplay(),getClientArea().width,((STRING_SPAN) * (this.strings.length - 1)) + TOP_SPAN + BOTTOM_SPAN);
292
GC imageGC = new GC(this.fretBoard);
295
imageGC.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
296
imageGC.fillRectangle(getClientArea());
299
// pinto las cegillas
300
Image fretImage = SystemImages.FRETBOARD_FRET_IMAGE;
301
Image firstFretImage = SystemImages.FRETBOARD_FIRST_FRET_IMAGE;
302
imageGC.drawImage(firstFretImage,0,0,firstFretImage.getBounds().width,firstFretImage.getBounds().height,frets[0] - 5,strings[0] - 5,firstFretImage.getBounds().width,strings[strings.length - 1] );
303
paintFretPoints(imageGC,0);
304
for (int i = 1; i < this.frets.length; i++) {
305
imageGC.drawImage(fretImage,0,0,fretImage.getBounds().width,fretImage.getBounds().height,frets[i],strings[0] - 5,fretImage.getBounds().width,strings[strings.length - 1] );
306
paintFretPoints(imageGC, i);
310
for (int i = 0; i < this.strings.length; i++) {
311
imageGC.setForeground(COLOR_STRING);
313
imageGC.setLineWidth(2);
315
imageGC.drawLine(frets[0], strings[i], frets[frets.length - 1], strings[i]);
322
gc.drawImage(this.fretBoard,0,0);
326
private void paintFretPoints(GC gc, int fretIndex) {
327
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
328
if ((fretIndex + 1) < this.frets.length) {
329
int fret = fretIndex + 1;
336
int size = getOvalSize();
337
int x = this.frets[fretIndex] + ((this.frets[fretIndex + 1] - this.frets[fretIndex]) / 2);
338
int y1 = this.strings[0] + ((this.strings[this.strings.length - 1] - this.strings[0]) / 2) - STRING_SPAN;
339
int y2 = this.strings[0] + ((this.strings[this.strings.length - 1] - this.strings[0]) / 2) + STRING_SPAN;
340
gc.fillOval(x - (size / 2), y1 - (size / 2), size, size);
341
gc.fillOval(x - (size / 2), y2 - (size / 2), size, size);
343
} else if (fret == 3 || fret == 5 || fret == 7 || fret == 9) {
345
int size = getOvalSize();
346
int x = this.frets[fretIndex] + ((this.frets[fretIndex + 1] - this.frets[fretIndex]) / 2);
347
int y = this.strings[0] + ((this.strings[this.strings.length - 1] - this.strings[0]) / 2);
348
gc.fillOval(x - (size / 2),y - (size / 2),size, size);
357
private void paintScale(GC gc) {
358
SongTrack track = editor.getTablature().getCaret().getSongTrackCoords().getTrack();
360
Font font = new Font(getDisplay(),new FontData("Sans",8,SWT.BOLD));
362
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
363
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_RED));
366
for (int i = 0; i < this.strings.length; i++) {
367
InstrumentString string = track.getString(i + 1);
368
for (int j = 0; j < this.frets.length; j++) {
370
int noteIndex = ((string.getValue() + j) % 12 );
371
if(TuxGuitar.instance().getScaleManager().getScale().getNote(noteIndex)){
372
String s = NOTE_NAMES[noteIndex];
373
Point size = gc.stringExtent(s);
375
int x = this.frets[j];
377
x -= ((x - this.frets[j - 1]) / 2);
380
int y = this.strings[i];
382
gc.fillRectangle(x - (size.x / 2),y - (size.y / 2),size.x, size.y);
383
gc.drawString(s,x - (size.x / 2),y - (size.y / 2),true);
391
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
396
private void paintComponents(GC gc) {
397
int size = getOvalSize();
398
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLUE));
400
Iterator it = this.components.iterator();
401
while (it.hasNext()) {
402
MeasureComponent component = (MeasureComponent) it.next();
403
if (component instanceof NoteCoords) {
404
NoteCoords note = (NoteCoords) component;
405
int fretIndex = note.getNote().getValue();
406
int stringIndex = note.getNote().getString() - 1;
407
if (fretIndex >= 0 && fretIndex < this.frets.length && stringIndex >= 0 && stringIndex < this.strings.length) {
408
int x = this.frets[fretIndex];
410
x -= ((this.frets[fretIndex] - this.frets[fretIndex - 1]) / 2);
412
int y = this.strings[stringIndex];
413
gc.fillOval(x - (size / 2),y - (size / 2),size, size);
418
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
421
private void paintEditor(GC gc) {
423
if (this.frets.length > 0 && this.strings.length > 0) {
430
private void hit(int x, int y) {
431
int fretIndex = getFretIndex(x);
432
int stringIndex = getStringIndex(y);
434
editor.getTablature().getCaret().setStringNumber(stringIndex + 1);
435
if (!removeNote(fretIndex, stringIndex + 1)) {
436
addNote(fretIndex, stringIndex + 1);
440
private int getStringIndex(int y) {
442
for (int i = 0; i < this.strings.length; i++) {
446
int distanceY = Math.abs(y - this.strings[index]);
447
int currDistanceY = Math.abs(y - this.strings[i]);
448
if (currDistanceY < distanceY) {
456
private int getFretIndex(int x) {
457
int length = this.frets.length;
458
if ((x - 10) <= frets[0] && frets[0] < frets[length - 1]) {
461
if ((x + 10) >= frets[0] && frets[0] > frets[length - 1]) {
465
for (int i = 0; i < length; i++) {
466
if ((i + 1) < length) {
467
if (x > frets[i] && x <= frets[i + 1] || x > frets[i + 1] && x <= frets[i]) {
475
private boolean removeNote(int fret, int string) {
476
Iterator it = this.components.iterator();
477
while (it.hasNext()) {
478
MeasureComponent component = (MeasureComponent) it.next();
479
if (component instanceof NoteCoords) {
480
Note note = ((NoteCoords) component).getNote();
481
if (note.getValue() == fret && note.getString() == string) {
482
//comienza el undoable
483
UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
485
Caret caret = this.editor.getTablature().getCaret();
486
SongManager manager = TuxGuitar.instance().getSongManager();
487
manager.getMeasureManager().removeNote(caret.getMeasureCoords().getMeasure(),note);
490
editor.getUndoManager().addEdit(undoable.endUndo());
499
private int getStringCount() {
500
return editor.getTablature().getCaret().getSongTrackCoords().getTrack().getStrings().size();
503
private int getOvalSize(){
504
return ((STRING_SPAN / 2) + (STRING_SPAN / 10));
507
private void addNote(int fret, int string) {
508
//comienza el undoable
509
UndoableMeasureGeneric undoable = UndoableMeasureGeneric.startUndo();
511
Caret caret = this.editor.getTablature().getCaret();
512
Duration duration = (Duration) caret.getDuration().clone();
513
Note note = new Note(fret, caret.getPosition(), duration, caret.getVelocity(), string, false, new NoteEffect());
515
SongManager manager = TuxGuitar.instance().getSongManager();
516
manager.getMeasureManager().addNote(caret.getMeasureCoords().getMeasure(),note);
519
editor.getUndoManager().addEdit(undoable.endUndo());
521
//reprodusco las notas en el pulso
522
caret.getMeasureCoords().playBeat(note.getStart());
525
private void afterAction() {
526
this.editor.getTablature().getViewLayout().fireUpdate(this.editor.getTablature().getCaret().getMeasureCoords().getMeasure().getNumber(), false);
527
TuxGuitar.instance().redraw();
528
TuxGuitar.instance().updateCache(true);
531
public boolean hasChanges(){
535
public void setChanges(boolean changes){
536
this.changes = changes;
539
public void redraw() {
540
if(!super.isDisposed()){
542
this.fretBoardComposite.redraw();
543
this.durationLabel.setImage(getDurationImage());
547
public void redrawPlayingMode(){
548
if(!super.isDisposed()){
549
this.fretBoardComposite.redraw();
553
public void dispose(){
555
this.disposeFretBoardImage();
558
public void loadProperties(){
559
int selection = this.handSelector.getSelectionIndex();
560
this.handSelector.removeAll();
561
this.handSelector.add(TuxGuitar.getProperty("fretboard.right-mode"));
562
this.handSelector.add(TuxGuitar.getProperty("fretboard.left-mode"));
563
this.handSelector.select(selection);
564
this.scale.setText(TuxGuitar.getProperty("scale"));
568
public int getHeight(){
569
int borderWidth = (2 * this.fretBoardComposite.getBorderWidth());
570
int toolBarHeight = (this.toolComposite.getBounds().height);
571
int fretBoardHeight = (((STRING_SPAN) * (this.strings.length - 1)) + TOP_SPAN + BOTTOM_SPAN);
572
return (borderWidth + toolBarHeight + fretBoardHeight);
575
public int getWidth(){
576
return this.frets[this.frets.length - 1];
579
public void layout(){
583
public void layout(int width,int hand){
584
this.disposeFretBoardImage();
585
this.calculateFretSpan(width);
586
this.initFrets(10,hand);
587
this.initStrings(getStringCount());
588
this.setChanges(false);
591
public static void disposeColors(){
592
COLOR_BACKGROUND.dispose();
593
COLOR_STRING.dispose();
598
private class FretBoardListener implements PaintListener,MouseListener {
600
public void paintControl(PaintEvent e) {
605
public void mouseUp(MouseEvent e) {
610
TuxGuitar.instance().getAction(GoRightAction.NAME).process(e);
614
public void mouseDoubleClick(MouseEvent e) {
617
public void mouseDown(MouseEvent e) {