/* * Created on Mar 7, 2006 * * Copyright (c) 2006 P.J.Leonard * * http://www.frinika.com * * This file is part of Frinika. * * Frinika 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 2 of the License, or * (at your option) any later version. * Frinika 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 Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.sequencer.gui; import static com.frinika.sequencer.gui.menu.midi.MidiStepRecordAction.formatNote; import static com.frinika.sequencer.gui.menu.midi.MidiStepRecordAction.parseNote; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; import com.frinika.project.ProjectContainer; import com.frinika.sequencer.model.util.TimeUtils; public class LabelFieldEditor extends JPanel { // changed to use TimeSelectors (JSpinners), NoteSelector (JComboBox) and JSpinners, Jens 2007-03-11 /** * */ private static final long serialVersionUID = 1L; //private JTextField textField; private JComponent editor; private JLabel label; AbstractTableModel model; private int column; private TimeUtils timeUtil; private String textBackup = null; public LabelFieldEditor(final MyAbstractTableModel model,final int column, ProjectContainer project) { timeUtil = new TimeUtils(project); //System.out.println("COLUMN-CLASS: #"+column+" "+model.getColumnClass(column).getName()); setLayout(new FlowLayout(FlowLayout.CENTER,2,0)); this.model=model; this.column=column; add(label=new JLabel(model.getColumnName(column))); /* textField=new JTextField(); textField.setColumns(model.getColumnWidth(column)); add(textField); textField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { model.setValueAt(textField.getText(), 0, column); } }); */ editor = createEditor(model, column, project); update(); add(editor); } boolean isUpdateing = false; protected JComponent createEditor(final MyAbstractTableModel model, int columnIndex, ProjectContainer project) { // hard-code different types of editors by index-number... not too beautiful, but effective switch (column) { case 0: // start-tick case 3: // length final TimeSelector ts = new TimeSelector(project, (column==0) ? TimeFormat.BAR_BEAT_TICK : TimeFormat.BEAT_TICK); ts.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { if(isUpdateing) return; Long ticks = ts.getTicks(); if (ticks == null) return; model.setValueAt(timeUtil.tickToBarBeatTick(ticks), 0, column); } }); return ts; case 2: // velocity/ctrl-value final JSpinner spinner = new JSpinnerDraggable(new SpinnerNumberModel(0, 0, 127, 1)); spinner.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { if(isUpdateing) return; model.setValueAt(spinner.getValue().toString(), 0, column); } }); return spinner; case 1: // note final NoteSelector ns = new NoteSelector(); ns.addItem("-"); // no. 128 ns.setSelectedIndex(128); ns.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(isUpdateing) return; int sel = ns.getSelectedIndex(); if (sel <= 127) { model.setValueAt( formatNote(127 - sel), 0, column ); } } }); return ns; default: assert false; return null; } } public void update() { try { isUpdateing = true; Object o=model.getValueAt(0, column); if ((o == null) || (o.toString().equals("null"))) { JComponent e = editor; if (e instanceof TimeSelector) { e = (JComponent)e.getComponent(0); } if (e instanceof JSpinner) { JTextField tf = ((JSpinner.DefaultEditor)((JSpinner)e).getEditor()).getTextField(); String t = tf.getText(); if ((t != null) && (t.length() > 0)) { // don't set backup twice if updated with null-value more than once textBackup = t; } tf.setText(""); } else if (e instanceof NoteSelector) { ((NoteSelector)e).setSelectedIndex(128); } //textField.setText(""); editor.setEnabled(false); label.setText("N.A."); } else { long value = 0; switch (column) { case 0: // fallthrough case 3: value = timeUtil.barBeatTickToTick(o.toString()); break; case 1: value = parseNote(o.toString()); break; case 2: value = Integer.parseInt(o.toString()); break; } if (editor instanceof TimeSelector) { JComponent e = (JComponent)editor.getComponent(0); restoreTextBackup((JSpinner)e); ((JSpinner)e).setValue(value); } else if (editor instanceof JSpinner) { restoreTextBackup((JSpinner)editor); ((JSpinner)editor).setValue((int)value); //JTextField tf = ((JSpinner.DefaultEditor)((JSpinner)editor).getEditor()).getTextField(); //tf.setText(""); } else if (editor instanceof NoteSelector) { int i = (127 - (int)value); if (((NoteSelector)editor).getSelectedIndex() != i) { ((NoteSelector)editor).setSelectedIndex(i); } } editor.setEnabled(true); //textField.setText(o.toString()); label.setText(model.getColumnName(column)); } } finally { isUpdateing = false; } } private void restoreTextBackup(JSpinner e) { // restore string backup if textfield had been emptied before // this is necessary because new (numerical) values can only be set if valid strings are currently set if (textBackup != null) { JTextField tf = ((JSpinner.DefaultEditor)e.getEditor()).getTextField(); String s = tf.getText(); if ((s == null) || (s.length() == 0)) { tf.setText(textBackup); } } } }