controller.addPropertyChangeListener(CompassController.Property.VISIBLE, visibleChangeListener);
}
});
this.latitudeLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, CompassPanel.class, "latitudeLabel.text"));
final SpinnerNumberModel latitudeSpinnerModel = new SpinnerNumberModel(new Float(0), new Float(-90), new Float(90), new Float(5));
this.latitudeSpinner = new JSpinner(latitudeSpinnerModel);
// Change positive / negative notation by North / South
JFormattedTextField textField = ((DefaultEditor)this.latitudeSpinner.getEditor()).getTextField();
NumberFormatter numberFormatter = (NumberFormatter)((DefaultFormatterFactory)textField.getFormatterFactory()).getDefaultFormatter();
numberFormatter.setFormat(new DecimalFormat("N ##0.000;S ##0.000"));
textField.setFormatterFactory(new DefaultFormatterFactory(numberFormatter));
SwingTools.addAutoSelectionOnFocusGain(textField);
latitudeSpinnerModel.setValue(controller.getLatitudeInDegrees());
final PropertyChangeListener latitudeChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
latitudeSpinnerModel.setValue((Float)ev.getNewValue());
}
};
controller.addPropertyChangeListener(CompassController.Property.LATITUDE_IN_DEGREES, latitudeChangeListener);
latitudeSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(CompassController.Property.LATITUDE_IN_DEGREES, latitudeChangeListener);
controller.setLatitudeInDegrees(((Number)latitudeSpinnerModel.getValue()).floatValue());
controller.addPropertyChangeListener(CompassController.Property.LATITUDE_IN_DEGREES, latitudeChangeListener);
}
});
this.longitudeLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, CompassPanel.class, "longitudeLabel.text"));
final SpinnerNumberModel longitudeSpinnerModel = new SpinnerNumberModel(new Float(0), new Float(-180), new Float(180), new Float(5));
this.longitudeSpinner = new JSpinner(longitudeSpinnerModel);
// Change positive / negative notation by East / West
textField = ((DefaultEditor)this.longitudeSpinner.getEditor()).getTextField();
numberFormatter = (NumberFormatter)((DefaultFormatterFactory)textField.getFormatterFactory()).getDefaultFormatter();
numberFormatter.setFormat(new DecimalFormat("E ##0.000;W ##0.000"));
textField.setFormatterFactory(new DefaultFormatterFactory(numberFormatter));
SwingTools.addAutoSelectionOnFocusGain(textField);
longitudeSpinnerModel.setValue(controller.getLongitudeInDegrees());
final PropertyChangeListener longitudeChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
longitudeSpinnerModel.setValue((Float)ev.getNewValue());
}
};
controller.addPropertyChangeListener(CompassController.Property.LONGITUDE_IN_DEGREES, longitudeChangeListener);
longitudeSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(CompassController.Property.LONGITUDE_IN_DEGREES, longitudeChangeListener);
controller.setLongitudeInDegrees(((Number)longitudeSpinnerModel.getValue()).floatValue());
controller.addPropertyChangeListener(CompassController.Property.LONGITUDE_IN_DEGREES, longitudeChangeListener);
}
});
this.timeZoneLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, CompassPanel.class, "timeZoneLabel.text"));
List<String> timeZoneIds = new ArrayList<String>(Arrays.asList(TimeZone.getAvailableIDs()));
// Remove synonymous time zones
timeZoneIds.remove("GMT");
timeZoneIds.remove("GMT0");
timeZoneIds.remove("Etc/GMT0");
timeZoneIds.remove("Etc/GMT-0");
timeZoneIds.remove("Etc/GMT+0");
// Replace Etc/GMT... ids by their English value that are less misleading
for (int i = 0; i < timeZoneIds.size(); i++) {
String timeZoneId = timeZoneIds.get(i);
if (timeZoneId.startsWith("Etc/GMT")) {
timeZoneIds.set(i, TimeZone.getTimeZone(timeZoneId).getDisplayName(Locale.ENGLISH));
}
}
String [] timeZoneIdsArray = timeZoneIds.toArray(new String [timeZoneIds.size()]);
Arrays.sort(timeZoneIdsArray);
this.timeZoneComboBox = new JComboBox(timeZoneIdsArray);
this.timeZoneComboBox.setSelectedItem(controller.getTimeZone());
final PropertyChangeListener timeZoneChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
timeZoneComboBox.setSelectedItem(ev.getNewValue());
}
};
controller.addPropertyChangeListener(CompassController.Property.TIME_ZONE, timeZoneChangeListener);
this.timeZoneComboBox.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
String timeZoneId = (String)value;
if (timeZoneId.startsWith("GMT")) {
if (!OperatingSystem.isMacOSX()) {
setToolTipText(timeZoneId);
}
} else {
String timeZoneDisplayName = TimeZone.getTimeZone(timeZoneId).getDisplayName();
if (OperatingSystem.isMacOSX()) {
value = timeZoneId + " - " + timeZoneDisplayName;
} else {
// Use tool tip do display the complete time zone information
setToolTipText(timeZoneId + " - " + timeZoneDisplayName);
}
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
this.timeZoneComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
controller.removePropertyChangeListener(CompassController.Property.TIME_ZONE, timeZoneChangeListener);
controller.setTimeZone((String)timeZoneComboBox.getSelectedItem());
controller.addPropertyChangeListener(CompassController.Property.TIME_ZONE, timeZoneChangeListener);
}
});
this.timeZoneComboBox.setPrototypeDisplayValue("GMT");
this.northDirectionLabel = new JLabel(SwingTools.getLocalizedLabelText(preferences, CompassPanel.class, "northDirectionLabel.text"));
// Create a spinner model able to choose an angle modulo 360
final SpinnerNumberModel northDirectionSpinnerModel = new SpinnerNumberModel(0, 0, 360, 5) {
@Override
public Object getNextValue() {
if (((Number)getValue()).intValue() + ((Number)getStepSize()).intValue() < ((Number)getMaximum()).intValue()) {
return super.getNextValue();
} else {
return ((Number)getValue()).intValue() + ((Number)getStepSize()).intValue() - ((Number)getMaximum()).intValue() + ((Number)getMinimum()).intValue();
}
}
@Override
public Object getPreviousValue() {
if (((Number)getValue()).intValue() - ((Number)getStepSize()).intValue() >= ((Number)getMinimum()).intValue()) {
return super.getPreviousValue();
} else {
return ((Number)getValue()).intValue() - ((Number)getStepSize()).intValue() - ((Number)getMinimum()).intValue() + ((Number)getMaximum()).intValue();
}
}
};
this.northDirectionSpinner = new AutoCommitSpinner(northDirectionSpinnerModel);
northDirectionSpinnerModel.setValue(new Integer(Math.round(controller.getNorthDirectionInDegrees())));
this.northDirectionComponent = new JComponent() {
@Override
public Dimension getPreferredSize() {
return new Dimension(35, 35);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2D.translate(getWidth() / 2, getHeight() / 2);
g2D.scale(getWidth() / 2, getWidth() / 2);
g2D.rotate(Math.toRadians(controller.getNorthDirectionInDegrees()));
// Draw a round arc
g2D.setStroke(new BasicStroke(0.5f / getWidth()));
g2D.draw(new Ellipse2D.Float(-0.7f, -0.7f, 1.4f, 1.4f));
g2D.draw(new Line2D.Float(-0.85f, 0, -0.7f, 0));
g2D.draw(new Line2D.Float(0.85f, 0, 0.7f, 0));
g2D.draw(new Line2D.Float(0, -0.8f, 0, -0.7f));
g2D.draw(new Line2D.Float(0, 0.85f, 0, 0.7f));
// Draw a N
GeneralPath path = new GeneralPath();
path.moveTo(-0.1f, -0.8f);
path.lineTo(-0.1f, -1f);
path.lineTo(0.1f, -0.8f);
path.lineTo(0.1f, -1f);
g2D.setStroke(new BasicStroke(1.5f / getWidth()));
g2D.draw(path);
// Draw the needle
GeneralPath needlePath = new GeneralPath();
needlePath.moveTo(0, -0.75f);
needlePath.lineTo(0.2f, 0.7f);
needlePath.lineTo(0, 0.5f);
needlePath.lineTo(-0.2f, 0.7f);
needlePath.closePath();
needlePath.moveTo(-0.02f, 0);
needlePath.lineTo(0.02f, 0);
g2D.setStroke(new BasicStroke(4 / getWidth()));
g2D.draw(needlePath);
}
};
this.northDirectionComponent.setOpaque(false);
final PropertyChangeListener northDirectionChangeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
northDirectionSpinnerModel.setValue(((Number)ev.getNewValue()).intValue());
northDirectionComponent.repaint();
}
};
controller.addPropertyChangeListener(CompassController.Property.NORTH_DIRECTION_IN_DEGREES, northDirectionChangeListener);
northDirectionSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ev) {
controller.removePropertyChangeListener(CompassController.Property.NORTH_DIRECTION_IN_DEGREES, northDirectionChangeListener);
controller.setNorthDirectionInDegrees(((Number)northDirectionSpinnerModel.getValue()).floatValue());
northDirectionComponent.repaint();
controller.addPropertyChangeListener(CompassController.Property.NORTH_DIRECTION_IN_DEGREES, northDirectionChangeListener);
}
});