/* License see bottom */
package jpianotrain.gui;
import static jpianotrain.util.ResourceKeys.FONT_RESOURCE_ERROR;
import static jpianotrain.util.ResourceKeys.MESSAGE_NOTES_UNMAPPED;
import static jpianotrain.util.ResourceKeys.TITLE_ERROR;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import jpianotrain.ApplicationContext;
import jpianotrain.Constants;
import jpianotrain.event.NoteDispatcherListener;
import jpianotrain.font.MusiQwikB;
import jpianotrain.font.NoteMapper;
import jpianotrain.midi.NoteDispatcher;
import jpianotrain.staff.Note;
import jpianotrain.staff.Tune;
import jpianotrain.util.ResourceFactory;
import org.apache.log4j.Logger;
/**
* Displays a staff which the user should
* play along.
*
* @since 0
* @author Alexander Methke
*/
public class NotationPanel extends JPanel
implements NoteDispatcherListener {
private static final Logger log=Logger.getLogger(NotationPanel.class);
public NotationPanel() {
super();
NoteDispatcher.getInstance().addListener(this);
initGui();
}
public void display(Tune t) {
StringBuffer sb=new StringBuffer();
StringBuffer failed=new StringBuffer();
sb.append("&");
NoteMapper nm=NoteMapper.getMapper(new MusiQwikB());
rightGlyphs=new ArrayList<NoteGlyph>();
rightIndex=0;
for(Note n:t.getRightHand()) {
String s=nm.renderTrebleNote(n);
if (s==null) {
failed.append(n);
failed.append("\n");
} else {
rightGlyphs.add(new NoteGlyph(sb.length(), s));
sb.append(s);
}
}
sb.append("!");
if (t.getLeftHand()!=null) {
leftIndex=0;
sb.append("\n\u00af");
leftGlyphs=new ArrayList<NoteGlyph>();
for(Note n:t.getLeftHand()) {
String s=nm.renderBassNote(n);
if (s==null) {
failed.append(n);
failed.append("\n");
} else {
leftGlyphs.add(new NoteGlyph(sb.length(), s));
sb.append(s);
}
}
sb.append("!");
}
textPane.setText(sb.toString());
if (failed.length()>0) {
JOptionPane.showMessageDialog(ApplicationContext.getInstance().getDefaultDialogOwner(),
ResourceFactory.getString(MESSAGE_NOTES_UNMAPPED)+"\n"+failed.toString(),
ResourceFactory.getString(TITLE_ERROR),
JOptionPane.ERROR_MESSAGE);
}
}
protected void initGui() {
textPane=new AATextPane();
textPane.setText("&rstuvw!\n\u00afwvutrs!\n&rst\u00d4uvw!");
textPane.setEditable(false);
MutableAttributeSet attrs = textPane.getInputAttributes();
try {
Font font=ResourceFactory.getNotationFont();
font=font.deriveFont(Font.PLAIN, Constants.NOTATION_FONT_SIZE);
StyleConstants.setFontFamily(attrs, font.getFamily());
StyleConstants.setFontSize(attrs, font.getSize());
StyleConstants.setItalic(attrs, (font.getStyle() & Font.ITALIC) != 0);
StyleConstants.setBold(attrs, (font.getStyle() & Font.BOLD) != 0);
rightStyle=new SimpleAttributeSet(attrs);
StyleConstants.setForeground(rightStyle, Color.green);
wrongStyle=new SimpleAttributeSet(attrs);
StyleConstants.setForeground(wrongStyle, Color.red);
textPane.setFont(font);
} catch (Exception ex) {
log.error(ResourceFactory.getString(FONT_RESOURCE_ERROR), ex);
}
StyleConstants.setForeground(attrs, Color.black);
StyledDocument doc = textPane.getStyledDocument();
doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false);
setLayout(new BorderLayout());
add(new JScrollPane(textPane), BorderLayout.CENTER);
}
// NoteDispatcherListener
public void notePlayedRight(Note n) {
NoteGlyph g=rightGlyphs.get(rightIndex);
StyledDocument doc = textPane.getStyledDocument();
doc.setCharacterAttributes(g.getStart(), g.getLength(), rightStyle, true);
rightIndex++;
}
public void notePlayedLeft(Note n) {
NoteGlyph g=leftGlyphs.get(leftIndex);
StyledDocument doc = textPane.getStyledDocument();
doc.setCharacterAttributes(g.getStart(), g.getLength(), rightStyle, true);
leftIndex++;
}
public void notePlayedWrong(Note n) {
NoteGlyph g1=rightGlyphs.get(rightIndex);
NoteGlyph g2=leftGlyphs.get(leftIndex);
StyledDocument doc = textPane.getStyledDocument();
doc.setCharacterAttributes(g1.getStart(), g1.getLength(), wrongStyle, true);
doc.setCharacterAttributes(g2.getStart(), g2.getLength(), wrongStyle, true);
}
/**
* Doesn't do anything.
*
*/
public void nextNoteRight(Note n) {
}
/**
* Doesn't do anything.
*
*/
public void nextNoteLeft(Note n) {
}
private static class NoteGlyph {
NoteGlyph(int start, String g) {
this.start=start;
this.glyph=g;
}
public int getStart() {
return start;
}
public String getGlyph() {
return glyph;
}
public int getEnd() {
return start+getGlyph().length();
}
public int getLength() {
return getGlyph().length();
}
private int start;
private String glyph;
}
private static class AATextPane extends JTextPane {
public void paintComponent(Graphics g) {
Graphics2D g2d=(Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
super.paintComponent(g2d);
}
}
private int leftIndex;
private int rightIndex;
private List<NoteGlyph> leftGlyphs;
private List<NoteGlyph> rightGlyphs;
private JTextPane textPane;
private MutableAttributeSet wrongStyle;
private MutableAttributeSet rightStyle;
}
/*
Copyright (C) 2008 Alexander Methke
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 (gplv3.txt).
*/