*/\r
public static class VersionInfo {\r
public static final String NAME = "MIDI Chord Helper";\r
- public static final String VERSION = "Ver.20140413.2";\r
+ public static final String VERSION = "Ver.20140413.3";\r
public static final String COPYRIGHT = "Copyright (C) 2004-2014";\r
public static final String AUTHER = "@きよし - Akiyoshi Kamide";\r
public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";\r
private JToggleButton anoGakkiToggleButton;\r
\r
public void init() {\r
- String imageIconPath = "images/midichordhelper.png";\r
+ String imageIconPath = "midichordhelper.png";\r
URL imageIconUrl = getClass().getResource(imageIconPath);\r
if( imageIconUrl == null ) {\r
- System.out.println("icon "+imageIconPath+" not found");\r
+ System.out.println("Icon image "+imageIconPath+" not found");\r
imageIcon = null;\r
}\r
else {\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent event) {\r
- chordMatrix.setSelectedChord(\r
- event.getActionCommand().trim().split("[ \t\r\n]")[0]\r
- );\r
+ String symbol = event.getActionCommand().trim().split("[ \t\r\n]")[0];\r
+ chordMatrix.setSelectedChord(symbol);\r
}\r
});\r
}};\r
add( Box.createHorizontalStrut(2) );\r
add( enterButtonLabel = new ChordButtonLabel("Enter",chordMatrix) {{\r
addMouseListener(new MouseAdapter() {\r
- public void mousePressed(MouseEvent e) {\r
- if( (e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ) // RightClicked\r
- chordMatrix.setSelectedChord( (Chord)null );\r
- else\r
- chordMatrix.setSelectedChord( lyricDisplay.getText() );\r
+ public void mousePressed(MouseEvent event) {\r
+ if( (event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ) // RightClicked\r
+ chordMatrix.setSelectedChord((Chord)null);\r
+ else {\r
+ chordMatrix.setSelectedChord(lyricDisplay.getText());\r
+ }\r
}\r
});\r
}});\r
// あの楽器っぽい表示\r
if( keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiPane != null ) {\r
JComponent btn = chordMatrix.getSelectedButton();\r
- if( btn != null )\r
- anoGakkiPane.start(chordMatrix,btn);\r
+ if( btn != null ) anoGakkiPane.start(chordMatrix, btn.getBounds());\r
}\r
// コードボタンからのコードを、カポつき演奏キーからオリジナルキーへ変換\r
Key originalKey = chordMatrix.getKeySignatureCapo();\r
}\r
}\r
/**\r
- * クリックされたコンポーネントの中央から図形の表示を開始します。\r
- * @param source 元のAWTコンポーネント\r
- * @param clickedComponent クリックされたコンポーネント\r
- */\r
- public void start(Component source, Component clickedComponent) {\r
- start(source,clickedComponent.getBounds());\r
- }\r
- /**\r
* 指定された長方形領域({@link Rectangle})の中央から図形の表示を開始します。\r
- * @param source 元のAWTコンポーネント\r
- * @param rect 長方形領域\r
+ * @param source AWTコンポーネント\r
+ * @param rect AWTコンポーネント内の座標系を基準とした長方形領域\r
*/\r
public void start(Component source, Rectangle rect) {\r
Point point = rect.getLocation();\r
point.translate( rect.width/2, rect.height/2 );\r
- start(source,point);\r
+ start(source, point);\r
}\r
private long prevStartedAt = System.nanoTime();\r
- public void start(Component source, Point clickedPoint) {\r
+ /**\r
+ * 指定された場所から図形の表示を開始します。\r
+ * @param source AWTコンポーネント\r
+ * @param point AWTコンポーネント内の座標系を基準とした場所\r
+ */\r
+ public void start(Component source, Point point) {\r
long startedAt = System.nanoTime();\r
if( startedAt - prevStartedAt < (INTERVAL_MS * 1000)*50 ) {\r
// 頻繁すぎる場合は無視する\r
return;\r
}\r
- clickedPoint = SwingUtilities.convertPoint(source, clickedPoint, this);\r
+ point = SwingUtilities.convertPoint(source, point, this);\r
synchronized (queue) {\r
- queue.add(new QueueEntry(clickedPoint));\r
+ queue.add(new QueueEntry(point));\r
}\r
timer.start();\r
prevStartedAt = startedAt;\r
import javax.swing.DefaultComboBoxModel;\r
import javax.swing.JComponent;\r
import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
import javax.swing.JPanel;\r
\r
import camidion.chordhelper.ButtonIcon;\r
selectedChordCapo = (chord == null ? null : chord.clone().transpose(capo,key));\r
fireChordChanged();\r
}\r
- public void setSelectedChord( String chordSymbol ) {\r
+ /**\r
+ * コードを文字列で設定します。\r
+ * @param chordSymbol コード名\r
+ */\r
+ public void setSelectedChord(String chordSymbol) throws IllegalArgumentException {\r
Chord chord = null;\r
if( chordSymbol != null && ! chordSymbol.isEmpty() ) {\r
try {\r
chord = new Chord(chordSymbol);\r
- } catch( IllegalArgumentException ex ) {\r
- // 手入力で誤ったコードが入力されても無視\r
+ } catch( IllegalArgumentException e ) {\r
+ JOptionPane.showMessageDialog(\r
+ null, e.getMessage(), "Input error",\r
+ JOptionPane.ERROR_MESSAGE\r
+ );\r
+ return;\r
}\r
}\r
setSelectedChord(chord);\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- ChordProgression cp = getChordProgression();\r
+ ChordProgression cp = createChordProgression();\r
cp.transpose(1);\r
setChordProgression(cp);\r
}\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- ChordProgression cp = getChordProgression();\r
+ ChordProgression cp = createChordProgression();\r
cp.transpose(-1);\r
setChordProgression(cp);\r
}\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- ChordProgression cp = getChordProgression();\r
+ ChordProgression cp = createChordProgression();\r
cp.toggleEnharmonically();\r
setChordProgression(cp);\r
}\r
addActionListener(new ActionListener() {\r
@Override\r
public void actionPerformed(ActionEvent e) {\r
- ChordProgression cp = getChordProgression();\r
+ ChordProgression cp = createChordProgression();\r
cp.toggleKeyMajorMinor();\r
setChordProgression(cp);\r
}\r
* 新しいコード進行を生成して返します。\r
* @return 新しいコード進行\r
*/\r
- private ChordProgression getChordProgression() {\r
+ private ChordProgression createChordProgression() {\r
return new ChordProgression(chordText.getText());\r
}\r
/**\r
tempoSelecter.getTempoByteArray(),\r
timesigSelecter.getByteArray()\r
);\r
- return getChordProgression().toMidiSequence(\r
+ return createChordProgression().toMidiSequence(\r
(int)ppqComboBox.getSelectedItem(),\r
measureSelecter.getStartMeasurePosition(),\r
measureSelecter.getEndMeasurePosition(),\r
}\r
//\r
// コードネームの文字列が示すコードに置き換えます。\r
- public Chord setChordSymbol(String chord_symbol) {\r
+ public Chord setChordSymbol(String chordSymbol) {\r
//\r
// 分数コードの分子と分母に分ける\r
- String parts[] = chord_symbol.trim().split("(/|on)");\r
+ String parts[] = chordSymbol.trim().split("(/|on)");\r
if( parts.length == 0 ) {\r
return this;\r
}\r
if( source_text == null ) return;\r
Measure measure;\r
Line line;\r
- String[] lines_src, measures_src, elements_src;\r
- Chord last_chord = null;\r
- String key_regex = "^Key(\\s*):(\\s*)";\r
+ String[] linesSrc, measuresSrc, elementsSrc;\r
+ Chord lastChord = null;\r
+ String keyHeaderRegex = "^Key(\\s*):(\\s*)";\r
+ String keyValueRegex = "[A-G]+.*$";\r
//\r
// キーであるかどうか見分けるためのパターン\r
- Pattern key_match_pattern = Pattern.compile(\r
- key_regex+".*$", Pattern.CASE_INSENSITIVE\r
- );\r
+ Pattern keyMatchPattern = Pattern.compile(\r
+ keyHeaderRegex + keyValueRegex,\r
+ Pattern.CASE_INSENSITIVE\r
+ );\r
// キーのヘッダーを取り除くためのパターン\r
- Pattern key_repl_pattern = Pattern.compile(\r
- key_regex, Pattern.CASE_INSENSITIVE\r
- );\r
+ Pattern keyReplPattern = Pattern.compile(\r
+ keyHeaderRegex, Pattern.CASE_INSENSITIVE\r
+ );\r
//\r
- lines_src = source_text.split("[\r\n]+");\r
+ linesSrc = source_text.split("[\r\n]+");\r
lines = new Vector<Line>();\r
- for( String line_src : lines_src ) {\r
- measures_src = line_src.split("\\|");\r
- if( measures_src.length > 0 ) {\r
- String key_string = measures_src[0].trim();\r
- if( key_match_pattern.matcher(key_string).matches() ) {\r
- key = new Key(\r
- key_repl_pattern.matcher(key_string).replaceFirst("")\r
- );\r
- // System.out.println("Key = " + key);\r
- continue;\r
+ for( String line_src : linesSrc ) {\r
+ measuresSrc = line_src.split("\\|");\r
+ if( measuresSrc.length > 0 ) {\r
+ String keyString = measuresSrc[0].trim();\r
+ if( keyMatchPattern.matcher(keyString).matches() ) {\r
+ try {\r
+ key = new Key(keyReplPattern.matcher(keyString).replaceFirst(""));\r
+ continue;\r
+ } catch( Exception e ) {\r
+ e.printStackTrace();\r
+ }\r
}\r
}\r
line = new Line();\r
- for( String measure_src : measures_src ) {\r
- elements_src = measure_src.split("[ \t]+");\r
+ for( String measureSrc : measuresSrc ) {\r
+ elementsSrc = measureSrc.split("[ \t]+");\r
measure = new Measure();\r
- for( String element_src : elements_src ) {\r
- if( element_src.isEmpty() ) continue;\r
- if( element_src.equals("%") ) {\r
+ for( String elementSrc : elementsSrc ) {\r
+ if( elementSrc.isEmpty() ) continue;\r
+ if( elementSrc.equals("%") ) {\r
if( measure.addBeat() == 0 ) {\r
- measure.add( new ChordStroke(last_chord) );\r
+ measure.add( new ChordStroke(lastChord) );\r
}\r
continue;\r
}\r
try {\r
- measure.add( new ChordStroke(\r
- last_chord = new Chord(element_src)\r
- ));\r
+ measure.add(new ChordStroke(lastChord = new Chord(elementSrc)));\r
} catch( IllegalArgumentException ex ) {\r
- measure.add( new Lyrics(element_src) );\r
+ measure.add( new Lyrics(elementSrc) );\r
}\r
}\r
line.add(measure);\r
}\r
\r
// コード進行の移調\r
- public void transpose(int chromatic_offset) {\r
+ public void transpose(int chromaticOffset) {\r
for( Line line : lines ) {\r
for( Measure measure : line ) {\r
for( int i=0; i<measure.size(); i++ ) {\r
// キーが未設定のときは、最初のコードから推測して設定\r
if( key == null ) key = new Key( new_chord );\r
//\r
- new_chord.transpose( chromatic_offset, key );\r
+ new_chord.transpose( chromaticOffset, key );\r
measure.set( i, new ChordStroke( new_chord, cs.beat_length ) );\r
}\r
}\r
}\r
}\r
- key.transpose(chromatic_offset);\r
+ key.transpose(chromaticOffset);\r
}\r
// 異名同音の♭と#を切り替える\r
public void toggleEnharmonically() {\r
}\r
/**\r
* 小節数、トラック仕様、コード進行をもとに MIDI シーケンスを生成します。\r
+ * @param ppq 分解能(pulse per quarter)\r
+ * @param startMeasure 開始小節位置\r
+ * @param endMeasure 終了小節位置\r
+ * @param firstTrack 最初のトラックの仕様\r
+ * @param trackSpecs 残りのトラックの仕様\r
* @return MIDIシーケンス\r
*/\r
public Sequence toMidiSequence(\r
- int ppq, int start_measure_pos, int end_measure_pos,\r
- FirstTrackSpec first_track,\r
- Vector<AbstractNoteTrackSpec> track_specs\r
+ int ppq, int startMeasure, int endMeasure,\r
+ FirstTrackSpec firstTrack,\r
+ Vector<AbstractNoteTrackSpec> trackSpecs\r
) {\r
Sequence seq;\r
try {\r
return null;\r
}\r
// マスタートラックの生成\r
- if( first_track == null ) {\r
- first_track = new FirstTrackSpec();\r
+ if( firstTrack == null ) {\r
+ firstTrack = new FirstTrackSpec();\r
}\r
- first_track.key = this.key;\r
- first_track.createTrack( seq, start_measure_pos, end_measure_pos );\r
+ firstTrack.key = this.key;\r
+ firstTrack.createTrack( seq, startMeasure, endMeasure );\r
//\r
// 中身がなければここで終了\r
- if( lines == null || track_specs == null ) return seq;\r
+ if( lines == null || trackSpecs == null ) return seq;\r
//\r
// コード進行の中に時間軸(MIDI tick)を書き込む\r
- setTickPositions( first_track );\r
+ setTickPositions(firstTrack);\r
//\r
// コードのテキストと歌詞を書き込む\r
- setChordSymbolTextTo( first_track );\r
- setLyricsTo( first_track );\r
+ setChordSymbolTextTo(firstTrack);\r
+ setLyricsTo(firstTrack);\r
//\r
// 残りのトラックを生成\r
- for( AbstractNoteTrackSpec ts : track_specs ) {\r
- ts.createTrack( seq, first_track );\r
+ for( AbstractNoteTrackSpec ts : trackSpecs ) {\r
+ ts.createTrack(seq, firstTrack);\r
if( ts instanceof DrumTrackSpec ) {\r
((DrumTrackSpec)ts).addDrums(this);\r
}\r
}\r
/**\r
* C、Am のような文字列から調を構築します。\r
- * @param keySymbol キーを表す文字列\r
+ * @param keySymbol 調を表す文字列\r
+ * @throw IllegalArgumentException 調を表す文字列が不正の場合\r
*/\r
- public Key(String keySymbol) {\r
+ public Key(String keySymbol) throws IllegalArgumentException {\r
boolean isMinor = keySymbol.matches(".*m");\r
setKey((new NoteSymbol(keySymbol)).toCo5(isMinor), isMinor);\r
}\r
public int majorCo5Of(String noteSymbol) {\r
if( Objects.requireNonNull(\r
noteSymbol,\r
- "Note symbol must not be null"\r
+ "Musical note symbol must not be null"\r
).isEmpty() ) {\r
throw new IllegalArgumentException(\r
- "Empty note symbol specified"\r
+ "Empty musical note symbol specified"\r
);\r
}\r
char topChar = noteSymbol.charAt(0);\r
int co5 = notes.indexOf(topChar);\r
if( co5 < 0 ) {\r
throw new IllegalArgumentException(\r
- "Unknown note symbol " + noteSymbol\r
+ "Invalid musical note symbol "+noteSymbol+", not in "+notes\r
);\r
}\r
co5--;\r
chordDisplay.setNote(noteNumber, isRhythmPart());\r
}\r
if( anoGakkiPane != null ) {\r
- PianoKey piano_key = getPianoKey(noteNumber);\r
- if( piano_key != null )\r
- anoGakkiPane.start(PianoKeyboard.this, piano_key.indicator);\r
+ PianoKey pienoKey = getPianoKey(noteNumber);\r
+ if( pienoKey != null )\r
+ anoGakkiPane.start(PianoKeyboard.this, pienoKey.indicator);\r
}\r
}\r
if( chordMatrix != null ) {\r