/* * Copyright (C) 2013-2015 たんらる */ package fourthline.mabiicco.ui.editor; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Objects; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JCheckBox; import javax.swing.JTextField; import fourthline.mabiicco.AppResource; import fourthline.mmlTools.MMLEventList; import fourthline.mmlTools.MMLNoteEvent; import fourthline.mmlTools.core.TuningBase; import javax.swing.JSpinner; /** * ノートプロパティを編集するためのダイアログ表示で用いるPanelです. * * onlySelectedNoteOption * TRUE: 選択した音符のみを変更 * 音量コマンド(onlySelectedNoteOptionがFALSE時のみ) * FALSE: 一つ前の音符と同じ音量に後続の音符も変更する = 音量コマンド削除 * TRUE: 後続の音符も変更(音量コマンドを挿入する) */ public final class MMLNotePropertyPanel extends JPanel implements ActionListener { private static final long serialVersionUID = 646262293010195918L; private JSpinner velocityValueField; private JSpinner velocityValueField2; private JCheckBox velocityCheckBox; // 音量コマンド private JCheckBox tuningNoteCheckBox; private JCheckBox onlySelectedNoteOption; private JCheckBox incDecrVelocityEditOption; private JComboBox<TuningBase> tuningBaseList; private MMLNoteEvent noteEvent[]; private MMLEventList eventList; // 調律属性は指定されたノートの調律属性がすべて同じ場合に編集可能 private boolean enableTuningEdit; public void showDialog(Frame parentFrame) { int status = JOptionPane.showConfirmDialog(parentFrame, this, AppResource.appText("note.properties"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (status == JOptionPane.OK_OPTION) { applyProperty(); } } /** * Create the panel. */ public MMLNotePropertyPanel() { this(null, null); } /** * Create the panel. */ public MMLNotePropertyPanel(MMLNoteEvent noteEvent[], MMLEventList eventList) { super(); setLayout(null); velocityCheckBox = new JCheckBox(AppResource.appText("note.properties.velocity")); velocityCheckBox.setBounds(40, 20, 150, 21); velocityCheckBox.addActionListener(this); add(velocityCheckBox); velocityValueField = createNumberSpinner(8, 0, MMLNoteEvent.MAX_VOL, 1, velocityCheckBox); velocityValueField.setBounds(240, 20, 50, 19); add(velocityValueField); onlySelectedNoteOption = new JCheckBox(AppResource.appText("note.properties.onlySelectedNoteOption")); onlySelectedNoteOption.setBounds(60, 50, 200, 21); onlySelectedNoteOption.addActionListener(this); add(onlySelectedNoteOption); incDecrVelocityEditOption = new JCheckBox(AppResource.appText("note.properties.incdecr")); incDecrVelocityEditOption.setBounds(60, 80, 180, 21); incDecrVelocityEditOption.addActionListener(this); add(incDecrVelocityEditOption); velocityValueField2 = createNumberSpinner(0, -MMLNoteEvent.MAX_VOL, MMLNoteEvent.MAX_VOL, 1, incDecrVelocityEditOption); velocityValueField2.setBounds(240, 80, 50, 19); add(velocityValueField2); tuningNoteCheckBox = new JCheckBox(AppResource.appText("note.properties.tuning")); tuningNoteCheckBox.setBounds(40, 110, 180, 21); tuningNoteCheckBox.addActionListener(this); add(tuningNoteCheckBox); tuningBaseList = new JComboBox<>(TuningBase.values()); tuningBaseList.setBounds(240, 110, 50, 21); addMousePressEnableAction(tuningBaseList, tuningNoteCheckBox); add(tuningBaseList); this.noteEvent = noteEvent; this.eventList = eventList; setNoteEvent(); updateView(); } /** * コンポーネントをクリックしたときに, 関連するチェックボックスが有効にできるならば有効にする. * @param t * @param checkBox */ private void addMousePressEnableAction(JComponent t, JCheckBox checkBox) { assert(checkBox != null); t.addMouseListener( new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (checkBox.isEnabled()) { checkBox.setSelected(true); t.requestFocus(); updateView(); } } }); } private JSpinner createNumberSpinner(int initial, int min, int max, int step, JCheckBox checkBox) { JSpinner obj = NumberSpinner.createSpinner(initial, min, max, step); JTextField t = ((JSpinner.DefaultEditor) obj.getEditor()).getTextField(); addMousePressEnableAction(t, checkBox); t.addKeyListener( new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { e.consume(); char c = e.getKeyChar(); int value = Integer.parseInt(t.getText()); if (Character.isDigit(c)) { value = Integer.parseInt(t.getText()+c); } else if (c == '-') { value = (value < 0) ? value : -value; } else if (c == '+') { value = (value < 0) ? -value : value; } else { return; } while ( (value < min) || (value > max) ) { value = Integer.parseInt(Integer.toString(value).substring(1)); } t.setText(Integer.toString(value)); } }); return obj; } private void setNoteEvent() { if (noteEvent == null) { return; } // 調律音 TuningBase first = noteEvent[0].getTuningBase(); if (first != null) { tuningNoteCheckBox.setSelected(true); tuningBaseList.setSelectedItem(first); } else { tuningNoteCheckBox.setSelected(false); } enableTuningEdit = true; for (MMLNoteEvent note : noteEvent) { if (!Objects.equals(first, note.getTuningBase())) { enableTuningEdit = false; break; } } MMLNoteEvent prevNote = eventList.searchPrevNoteOnTickOffset(noteEvent[0].getTickOffset()); int velocity = noteEvent[0].getVelocity(); velocityValueField.setValue(velocity); if ( (prevNote == null) || (prevNote.getVelocity() != velocity) ) { velocityCheckBox.setSelected(true); } else { velocityCheckBox.setSelected(false); } } /** * パネルの情報をノートに反映します. */ public void applyProperty() { int incDecrValue = ((Integer) velocityValueField2.getValue()).intValue(); for (MMLNoteEvent targetNote : noteEvent) { Integer value = (Integer) velocityValueField.getValue(); if (onlySelectedNoteOption.isSelected()) { if (!incDecrVelocityEditOption.isSelected()) { // 選択されたノートのみの音量を変更 targetNote.setVelocity(value.intValue()); } else { // 増減量による音量変更 targetNote.setVelocity( targetNote.getVelocity() + incDecrValue ); } } else { // 音量コマンドにより後続のノートも更新する if (velocityCheckBox.isSelected()) { eventList.setVelocityCommand(targetNote, value.intValue()); } else { eventList.unsetVelocityCommand(targetNote); } } // 調律設定が有効な場合は、調律属性も更新する. if (tuningNoteCheckBox.isEnabled()) { TuningBase base = tuningBaseList.getItemAt(tuningBaseList.getSelectedIndex()); targetNote.setTuningNote( tuningNoteCheckBox.isSelected() ? base : null ); } } } private void updateView() { boolean velocityCommand = velocityCheckBox.isSelected(); boolean onlySelect = onlySelectedNoteOption.isSelected(); boolean incrDecrValue = incDecrVelocityEditOption.isSelected(); // 音量コマンドチェックBox velocityCheckBox.setEnabled( !onlySelect ); // 音量入力欄 velocityValueField.setEnabled( (velocityCommand && !onlySelect) || (!incrDecrValue && (velocityCommand || onlySelect)) ); // 増減入力チェックBox incDecrVelocityEditOption.setEnabled( onlySelect ); // 増減入力欄 velocityValueField2.setEnabled( onlySelect && incrDecrValue ); // 調律チェックBox tuningNoteCheckBox.setEnabled(enableTuningEdit); tuningBaseList.setEnabled( (enableTuningEdit && tuningNoteCheckBox.isSelected()) ); } @Override public Dimension getPreferredSize() { return new Dimension(350, 150); } @Override public void actionPerformed(ActionEvent e) { updateView(); } }