// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/location/TimerLocationLayer.java,v $
// $RCSfile: TimerLocationLayer.java,v $
// $Revision: 1.4.2.2 $
// $Date: 2006/01/18 17:51:02 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.layer.location;
/* Java Core */
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Properties;
import javax.swing.Box;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.Timer;
/* Openmap */
import com.bbn.openmap.util.PropUtils;
import com.bbn.openmap.event.ProjectionEvent;
/**
* The TimerLocationLayer is a LocationLayer that has a timer to
* automatically relod data at specified interval.
*
* The properties for this layer are the same as a LocationLayer, with
* the addition of two:
* <P>
*
* <pre>
*
* # Specify the interval (milliseconds) for the timer. Default is 10 seconds.
* layer.updateTimerInterval=10000
* # Auto-start/stop the timer when the layer is part of the Default
* # is true. There is a control to start/stop the timer on the
* # palette.
* layer.automaticTimer=true;
*
* </pre>
*/
public class TimerLocationLayer extends LocationLayer {
/** Reloading timer. */
protected Timer timer;
/** updateTimerInterval */
public static final String UpdateTimerIntervalProperty = "updateTimerInterval";
/** automaticTimer */
public static final String AutoTimerProperty = "automaticTimer";
/**
* Flag to note whether file reloading should only happen when the
* layer is visible. True by default.
*/
protected boolean autoTimer = true;
private final com.bbn.openmap.Layer layer = this;
/**
* The default constructor for the Layer. All of the attributes
* are set to their default values.
*/
public TimerLocationLayer() {
addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent e) {
if (e.getComponent() == layer && getAutoTimer()
&& timerButton != null && !timerButton.isSelected()) {
timerButton.doClick();
}
}
public void componentHidden(ComponentEvent e) {
if (e.getComponent() == layer && getAutoTimer()
&& timerButton != null && timerButton.isSelected()) {
timerButton.doClick();
}
}
});
}
public void projectionChanged(ProjectionEvent e) {
super.projectionChanged(e);
if (autoTimer
&& timer != null
&& ((timerButton != null && timerButton.isSelected()) || (timerButton == null && getUpdateInterval() > 0))) {
timer.restart();
updateTimerButton();
}
}
/**
* This method is called after the layer is removed from the
* MapBean and when the projection changes. If the autoTimer is
* set, the timer is stopped.
*/
public void removed(java.awt.Container cont) {
if (autoTimer) {
timer.stop();
updateTimerButton();
}
}
protected JCheckBox timerButton = null;
protected JCheckBox autoTimerButton = null;
/**
* Provides the palette widgets to control the options of showing
* maps, or attribute text.
*
* @return Component object representing the palette widgets.
*/
public java.awt.Component getGUI() {
box = null;
box = (Box) super.getGUI();
// Only want to do this once...
if (getTimer() != null) {
if (timerButton == null) {
String bTitle = "Run Update Timer";
int interval = getUpdateInterval();
if (interval > 0) {
bTitle = "Reload Data (" + (interval / 1000) + " sec)";
}
timerButton = new JCheckBox(bTitle, getTimer().isRunning());
timerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JCheckBox check = (JCheckBox) ae.getSource();
Timer t = getTimer();
if (t != null) {
if (check.isSelected()) {
t.restart();
} else {
t.stop();
}
}
}
});
timerButton.setToolTipText("<HTML><BODY>Reload the map data from the original source at specified intervals.</BODY></HTML>");
}
if (autoTimerButton == null) {
autoTimerButton = new JCheckBox("Reload Only When Visible", getAutoTimer());
autoTimerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JCheckBox check = (JCheckBox) ae.getSource();
setAutoTimer(check.isSelected());
}
});
autoTimerButton.setToolTipText("<HTML><BODY>Only run the timer when the layer is active on the map.</BODY></HTML>");
}
JPanel tbp = new JPanel(new GridLayout(0, 1));
tbp.add(timerButton);
tbp.add(autoTimerButton);
box.add(tbp);
}
return box;
}
/**
* The properties and prefix are managed and decoded here, for the
* standard uses of the LocationLayer.
*
* @param prefix string prefix used in the properties file for
* this layer.
* @param properties the properties set in the properties file.
*/
public void setProperties(String prefix, Properties properties) {
super.setProperties(prefix, properties);
String realPrefix = "";
if (prefix != null) {
realPrefix = prefix + ".";
}
setUpdateInterval(PropUtils.intFromProperties(properties, realPrefix
+ UpdateTimerIntervalProperty, updateInterval));
setAutoTimer(PropUtils.booleanFromProperties(properties, realPrefix
+ AutoTimerProperty, autoTimer));
}
/**
* PropertyConsumer method, to fill in a Properties object,
* reflecting the current values of the layer. If the layer has a
* propertyPrefix set, the property keys should have that prefix
* plus a separating '.' prepended to each propery key it uses for
* configuration.
*
* @param props a Properties object to load the PropertyConsumer
* properties into. If props equals null, then a new
* Properties object should be created.
* @return Properties object containing PropertyConsumer property
* values. If getList was not null, this should equal
* getList. Otherwise, it should be the Properties object
* created by the PropertyConsumer.
*/
public Properties getProperties(Properties props) {
props = super.getProperties(props);
String prefix = PropUtils.getScopedPropertyPrefix(this);
props.put(prefix + UpdateTimerIntervalProperty,
Integer.toString(updateInterval));
props.put(prefix + AutoTimerProperty, new Boolean(autoTimer).toString());
return props;
}
/**
* Method to fill in a Properties object with values reflecting
* the properties able to be set on this PropertyConsumer. The key
* for each property should be the raw property name (without a
* prefix) with a value that is a String that describes what the
* property key represents, along with any other information about
* the property that would be helpful (range, default value,
* etc.). For Layer, this method should at least return the
* 'prettyName' property.
*
* @param list a Properties object to load the PropertyConsumer
* properties into. If getList equals null, then a new
* Properties object should be created.
* @return Properties object containing PropertyConsumer property
* values. If getList was not null, this should equal
* getList. Otherwise, it should be the Properties object
* created by the PropertyConsumer.
*/
public Properties getPropertyInfo(Properties list) {
list = super.getPropertyInfo(list);
PropUtils.setI18NPropertyInfo(i18n,
list,
TimerLocationLayer.class,
UpdateTimerIntervalProperty,
"Timer interval",
"Number of milliseconds for automatic file reloading.", null);
PropUtils.setI18NPropertyInfo(i18n,
list,
TimerLocationLayer.class,
AutoTimerProperty,
"Auto Timer",
"Flag to start/stop timer automatically when layer is on map.",
"com.bbn.openmap.util.propertyEditor.OnOffPropertyEditor");
return list;
}
/**
* Sets whether the timer should automatically be turned on and
* off when the layer is added and removed from the map.
* <P>
*
* If the layer is not visible, the timer may be started or
* stopped when this method is called. If the autoTimer is turned
* off, and the layer has received a projection before, the timer
* is turned on. If the autoTimer is on, the timer will be
* stopped.
*/
public void setAutoTimer(boolean value) {
autoTimer = value;
if (autoTimerButton != null) {
autoTimerButton.setSelected(getAutoTimer());
}
if (!isVisible()) {
if (!value && getProjection() != null) {
timer.restart();
} else if (value) {
timer.stop();
}
}
}
public boolean getAutoTimer() {
return autoTimer;
}
/**
* Get the timer being used for automatic updates. May be null if
* a timer is not set.
*/
public Timer getTimer() {
return timer;
}
/**
* If you want the layer to update itself at certain intervals,
* you can set the timer to do that. Set it to null to disable it.
*/
public void setTimer(Timer t) {
if (timer != null) {
timer.stop();
}
timer = t;
updateTimerButton();
}
/**
* What to do when the timer goes off.
*/
public void timerPing() {
reloadData();
if (isVisible()) {
doPrepare();
}
}
/**
* Creates a timer with the current updateInterval and calls
* setTimer().
*/
public void createTimer() {
Timer t = new Timer(updateInterval, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
timerPing();
}
});
t.setInitialDelay(0);
setTimer(t);
}
/**
* The delay between timer pulses, in milliseconds. Default is 10
* seconds.
*/
protected int updateInterval = 10000;
/**
* Set how often the timer calls timerPing. If less than or equal
* to zero, the timer will be stopped, but the interval will not
* be affected.
*/
public void setUpdateInterval(int delay) {
if (delay > 0) {
updateInterval = delay;
if (timer == null) {
createTimer();
}
timer.setDelay(updateInterval);
if (timer.isRunning()) {
timer.restart();
}
} else if (timer != null) {
timer.stop();
}
updateTimerButton();
}
public int getUpdateInterval() {
return updateInterval;
}
/**
* Enable the timer button if there is a timer, check it on if the
* timer is running.
*/
protected void updateTimerButton() {
if (timerButton != null) {
timerButton.setEnabled(timer != null);
timerButton.setSelected(timer != null && timer.isRunning());
}
}
}