package org.herac.tuxguitar.gui.tools.custom.tuner;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.herac.tuxguitar.gui.editors.TGPainter;
/**
* @author Nikola Kolarovic <johnny47ns@yahoo.com>
*
*/
public class TGTunerRoughWidget extends Composite {
private static final int MIN_HEIGHT = 25;
static String[] TONESSTRING = { "C", "C#", "D", "D#", "E", "F", "F#", "G",
"G#", "A", "A#", "B" };
private final int boundaryHeight = 16;
protected Composite composite = null;
protected float currentFrequency = 0;
private final int endAb = 20;
private final int markerHeight = 12;
private final int markerWidth = 4;
/** constants for drawing */
private final int startA = 20;
public TGTunerRoughWidget(Composite parent) {
super(parent, SWT.NONE);
this.init();
}
/**
* formula which gets fine tone position (on scale 0-240) in fact, it's
* inverse formula of inverse of TGTuner::getNoteFrequency()
*/
protected int getTone(float frequency) {
float midiTone = (float) (45 + 12 * (Math.log(frequency / 110) / Math
.log(2)));
return Math.round(20 * (midiTone % 12));
}
public void init() {
this.setLayout(new GridLayout(1, true));
this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
((GridData) this.getLayoutData()).widthHint = 600;
this.composite = new Composite(this, SWT.BORDER | SWT.DOUBLE_BUFFERED);
this.composite.setBackground(this.getDisplay().getSystemColor(
SWT.COLOR_WHITE));
this.composite.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
TGPainter painter = new TGPainter(e.gc);
TGTunerRoughWidget.this.paintWidget(painter);
}
});
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.minimumHeight = MIN_HEIGHT;
data.grabExcessHorizontalSpace = true;
this.composite.setLayoutData(data);
}
private void paintWidget(TGPainter painter) {
Point compositeSize = this.composite.getSize();
// lines and tones
painter.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
painter.initPath();
painter.moveTo(this.startA, compositeSize.y / 2);
painter.lineTo(compositeSize.x - this.endAb, compositeSize.y / 2);
painter.closePath();
int increment = (int) Math
.round((compositeSize.x - this.startA - this.endAb) / 12.0);
int currentTone = 0;
for (int i = this.startA; i < compositeSize.x + 1 - this.endAb; i += increment) {
painter.initPath();
painter.moveTo(i, compositeSize.y / 2 - this.boundaryHeight / 2);
painter.lineTo(i, compositeSize.y / 2 + this.boundaryHeight / 2);
painter.closePath();
painter.drawString(TONESSTRING[currentTone % 12], i, compositeSize.y / 2
- this.boundaryHeight / 2 - 20);
currentTone++;
}
// marker
if (this.currentFrequency > 0) {
painter.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLUE));
painter.initPath();
int markerPos = this.markerWidth
/ 2
+ this.startA
+ (int) Math
.round(((compositeSize.x - this.startA - this.endAb) / 240.0)
* (this.getTone(this.currentFrequency)));
painter.moveTo(markerPos, compositeSize.y / 2 - this.markerHeight / 2);
painter.setLineWidth(this.markerWidth);
painter.lineTo(markerPos, compositeSize.y / 2 + this.markerHeight / 2);
painter.closePath();
}
}
public void redraw() {
super.redraw();
this.composite.redraw();
}
public void setCurrentFrequency(double currentFrequency) {
this.currentFrequency = (float) currentFrequency;
this.redraw();
}
}