/*
* Musical Skill Coach - An interactive midi device friendly program to help music students improve their skills
* Copyright (C) 2011 Paul-Emile Gaudet
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package music.ui.lib;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
public class Note extends Component
{
/**
*
*/
private static final long serialVersionUID = 1L;
public static final int MODE_NATURAL = 0;
public static final int MODE_FLAT = 1;
public static final int MODE_SHARP = 2;
protected int position;
protected int duration;
protected int mode;
protected Point tailTip;
protected int staff;
public Note(int staff)
{
this.position = 0;
this.duration = 1;
this.staff = staff;
this.mode = MODE_NATURAL;
tailTip = null;
}
public Note(int position, int duration, int staff)
{
this.position = position;
this.duration = duration;
this.staff = staff;
this.mode = MODE_NATURAL;
tailTip = null;
}
public void setMidiNote(int position, int duration, int randomHalfNote)
{
if ((position < 0) || (position > 127))
return;
int octave = position / 12;
int octaveKey = position % 12;
int mode = MODE_NATURAL;
// Do we want a sharp
if ((randomHalfNote % 2) == 0)
{
switch (octaveKey)
{
case 0: // C
break;
case 1: // C#
octaveKey = 0;
mode = MODE_SHARP;
break;
case 2: // D
octaveKey = 1;
break;
case 3: // D#
octaveKey = 1;
mode = MODE_SHARP;
break;
case 4: // E
octaveKey = 2;
break;
case 5: // F
octaveKey = 3;
break;
case 6: // F#
octaveKey = 3;
mode = MODE_SHARP;
break;
case 7: // G
octaveKey = 4;
break;
case 8: // G#
octaveKey = 4;
mode = MODE_SHARP;
break;
case 9: // A
octaveKey = 5;
break;
case 10: // A#
octaveKey = 5;
mode = MODE_SHARP;
break;
case 11: // B
octaveKey = 6;
break;
}
}
// or would be prefer the flat instead?
else
{
switch (octaveKey)
{
case 0: // C
break;
case 1: // Db
octaveKey = 1;
mode = MODE_FLAT;
break;
case 2: // D
octaveKey = 1;
break;
case 3: // Eb
octaveKey = 2;
mode = MODE_FLAT;
break;
case 4: // E
octaveKey = 2;
break;
case 5: // F
octaveKey = 3;
break;
case 6: // Gb
octaveKey = 4;
mode = MODE_FLAT;
break;
case 7: // G
octaveKey = 4;
break;
case 8: // Ab
octaveKey = 5;
mode = MODE_FLAT;
break;
case 9: // A
octaveKey = 5;
break;
case 10: // Bb
octaveKey = 6;
mode = MODE_FLAT;
break;
case 11: // B
octaveKey = 6;
break;
}
}
this.duration = duration;
this.mode = mode;
if (staff == 0)
{
octave -= 3;
this.position = ((octave * 7) + octaveKey) - 4;
}
else if (staff == 1)
{
octave -= 5;
this.position = ((octave * 7) + octaveKey) - 2;
}
}
public int getPosition()
{
return position;
}
public void setPosition(int position)
{
this.position = position;
}
public int getDuration()
{
return duration;
}
public void setDuration(int duration)
{
this.duration = duration;
}
public Point getTailTip()
{
return tailTip;
}
protected int getRequiredSharpWidth(int x1, int x2)
{
int width = x2 - x1;
if (width < 0)
width *= -1;
return width * 2 / 3;
}
protected int getRequiredFlatWidth(int x1, int x2)
{
int width = x2 - x1;
if (width < 0)
width *= -1;
return width * 2 / 3;
}
public int getRequiredWidth(int x1, int x2)
{
int standardWidth = x2 - x1;
if (duration > 4)
standardWidth *= 2;
if (mode == MODE_SHARP)
standardWidth += getRequiredSharpWidth(x1, x2);
else if (mode == MODE_FLAT)
standardWidth += getRequiredFlatWidth(x1, x2);
return standardWidth;
}
public void paint(Graphics g, int x1, int y1, int x2, int y2)
{
Graphics2D g2 = (Graphics2D) g;
int width = x2 - x1;
int height = y2 - y1;
if (width < 0)
width *= -1;
if (height < 0)
height *= -1;
if (duration > 4)
{
x1 -= width;
x2 -= width;
}
// note modifier(s) like flats/sharps, etc...
int modWidth = width / 2;
int modHeight = height;
int modx1 = x1 - (width * 2 / 3);
int modx2 = modx1 + modWidth;
int mody1 = y1;
int mody2 = y2;
if (mode == MODE_SHARP)
{
g2.drawLine(modx1, mody1 + modHeight / 2, modx2, mody1);
g2.drawLine(modx1, mody2, modx2, mody1 + modHeight / 2);
g2.drawLine(modx1 + modWidth / 3, mody1, modx1 + modWidth / 3, mody2);
g2.drawLine(modx2 - modWidth / 3, mody1, modx2 - modWidth / 3, mody2);
}
if (mode == MODE_FLAT)
{
g2.drawLine(modx2 - modWidth / 3, mody1 - modHeight, modx2 - modWidth / 3, mody2);
g2.drawOval(modx2 - modWidth / 3, mody1 + modHeight / 4, modWidth / 3, modHeight / 2);
}
if (duration == 1)
{
g2.drawOval(x1, y1, width, height);
tailTip = null;
}
else
{
if (tailTip == null)
tailTip = new Point(x2, y1 + height / 2 - Constants.NOTATION_TAIL_LENGTH);
else
tailTip.setLocation(x2, y1 + height / 2 - Constants.NOTATION_TAIL_LENGTH);
if (duration == 2)
{
g2.drawOval(x1, y1, width, height);
g2.drawLine(x2, y1 + height / 2, x2, y1 + height / 2 - Constants.NOTATION_TAIL_LENGTH);
}
else
{
g2.fillOval(x1, y1, width, height);
g2.drawLine(x2, y1 + height / 2, x2, y1 + height / 2 - Constants.NOTATION_TAIL_LENGTH);
int d = duration;
int yLocus = y1 + height / 2 - Constants.NOTATION_TAIL_LENGTH;
while (d > 4)
{
g2.drawLine(x2, yLocus, x2 + width, yLocus + width);
d /= 2;
yLocus += width;
}
}
}
}
}