1
package org.herac.tuxguitar.gui.table;
3
import java.util.ArrayList;
4
import java.util.Iterator;
7
import org.eclipse.swt.SWT;
8
import org.eclipse.swt.custom.CLabel;
9
import org.eclipse.swt.custom.SashForm;
10
import org.eclipse.swt.custom.ScrolledComposite;
11
import org.eclipse.swt.events.MouseAdapter;
12
import org.eclipse.swt.events.MouseEvent;
13
import org.eclipse.swt.events.PaintEvent;
14
import org.eclipse.swt.events.PaintListener;
15
import org.eclipse.swt.events.SelectionAdapter;
16
import org.eclipse.swt.events.SelectionEvent;
17
import org.eclipse.swt.graphics.Color;
18
import org.eclipse.swt.graphics.GC;
19
import org.eclipse.swt.graphics.Rectangle;
20
import org.eclipse.swt.layout.FillLayout;
21
import org.eclipse.swt.layout.GridData;
22
import org.eclipse.swt.layout.GridLayout;
23
import org.eclipse.swt.widgets.Button;
24
import org.eclipse.swt.widgets.Canvas;
25
import org.eclipse.swt.widgets.Combo;
26
import org.eclipse.swt.widgets.Composite;
27
import org.eclipse.swt.widgets.Control;
28
import org.eclipse.swt.widgets.Event;
29
import org.eclipse.swt.widgets.Listener;
30
import org.eclipse.swt.widgets.ScrollBar;
31
import org.herac.tuxguitar.gui.TuxGuitar;
32
import org.herac.tuxguitar.gui.actions.composition.ChangeInfoAction;
33
import org.herac.tuxguitar.gui.actions.track.ChangeTrackPropertiesAction;
34
import org.herac.tuxguitar.gui.actions.track.GoToTrackAction;
35
import org.herac.tuxguitar.gui.editors.TablatureEditor;
36
import org.herac.tuxguitar.gui.editors.tab.MeasureCoords;
37
import org.herac.tuxguitar.gui.editors.tab.SongTrackCoords;
38
import org.herac.tuxguitar.song.models.SongChannel;
39
import org.herac.tuxguitar.song.models.SongTrack;
40
import org.herac.tuxguitar.song.models.RGBColor;
43
public class SongTableInfo extends Composite{
44
private static final int TABLE_COLUMN_NUMBER = 0;
45
private static final int TABLE_COLUMN_NAME = 1;
46
private static final int TABLE_COLUMN_INSTRUMENT = 2;
47
private static final int TABLE_COLUMN_CHANNEL = 3;
48
private static final int TABLE_COLUMN_EFFECT_CHANNEL = 4;
50
private static final Color[] BACKGROUNDS = new Color[]{
51
new Color(TuxGuitar.instance().getDisplay(),255,255,255),
52
new Color(TuxGuitar.instance().getDisplay(),238,238,238),
53
new Color(TuxGuitar.instance().getDisplay(),192,192,192)
56
private TablatureEditor editor;
57
private ScrollBar hSroll;
58
private ScrolledComposite scrolledComposite;
59
private SongTable table;
60
private Composite trackMeasures;
61
private Button trackMeasuresHeader;
62
private Canvas painter;
63
private int measureLength;
65
private long lastTrackSelection;
66
private MeasureCoords lasPlayedMeasure;
68
public SongTableInfo(Composite parent,TablatureEditor editor) {
69
super(parent,SWT.H_SCROLL | SWT.BORDER);
70
this.setLayout(new FillLayout());
74
this.hSroll = getHorizontalBar();
75
this.hSroll.addListener(SWT.Selection, new Listener() {
76
public void handleEvent(Event e) {
85
this.scrolledComposite = new ScrolledComposite(this,SWT.V_SCROLL);
86
GridLayout layout = new GridLayout();
88
layout.marginBottom = 0;
89
layout.marginLeft = 0;
90
layout.marginRight = 0;
91
layout.marginHeight = 0;
92
layout.marginWidth = 0;
93
layout.horizontalSpacing = 0;
94
layout.verticalSpacing = 0;
95
scrolledComposite.setLayout(layout);
97
SashForm sashForm = new SashForm(this.scrolledComposite, SWT.HORIZONTAL);
98
sashForm.SASH_WIDTH = 2;
101
initTrackMeasures(sashForm);
103
this.scrolledComposite.setContent(sashForm);
104
this.scrolledComposite.setExpandHorizontal(true);
105
this.scrolledComposite.setExpandVertical(true);
108
private void initTable(Composite parent){
109
this.table = new SongTable(parent,5,editor);
110
this.loadProperties();
112
this.table.setWeights(new int[] { 1,7,5,3,2});
119
private void initTrackMeasures(Composite parent){
120
Composite composite = new Composite(parent,SWT.NONE);
121
composite.setLayout(new FillLayout(SWT.VERTICAL));
123
this.trackMeasures = new Composite(composite,SWT.NONE);
124
GridLayout layout = new GridLayout();
125
layout.marginTop = 0;
126
layout.marginBottom = 0;
127
layout.marginLeft = 0;
128
layout.marginRight = 0;
129
layout.marginHeight = 0;
130
layout.marginWidth = 0;
131
layout.horizontalSpacing = 0;
132
layout.verticalSpacing = 0;
133
this.trackMeasures.setLayout(layout);
134
this.trackMeasuresHeader = new Button(this.trackMeasures,SWT.PUSH);
135
this.trackMeasuresHeader.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,false,0,0));
137
this.trackMeasuresHeader.addMouseListener(new MouseAdapter() {
138
public void mouseDoubleClick(MouseEvent e) {
139
TuxGuitar.instance().getAction(ChangeInfoAction.NAME).process(e);
144
this.painter = new Canvas(this.trackMeasures,SWT.DOUBLE_BUFFERED);
145
this.painter.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,0,0));
146
this.painter.addPaintListener(new PaintListener() {
147
public void paintControl(PaintEvent e) {
148
updateTrackMeasuresHeader();
149
paintMeasures(e.gc,-hSroll.getSelection(),0);
154
this.painter.addMouseListener(new MouseAdapter() {
155
public void mouseDown(MouseEvent e) {
156
int trackIndex = getSelectedTrackIndex(e.y);
158
SongTrackCoords track = (SongTrackCoords)editor.getTablature().getSongCoords().getTrackCoords().get(trackIndex);
159
int measureIndex = getSelectedMeasureIndex(track,e.x);
161
if(measureIndex >= 0){
162
MeasureCoords measure = (MeasureCoords)track.getMeasuresCoords().get(measureIndex);
163
editor.getTablature().getCaret().moveTo(track,measure,measure.getFirstComponent(),1);
164
//editor.getTablature().getCaret().update(track.getTrack().getNumber(),measure.getMeasure().getStart(),1);
165
//editor.getTablature().getCaret().setChanges(true);
166
//TuxGuitar.instance().getTransport().gotoMeasure(measure.getMeasure());
167
TuxGuitar.instance().redraw();
177
private void updateTable(){
178
List tracks = this.editor.getTablature().getSongCoords().getTrackCoords();
179
int length = tracks.size();
181
this.table.clearColumnsAfter(length);
182
this.makeTableItems(length);
184
for(int i = 0;i < tracks.size();i++){
185
final SongTrackCoords track = (SongTrackCoords)tracks.get(i);
186
String number = Long.toString(track.getTrack().getNumber());
187
String name = track.getTrack().getName();
188
String instrument = "";
189
if(track.getTrack().isPercussionTrack()){
190
instrument = TuxGuitar.getProperty("track.name.default-percussion-name");
192
instrument = TuxGuitar.instance().getPlayer().getInstrumentName(track.getTrack().getChannel().getInstrument());
194
updateTableItems(i,new String[] {number,name,instrument},track);
196
this.updateItemBackgrounds();
201
private void makeTableItems(int count){
202
GridData gridData = new GridData(SWT.FILL,SWT.FILL,true,true,0,0);
203
gridData.heightHint = 22;
205
int currentItems = table.getColumn(TABLE_COLUMN_NUMBER).getItemCount();
206
for(int i = currentItems;i < count;i ++){
207
final int trackIndex = i;
209
CLabel item = new CLabel(table.getColumn(TABLE_COLUMN_NUMBER),SWT.LEFT);
210
item.setLayoutData(gridData);
211
item.addMouseListener(new ItemSelectionListener());
213
item = new CLabel(table.getColumn(TABLE_COLUMN_NAME),SWT.LEFT);
214
item.setLayoutData(gridData);
215
item.addMouseListener(new ItemSelectionListener());
217
item = new CLabel(table.getColumn(TABLE_COLUMN_INSTRUMENT),SWT.LEFT);
218
item.setLayoutData(gridData);
219
item.addMouseListener(new ItemSelectionListener());
222
final Combo channelCombo = new Combo(table.getColumn(TABLE_COLUMN_CHANNEL),SWT.DROP_DOWN | SWT.READ_ONLY);
223
channelCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
224
channelCombo.setData(new ChannelList());
225
updateChannelCombo(channelCombo,(ChannelList)channelCombo.getData(),trackIndex);
227
final Combo effectChannelCombo = new Combo(table.getColumn(TABLE_COLUMN_EFFECT_CHANNEL),SWT.DROP_DOWN | SWT.READ_ONLY);
228
effectChannelCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
229
effectChannelCombo.setData(new ChannelList());
230
updateEffectChannelCombo(effectChannelCombo,(ChannelList)effectChannelCombo.getData(),trackIndex);
233
channelCombo.addSelectionListener(new SelectionAdapter() {
234
public void widgetSelected(SelectionEvent e) {
236
if(e.widget.getData() instanceof ChannelList){
237
SongChannel channel = ((SongTrack)TuxGuitar.instance().getSongManager().getSong().getTracks().get(trackIndex)).getChannel();
238
boolean[] usedChannels = TuxGuitar.instance().getSongManager().getUsedChannels();
239
boolean[] usedEffectChannels = TuxGuitar.instance().getSongManager().getUsedEffectChannels();
240
ChannelList channelItems = (ChannelList)e.widget.getData();
241
int idx = channelItems.getChannel(channelCombo.getSelectionIndex());
242
if(!usedChannels[idx]){
243
channel.setChannel((short)idx);
244
channel.setEffectChannel(channel.getChannel());
246
SongChannel tempChannel = TuxGuitar.instance().getSongManager().getUsedChannel(idx);
247
channel.setChannel(tempChannel.getChannel());
248
channel.setEffectChannel(tempChannel.getEffectChannel());
249
channel.setVolume(tempChannel.getVolume());
250
channel.setBalance(tempChannel.getBalance());
251
channel.setChorus(tempChannel.getChorus());
252
channel.setInstrument(tempChannel.getInstrument());
253
channel.setPhaser(tempChannel.getPhaser());
254
channel.setReverb(tempChannel.getReverb());
255
channel.setTremolo(tempChannel.getTremolo());
256
channel.setSolo(tempChannel.isSolo());
257
channel.setMute(tempChannel.isMute());
259
fireChannelChange(channel);
261
TuxGuitar.instance().getMixer().update();
266
effectChannelCombo.addSelectionListener(new SelectionAdapter() {
267
public void widgetSelected(SelectionEvent e) {
268
if(e.widget.getData() instanceof ChannelList){
269
SongChannel channel = ((SongTrack)TuxGuitar.instance().getSongManager().getSong().getTracks().get(trackIndex)).getChannel();
270
ChannelList effectChannelItems = (ChannelList)e.widget.getData();
271
int idx = effectChannelItems.getChannel(effectChannelCombo.getSelectionIndex());
272
channel.setEffectChannel((short)idx);
273
fireChannelChange(channel);
275
TuxGuitar.instance().getMixer().update();
282
List tracks = TuxGuitar.instance().getSongManager().getSong().getTracks();
283
for(int i = 0;i < tracks.size();i++){
284
Combo channelCombo = (Combo)this.table.getColumn(TABLE_COLUMN_CHANNEL).getItem(i);
285
Combo effectChannelCombo = (Combo)this.table.getColumn(TABLE_COLUMN_EFFECT_CHANNEL).getItem(i);
287
updateChannelCombo(channelCombo,(ChannelList)channelCombo.getData(),i);
288
updateEffectChannelCombo(effectChannelCombo,(ChannelList)effectChannelCombo.getData(),i);
293
private void updateItemBackgrounds(){
294
this.lastTrackSelection = this.editor.getTablature().getCaret().getSongTrackCoords().getTrack().getNumber();
296
int currentItems = table.getColumn(TABLE_COLUMN_NUMBER).getItemCount();
297
for(int i = 0;i < currentItems;i ++){
298
CLabel item = (CLabel)table.getColumn(TABLE_COLUMN_NUMBER).getItem(i);
299
Color background = BACKGROUNDS[(i % 2)];
300
int trackNumber = Integer.parseInt(item.getText());
301
if(trackNumber == lastTrackSelection){
302
background = BACKGROUNDS[2];
304
item.setBackground(background);
306
item = (CLabel)table.getColumn(TABLE_COLUMN_NAME).getItem(i);
307
item.setBackground(background);
309
item = (CLabel)table.getColumn(TABLE_COLUMN_INSTRUMENT).getItem(i);
310
item.setBackground(background);
314
private void updateTableItems(int index,String[] texts,Object data){
315
for(int i = 0;i < texts.length;i ++){
316
CLabel item = (CLabel)table.getColumn(i).getItem(index);
318
item.setText(texts[i]);
322
private void updateTrackMeasuresHeader(){
323
((GridData)this.trackMeasuresHeader.getLayoutData()).heightHint = table.getHeaderHeight();
324
this.trackMeasuresHeader.setText(this.editor.getSongManager().getSong().getName());
327
private void paintMeasures(GC gc,int fromX,int fromY){
328
int width = this.trackMeasures.getBounds().width;
329
int itemSpan = getItemSpan();
333
int firstTableItemY = 0;
335
boolean playing = TuxGuitar.instance().getPlayer().isRunning();
336
this.lasPlayedMeasure = null;
337
List tracks = this.editor.getTablature().getSongCoords().getTrackCoords();
338
int trackLength = tracks.size();
339
for(int i = 0;i < trackLength;i++){
340
SongTrackCoords track = (SongTrackCoords)tracks.get(i);
342
//Calculo el Y acorde a la tabla
343
Control control = table.getColumn(TABLE_COLUMN_NUMBER).getItem(i);
344
Rectangle controlBounds = control.getBounds();
346
firstTableItemY = controlBounds.y;
348
y = fromY + (controlBounds.y - firstTableItemY);
350
//gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
351
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
352
gc.fillRectangle(0,y,width,itemSpan - 1);
354
RGBColor rgb = track.getTrack().getColor();
355
Color trackColor = new Color(getDisplay(),rgb.getR(),rgb.getG(),rgb.getB());
356
gc.setBackground(trackColor);
357
gc.setForeground(trackColor);
359
List measures = track.getMeasuresCoords();
360
this.measureLength = measures.size();
361
for(int j = 0;j < measureLength;j++){
362
MeasureCoords measure = (MeasureCoords)measures.get(j);
363
if(measure.getMeasure().getNotes().isEmpty()){
364
gc.drawRectangle(x,y,itemSpan -2 ,itemSpan - 2);
366
gc.fillRectangle(x,y,itemSpan - 1,itemSpan - 1);
369
if(measure.getMeasure().hasMarker()){
370
RGBColor markerRGB = measure.getMeasure().getMarker().getColor();
371
Color markerColor = new Color(getDisplay(),markerRGB.getR(),markerRGB.getG(),markerRGB.getB());
372
gc.setBackground(markerColor);
373
gc.fillRectangle(x,y,4,4);
374
gc.setBackground(trackColor);
375
markerColor.dispose();
378
boolean hasCaret = TuxGuitar.instance().getTablatureEditor().getTablature().getCaret().getMeasureCoords().equals(measure);
379
if((playing && measure.isPlaying()) || (!playing && hasCaret/*measure.hasCaret()*/)){
380
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
381
gc.fillRectangle(x + 4,y + 4,itemSpan - 9,itemSpan - 9);
382
gc.setBackground(trackColor);
383
this.lasPlayedMeasure = measure;
391
trackColor.dispose();
393
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
395
this.trackMeasures.layout();
398
private int getItemSpan(){
399
return table.getColumn(TABLE_COLUMN_NUMBER).getItemHeight();
402
private int getSelectedTrackIndex(int y){
403
int itemSpan = getItemSpan();
404
List tracks = editor.getTablature().getSongCoords().getTrackCoords();
405
int trackLength = tracks.size();
407
for(int i = 0;i < trackLength;i++){
408
if(y >= trackY && y < (trackY + itemSpan)){
416
private int getSelectedMeasureIndex(SongTrackCoords track,int x){
417
int itemSpan = getItemSpan();
418
List measures = track.getMeasuresCoords();
419
int measureLength = measures.size();
420
int measureX = -hSroll.getSelection();;
421
for(int i = 0;i < measureLength;i++){
422
if(x >= measureX && x < (measureX + itemSpan)){
425
measureX += itemSpan;
430
public void updateScrolls(){
431
int itemSpan = getItemSpan();
432
this.scrolledComposite.setMinSize(0, itemSpan + itemSpan * table.getItemCount() + 10);
434
int width = (editor.getTablature().getCaret().getSongTrackCoords().getMeasuresCoords().size() * itemSpan);
435
this.hSroll.setMaximum(width);
436
this.hSroll.setThumb(Math.min(width ,this.painter.getClientArea().width));
438
this.hSroll.setVisible(width > this.painter.getClientArea().width);
442
public void loadProperties(){
444
this.table.getColumn(TABLE_COLUMN_NUMBER).setName(TuxGuitar.getProperty("track.number"));
445
this.table.getColumn(TABLE_COLUMN_NAME).setName(TuxGuitar.getProperty("track.name"));
446
this.table.getColumn(TABLE_COLUMN_INSTRUMENT).setName(TuxGuitar.getProperty("track.instrument"));
447
this.table.getColumn(TABLE_COLUMN_CHANNEL).setName(TuxGuitar.getProperty("track.channel.channel"));
448
this.table.getColumn(TABLE_COLUMN_EFFECT_CHANNEL).setName(TuxGuitar.getProperty("track.channel.effect-channel"));
451
public void fireUpdate(){
455
public int getHeight(){
456
return this.table.getBounds().height;
459
public void redraw(){
460
if(!super.isDisposed()){
461
if(editor.getTablature().getCaret().getSongTrackCoords().getTrack().getNumber() != lastTrackSelection){
462
updateItemBackgrounds();
470
public void redrawPlayingMode(){
471
if(!super.isDisposed()){
472
if(editor.getTablature().getCaret().getSongTrackCoords().getTrack().getNumber() != lastTrackSelection){
473
updateItemBackgrounds();
475
if(this.lasPlayedMeasure == null || !this.lasPlayedMeasure.isPlaying()){
482
private void updateChannelCombo(Combo channelCombo,ChannelList channelItems,int trackIndex){
483
channelCombo.removeAll();
484
channelItems.clear();
486
SongChannel channel = ((SongTrack)TuxGuitar.instance().getSongManager().getSong().getTracks().get(trackIndex)).getChannel();
488
boolean[] usedChannels = TuxGuitar.instance().getSongManager().getUsedChannels();
489
boolean[] usedEffectChannels = TuxGuitar.instance().getSongManager().getUsedEffectChannels();
490
if(channel.isPercusionChannel()){
491
channelCombo.add(Integer.toString(SongChannel.DEFAULT_PERCUSION_CHANNEL));
492
channelCombo.select(0);
493
channelItems.addChannel(0,0);
496
for(int i = 0;i < usedChannels.length;i++){
497
if(i != SongChannel.DEFAULT_PERCUSION_CHANNEL){
498
if(!usedEffectChannels[i] || (usedEffectChannels[i] && usedChannels[i]) || (channel.getChannel() == i && channel.getEffectChannel() == channel.getChannel())){
499
String itemName = new String();
500
if(usedChannels[i] && (channel.getChannel() != i || TuxGuitar.instance().getSongManager().countTracksForChannel(i) > 1)){
501
itemName = i + " " + TuxGuitar.getProperty("track.channel.link");
503
itemName = i + " " + TuxGuitar.getProperty("track.channel.free");
505
channelCombo.add(itemName);
507
if(i == channel.getChannel()){
508
channelCombo.select(itemIndex);
511
channelItems.addChannel(itemIndex,i);
520
private void updateEffectChannelCombo(Combo effectChannelCombo,ChannelList effectChannelItems,int trackIndex){
521
effectChannelCombo.removeAll();
522
effectChannelItems.clear();
524
SongChannel channel = ((SongTrack)TuxGuitar.instance().getSongManager().getSong().getTracks().get(trackIndex)).getChannel();
526
boolean[] usedChannels = TuxGuitar.instance().getSongManager().getUsedChannels();
527
boolean[] usedEffectChannels = TuxGuitar.instance().getSongManager().getUsedEffectChannels();
528
if(channel.isPercusionChannel()){
529
effectChannelCombo.add(Integer.toString(SongChannel.DEFAULT_PERCUSION_CHANNEL));
530
effectChannelCombo.select(0);
531
effectChannelItems.addChannel(0,0);
535
for(int i = 0;i < usedEffectChannels.length;i++){
536
if(i != SongChannel.DEFAULT_PERCUSION_CHANNEL){
537
if((!usedEffectChannels[i] || channel.getEffectChannel() == i) && (!usedChannels[i] || i == channel.getChannel())){
538
effectChannelCombo.add(Integer.toString(i));
540
if(i == channel.getEffectChannel()){
541
effectChannelCombo.select(itemIndex);
543
effectChannelItems.addChannel(itemIndex,i);
552
public void fireChannelChange(SongChannel channel){
553
List tracks = TuxGuitar.instance().getSongManager().getSong().getTracks();
554
for(int i = 0;i < tracks.size();i++){
555
SongTrack track = (SongTrack)tracks.get(i);
556
if(track.getChannel().getChannel() == channel.getChannel()){
557
track.getChannel().setEffectChannel(channel.getEffectChannel());
558
track.getChannel().setVolume(channel.getVolume());
559
track.getChannel().setBalance(channel.getBalance());
560
track.getChannel().setChorus(channel.getChorus());
561
track.getChannel().setReverb(channel.getReverb());
562
track.getChannel().setPhaser(channel.getPhaser());
563
track.getChannel().setTremolo(channel.getTremolo());
564
track.getChannel().setSolo(channel.isSolo());
565
track.getChannel().setMute(channel.isMute());
575
private class ItemSelectionListener extends MouseAdapter{
577
public void mouseDown(MouseEvent e) {
578
TuxGuitar.instance().getAction(GoToTrackAction.NAME).process(e);
581
public void mouseDoubleClick(MouseEvent e) {
582
TuxGuitar.instance().getAction(ChangeTrackPropertiesAction.NAME).process(e);
589
private class ChannelList{
590
private List channelIndexs;
592
public ChannelList(){
593
this.channelIndexs = new ArrayList();
596
public void addChannel(int index,int channel){
597
this.channelIndexs.add(new ChannelIndex(index,channel));
600
public int getChannel(int index){
601
Iterator it = this.channelIndexs.iterator();
602
while (it.hasNext()) {
603
ChannelIndex channelIndex = (ChannelIndex) it.next();
604
if(index == channelIndex.getIndex()){
605
return channelIndex.getChannel();
612
this.channelIndexs.clear();
616
private class ChannelIndex{
620
public ChannelIndex(int index,int channel){
622
this.channel = channel;
625
public int getChannel() {
629
public int getIndex() {
635
public static void disposeColors(){
636
for(int i = 0;i < BACKGROUNDS.length;i++){
637
BACKGROUNDS[i].dispose();