package hirondelle.stocks.preferences;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.logging.*;
import java.util.prefs.*;
import hirondelle.stocks.table.QuoteField;
import hirondelle.stocks.util.Util;
import hirondelle.stocks.util.ui.UiConsts;
import hirondelle.stocks.util.ui.UiUtil;
public final class QuoteTablePreferencesEditor extends Observable
implements PreferencesEditor {
@Override public JComponent getUI() {
JPanel content = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
content.setLayout(gridbag);
addSortField(content);
addHorizontalVerticalLines(content);
addRowHeight(content);
addUpdateFrequency(content);
addColumnOrder(content);
addRestore(content);
matchGuiToStoredPrefs();
return content;
}
@Override public String getTitle() {
return TITLE;
}
@Override public int getMnemonic() {
return MNEMONIC;
}
@Override public void savePreferences() {
fLogger.fine("Updating table preferences.");
fPrefs.putBoolean(HORIZONTAL_LINES_KEY, fHorizontalLines.isSelected());
fPrefs.putBoolean(VERTICAL_LINES_KEY, fVerticalLines.isSelected());
fPrefs.putInt(ROW_HEIGHT_KEY, fRowSizeModel.getNumber().intValue());
fPrefs.put(SORT_FIELD_KEY, fSortField.getSelectedItem().toString());
fPrefs.put(COLUMN_ORDER_KEY, fColumnOrderEditor.getItems().toString());
fPrefs.putInt(UPDATE_FREQ_KEY, fUpdateFreqModel.getNumber().intValue());
setChanged();
notifyObservers();
}
@Override public void matchGuiToDefaultPreferences() {
fHorizontalLines.setSelected(HORIZONTAL_LINES_DEFAULT);
fVerticalLines.setSelected(VERTICAL_LINES_DEFAULT);
fRowSizeModel.setValue(new Integer(ROW_HEIGHT_DEFAULT));
fSortField.setSelectedItem(QuoteField.valueFrom(SORT_FIELD_DEFAULT));
fColumnOrderEditor.setItems(parseRawColumnOrder(COLUMN_ORDER_DEFAULT));
fUpdateFreqModel.setValue(new Integer(UPDATE_FREQ_DEFAULT));
}
public boolean hasHorizontalLines() {
return fPrefs.getBoolean(HORIZONTAL_LINES_KEY, HORIZONTAL_LINES_DEFAULT);
}
public boolean hasVerticalLines() {
return fPrefs.getBoolean(VERTICAL_LINES_KEY, VERTICAL_LINES_DEFAULT);
}
public int getRowHeight() {
return fPrefs.getInt(ROW_HEIGHT_KEY, ROW_HEIGHT_DEFAULT);
}
public QuoteField getSortField() {
String fieldName = fPrefs.get(SORT_FIELD_KEY, SORT_FIELD_DEFAULT);
return QuoteField.valueFrom(fieldName);
}
public Set<Object> getColumnOrder() {
return parseRawColumnOrder(fPrefs.get(COLUMN_ORDER_KEY, COLUMN_ORDER_DEFAULT));
}
public int getUpdateFrequency() {
return fPrefs.getInt(UPDATE_FREQ_KEY, UPDATE_FREQ_DEFAULT);
}
private static final String TITLE = "Quote Table";
private static final int MNEMONIC = KeyEvent.VK_Q;
private static final String STOCKS_TABLE_NODE_NAME =
"stocksmonitor/ui/prefs/StocksTable"
;
private static final boolean HORIZONTAL_LINES_DEFAULT = true;
private static final String HORIZONTAL_LINES_KEY = "HorizontalLines";
private static final boolean VERTICAL_LINES_DEFAULT = true;
private static final String VERTICAL_LINES_KEY = "VerticalLines";
private static final int MAX_ROW_HEIGHT = 32;
private static final int MIN_ROW_HEIGHT = 16;
private static final int INITIAL_ROW_HEIGHT = MIN_ROW_HEIGHT;
private static final int STEP_SIZE = 1;
private static final int ROW_HEIGHT_DEFAULT = MIN_ROW_HEIGHT;
private static final String ROW_HEIGHT_KEY = "RowHeight";
private static final String SORT_FIELD_DEFAULT = "Stock";
private static final String SORT_FIELD_KEY = "SortBy";
private static final String COLUMN_ORDER_DEFAULT =
"[Stock, Price, Change, %Change, Profit, %Profit]"
;
private static final String COLUMN_ORDER_KEY = "ColumnOrder";
private static final int MAX_UPDATE_FREQ = 60;
private static final int MIN_UPDATE_FREQ = 1;
private static final int UPDATE_FREQ_DEFAULT = 1; private static final String UPDATE_FREQ_KEY = "UpdateFrequency";
private Preferences fPrefs = Preferences.userRoot().node(STOCKS_TABLE_NODE_NAME);
private JCheckBox fHorizontalLines;
private JCheckBox fVerticalLines;
private SpinnerNumberModel fRowSizeModel;
private JComboBox<QuoteField> fSortField;
private OrderEditor fColumnOrderEditor;
private SpinnerNumberModel fUpdateFreqModel;
private static final Logger fLogger = Util.getLogger(QuoteTablePreferencesEditor.class);
private void addSortField(JPanel aContent) {
JLabel sortBy = new JLabel("Sort By:");
sortBy.setDisplayedMnemonic(KeyEvent.VK_S);
sortBy.setToolTipText("Always descending order");
aContent.add(sortBy, getConstraints(0, 0));
DefaultComboBoxModel<QuoteField>sortByModel = new DefaultComboBoxModel<QuoteField>(
QuoteField.values()
);
fSortField = new JComboBox<QuoteField>(sortByModel);
sortBy.setLabelFor(fSortField);
aContent.add(fSortField, getConstraints(0, 1));
}
private void addHorizontalVerticalLines(JPanel aContent) {
JLabel show = new JLabel("Show:");
aContent.add(show, getConstraints(1, 0));
fHorizontalLines = new JCheckBox("Horizontal Lines");
fHorizontalLines.setMnemonic(KeyEvent.VK_H);
aContent.add(fHorizontalLines, getConstraints(1, 1));
fVerticalLines = new JCheckBox("Vertical Lines");
fVerticalLines.setMnemonic(KeyEvent.VK_V);
aContent.add(fVerticalLines, getConstraints(1, 2, 2, 1));
}
private void addRowHeight(JPanel aContent) {
JLabel rowHeight = new JLabel("Row Height:");
rowHeight.setDisplayedMnemonic(KeyEvent.VK_R);
rowHeight.setToolTipText("Height in pixels of table rows");
aContent.add(rowHeight, getConstraints(2, 0));
fRowSizeModel = new SpinnerNumberModel(
INITIAL_ROW_HEIGHT, MIN_ROW_HEIGHT, MAX_ROW_HEIGHT, STEP_SIZE
);
JSpinner rowHeightSelector = new JSpinner(fRowSizeModel);
rowHeight.setLabelFor(rowHeightSelector);
aContent.add(rowHeightSelector, getConstraints(2, 1));
}
private void addUpdateFrequency(JPanel aContent) {
JLabel updateFreq = new JLabel("Update Freq:");
updateFreq.setDisplayedMnemonic(KeyEvent.VK_U);
updateFreq.setToolTipText("Refresh interval in minutes");
aContent.add(updateFreq, getConstraints(2, 2));
int initialFreqValue = MIN_UPDATE_FREQ;
fUpdateFreqModel = new SpinnerNumberModel(
initialFreqValue, MIN_UPDATE_FREQ, MAX_UPDATE_FREQ, 1
);
JSpinner updateFreqSelector = new JSpinner(fUpdateFreqModel);
updateFreq.setLabelFor(updateFreqSelector);
aContent.add(updateFreqSelector, getConstraints(2, 3));
}
private void addColumnOrder(JPanel aContent) {
JLabel columnOrder = new JLabel("Column Order:");
columnOrder.setDisplayedMnemonic(KeyEvent.VK_C);
GridBagConstraints columnOrderConstraints = getConstraints(3, 0);
columnOrderConstraints.anchor = GridBagConstraints.NORTH;
aContent.add(columnOrder, columnOrderConstraints);
fColumnOrderEditor = new OrderEditor("Up", "Down");
columnOrder.setLabelFor(fColumnOrderEditor);
GridBagConstraints orderEditorConstraints = UiUtil.getConstraints(3, 1);
orderEditorConstraints.insets = new Insets(UiConsts.ONE_SPACE, 0, 0, 0);
aContent.add(fColumnOrderEditor, orderEditorConstraints);
}
private void addRestore(JPanel aContent) {
JButton restore = new JButton("Restore Defaults");
restore.setMnemonic(KeyEvent.VK_D);
restore.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent event) {
matchGuiToDefaultPreferences();
}
});
GridBagConstraints constraints = UiUtil.getConstraints(3, 2, 2, 1);
constraints.anchor = GridBagConstraints.SOUTH;
constraints.insets = new Insets(0, 0, 0, 0);
aContent.add(restore, constraints);
}
private Set<Object> parseRawColumnOrder(String aRawColumnOrderPref) {
java.util.List<String> columnNames = Util.getListFromString(aRawColumnOrderPref);
Set<Object> result = new LinkedHashSet<Object>();
for(String fieldName: columnNames){
result.add(QuoteField.valueFrom(fieldName));
}
assert (result.size() == QuoteField.values().length);
return result;
}
private void matchGuiToStoredPrefs() {
fHorizontalLines.setSelected(hasHorizontalLines());
fVerticalLines.setSelected(hasVerticalLines());
fRowSizeModel.setValue(new Integer(getRowHeight()));
fSortField.setSelectedItem(getSortField());
fColumnOrderEditor.setItems(getColumnOrder());
fUpdateFreqModel.setValue(new Integer(getUpdateFrequency()));
}
private GridBagConstraints getConstraints(int aY, int aX) {
GridBagConstraints result = UiUtil.getConstraints(aY, aX);
addBottom(result);
return result;
}
private GridBagConstraints getConstraints(int aY, int aX, int aWidth, int aHeight) {
GridBagConstraints result = UiUtil.getConstraints(aY, aX, aWidth, aHeight);
addBottom(result);
return result;
}
private void addBottom(GridBagConstraints aConstraints) {
aConstraints.insets = new Insets(0, 0, UiConsts.ONE_SPACE, UiConsts.ONE_SPACE);
}
private static void main(String... aArgs) {
QuoteTablePreferencesEditor thing = new QuoteTablePreferencesEditor();
try {
thing.fPrefs.removeNode();
}
catch (BackingStoreException ex) {
fLogger.severe("Cannot access preferences.");
}
fLogger.severe("Done.");
}
}