package org.hwo.ui; import javax.swing.JComponent; import java.awt.GridBagLayout; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.util.LinkedList; import java.util.List; import javax.swing.JLabel; public class JTimeSpanEditor extends JComponent implements FocusListener { private JSpinner spDays; private JSpinner spHours; private JSpinner spMinutes; private JSpinner spSeconds; private JLabel lblD; private JLabel lblNewLabel; private JLabel label; private List focusListeners; private List components; public JTimeSpanEditor() { this.focusListeners = new LinkedList(); GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[] {0, 0, 0, 0, 0, 0, 0}; gridBagLayout.rowHeights = new int[]{0, 0}; gridBagLayout.columnWeights = new double[]{1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0}; gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE}; setLayout(gridBagLayout); spDays = new JSpinner(); spDays.addFocusListener(this); spDays.getEditor().addFocusListener(this); spDays.setModel(new SpinnerNumberModel(0, 0, 366, 1)); GridBagConstraints gbc_spDays = new GridBagConstraints(); gbc_spDays.fill = GridBagConstraints.BOTH; gbc_spDays.insets = new Insets(0, 0, 0, 5); gbc_spDays.gridx = 0; gbc_spDays.gridy = 0; add(spDays, gbc_spDays); lblD = new JLabel("d"); GridBagConstraints gbc_lblD = new GridBagConstraints(); gbc_lblD.insets = new Insets(0, 0, 0, 5); gbc_lblD.gridx = 1; gbc_lblD.gridy = 0; add(lblD, gbc_lblD); spHours = new JSpinner(); spHours.addFocusListener(this); spHours.setFocusable(true); spHours.getEditor().addFocusListener(this); spHours.setModel(new SpinnerNumberModel(0, 0, 23, 1)); GridBagConstraints gbc_spHours = new GridBagConstraints(); gbc_spHours.fill = GridBagConstraints.BOTH; gbc_spHours.insets = new Insets(0, 0, 0, 5); gbc_spHours.gridx = 2; gbc_spHours.gridy = 0; add(spHours, gbc_spHours); lblNewLabel = new JLabel(":"); GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5); gbc_lblNewLabel.gridx = 3; gbc_lblNewLabel.gridy = 0; add(lblNewLabel, gbc_lblNewLabel); spMinutes = new JSpinner(); spMinutes.addFocusListener(this); spMinutes.getEditor().addFocusListener(this); spMinutes.setModel(new SpinnerNumberModel(0, 0, 59, 1)); GridBagConstraints gbc_spMinutes = new GridBagConstraints(); gbc_spMinutes.fill = GridBagConstraints.BOTH; gbc_spMinutes.insets = new Insets(0, 0, 0, 5); gbc_spMinutes.gridx = 4; gbc_spMinutes.gridy = 0; add(spMinutes, gbc_spMinutes); label = new JLabel(":"); GridBagConstraints gbc_label = new GridBagConstraints(); gbc_label.insets = new Insets(0, 0, 0, 5); gbc_label.gridx = 5; gbc_label.gridy = 0; add(label, gbc_label); spSeconds = new JSpinner(); spSeconds.addFocusListener(this); spSeconds.getEditor().addFocusListener(this); spSeconds.setModel(new SpinnerNumberModel(0, 0, 59, 1)); GridBagConstraints gbc_spSeconds = new GridBagConstraints(); gbc_spSeconds.fill = GridBagConstraints.BOTH; gbc_spSeconds.gridx = 6; gbc_spSeconds.gridy = 0; add(spSeconds, gbc_spSeconds); components = UIHelper.getComponentsRecursive(this); setupFocusListeners(); } private void setupFocusListeners(){ setupFocusListener(UIHelper.getComponentsRecursive(spDays)); setupFocusListener(UIHelper.getComponentsRecursive(spHours)); setupFocusListener(UIHelper.getComponentsRecursive(spMinutes)); setupFocusListener(UIHelper.getComponentsRecursive(spSeconds)); } private void setupFocusListener(List cl){ for (Component c: cl) c.addFocusListener(this); } @Override public synchronized void addFocusListener(FocusListener l) { focusListeners.add(l); } @Override public synchronized void removeFocusListener(FocusListener l) { focusListeners.remove(l); } private void fireFocusLost(Component other){ FocusEvent fe = new FocusEvent(this, FocusEvent.FOCUS_LOST, false, other); for (FocusListener l:focusListeners) l.focusLost(fe); } private void fireFocusGained(Component other){ FocusEvent fe = new FocusEvent(this, FocusEvent.FOCUS_GAINED, false, other); for (FocusListener l:focusListeners) l.focusGained(fe); } public Integer getValue(){ if (!spSeconds.isEnabled()) return null; return ((Integer)spSeconds.getValue()) + ((Integer)spMinutes.getValue()) * 60 + ((Integer)spHours.getValue()) * 3600 + ((Integer)spDays.getValue()) * 86400 ; } public void setValue(Integer seconds){ Integer mod = seconds; if (mod == null){ spSeconds.setEnabled(false); spMinutes.setEnabled(false); spHours.setEnabled(false); spDays.setEnabled(false); } else { spSeconds.setEnabled(true); spMinutes.setEnabled(true); spHours.setEnabled(true); spDays.setEnabled(true); if (spDays.isVisible()) spDays.setValue(mod / 86400); mod %= 86400; spHours.setValue(mod / 3600); mod %= 3600; spMinutes.setValue(mod / 60); mod %= 60; spSeconds.setValue(mod); } } public boolean isDaysEnabled(){ return spDays.isVisible(); } public void setDaysEnabled(boolean daysEnabled){ if (!daysEnabled){ spDays.setValue(new Integer(0)); } spDays.setVisible(daysEnabled); spDays.setEnabled(daysEnabled); lblD.setVisible(daysEnabled); } public void focusLost(FocusEvent e) { if (!components.contains(e.getOppositeComponent())){ System.err.println("JTimeSpanEditor: Focus Lost " + this); System.err.println("Source: " + e.getSource()); System.err.println("Other: " + e.getOppositeComponent()); System.err.println(""); fireFocusLost(e.getOppositeComponent()); } } public void focusGained(FocusEvent e) { if (!components.contains(e.getOppositeComponent())){ System.err.println("JTimeSpanEditor: Focus Gained " + this); System.err.println("Source: " + e.getSource()); System.err.println("Other: " + e.getOppositeComponent()); System.err.println(""); fireFocusGained(e.getOppositeComponent()); } } }