/*
* Created on Mar 9, 2007
*
* Copyright (c) 2007 Jens Gulden
*
* 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 java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import com.frinika.sequencer.model.util.TimeUtils;
/**
* JSpinner extended to display and edit time-values of the form "bar.beat:tick".
*
* @author Jens Gulden
*/
public class TickSpinner extends JSpinnerDraggable implements CaretListener {
public TickSpinner() {
super();
init();
}
public TickSpinner(TickSpinnerModel model) {
super(model);
init();
}
public TickSpinner(TimeFormat format, long value, TimeUtils timeUtils) {
this(format, value, false, timeUtils);
}
public TickSpinner(TimeFormat format, long value, boolean allowNegative, TimeUtils timeUtils) {
this(new TickSpinnerModel(format, value, allowNegative, timeUtils));
}
public TickSpinner(TimeFormat format, TimeUtils timeUtils) {
this(format, 0, timeUtils);
}
public Object getNextValue() {
return super.getNextValue();
}
private void init() {
JFormattedTextField ftf = (JFormattedTextField)((JSpinner.DefaultEditor)this.getEditor()).getTextField(); // ! depends on swing implementation to actually use FormattedTextField
ftf.setColumns(((TickSpinnerModel)getModel()).format.textFieldSize);
ftf.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
@Override
public AbstractFormatter getFormatter(JFormattedTextField tf) {
return new JFormattedTextField.AbstractFormatter() {
@Override
public Object stringToValue(String text) throws ParseException {
return ((TickSpinnerModel)getModel()).stringToTicks(text);
}
@Override
public String valueToString(Object value) throws ParseException {
return ((TickSpinnerModel)getModel()).ticksToString((Long)value);
}
};
}
});
ftf.addCaretListener(this);
}
@Override
public void commitEdit() throws ParseException {
final JTextField textField = ((JSpinner.DefaultEditor)this.getEditor()).getTextField();
final int pos = textField.getCaretPosition();
super.commitEdit();
(new Thread() {
public void run() {
try {
//Thread.sleep(50); // 50 ms ok?
textField.setCaretPosition(pos); // reset old caret position after all event handling is done
} catch (IllegalArgumentException ie) {
ie.printStackTrace();
}
}
}).start();
}
public void caretUpdate(CaretEvent e) {
// depending on the position in the formatted string, set different step sizes so that up/down arrows will modify the part in which the cursor is
TickSpinnerModel model = (TickSpinnerModel)getModel();
JTextField textField = ((JSpinner.DefaultEditor)this.getEditor()).getTextField();
int pos = textField.getCaretPosition();
//int stepSize = stepSizeForPosition(model.getFormat(), textField.getText(), pos);
model.updateStepSize(textField.getText(), pos);
//model.setStepSize(stepSize);
}
/*protected JComponent createEditor(SpinnerModel model) {
return super.createEditor(model);
}*/
/*@Override
public void commitEdit() throws ParseException {
super.commitEdit();
}*/
}