omgraphichandlerlayer.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,519 行 · 第 1/4 页
JAVA
1,519 行
* reason the OMGraphicList is nulled out is so if another layer finishes
* before yours does and gets repainted, your old OMGraphics don't get
* painted along side their new ones - it's a mismatched situation. You can
* set the ProjectionChangePolicy directly with the
* setProjectionChangePolicy, or by overriding the getProjectionChangePolicy
* method and returning the type you want by default if it is null.
*
* @see com.bbn.openmap.layer.policy.ProjectionChangePolicy
* @see com.bbn.openmap.layer.policy.StandardPCPolicy
* @see com.bbn.openmap.layer.policy.ListResetPCPolicy
*/
public void projectionChanged(ProjectionEvent pe) {
if (Debug.debugging("layer")) {
Debug.output("OMGraphicHandlerLayer " + getName()
+ " projection changed, calling "
+ getProjectionChangePolicy().getClass().getName());
}
getProjectionChangePolicy().projectionChanged(pe);
}
/**
* Get the ProjectionChangePolicy that determines how a layer reacts and
* gathers OMGraphics for a projection change.
*/
public ProjectionChangePolicy getProjectionChangePolicy() {
if (projectionChangePolicy == null) {
projectionChangePolicy = new StandardPCPolicy(this);
}
return projectionChangePolicy;
}
/**
* Set the ProjectionChangePolicy that determines how a layer reacts and
* gathers OMGraphics for a projection change.
*/
public void setProjectionChangePolicy(ProjectionChangePolicy pcp) {
projectionChangePolicy = pcp;
// Just to make sure,
pcp.setLayer(this);
}
/**
* Get the RenderPolicy that determines how an OMGraphicList is rendered.
*/
public RenderPolicy getRenderPolicy() {
if (renderPolicy == null) {
renderPolicy = new StandardRenderPolicy(this);
}
return renderPolicy;
}
/**
* Set the RenderPolicy that determines how the OMGraphicList is rendered.
*/
public void setRenderPolicy(RenderPolicy rp) {
renderPolicy = rp;
// Just to make sure,
rp.setLayer(this);
}
protected void interrupt() {
try {
synchronized (LAYERWORKER_LOCK) {
if (layerWorker != null && interruptable) {
layerWorker.interrupt();
}
}
} catch (SecurityException se) {
Debug.output(getName()
+ " layer caught a SecurityException when something tried to stop work on the worker thread");
}
}
/**
* Sets the SwingWorker off to call prepare(). If the SwingWorker passed in
* is not null, start() is called on it.
*
* @param worker null to reset the layerWorker variable, or a SwingWorker to
* start up.
*/
protected void setLayerWorker(SwingWorker worker) {
synchronized (LAYERWORKER_LOCK) {
layerWorker = worker;
if (layerWorker != null) {
layerWorker.start();
}
}
}
protected SwingWorker getLayerWorker() {
return layerWorker;
}
/**
* Called from within the layer to create a LayerWorker to use for the
* prepare() method. By default, a new LayerWorker is returned. This method
* may be overridden to make the layer use an extended
* LayerWorker/SwingWorker class.
*
* @return SwingWorker/LayerWorker
*/
protected SwingWorker createLayerWorker() {
return new LayerWorker();
}
/**
* This method is here to provide a default action for Layers as they act as
* a ProjectionPainter. Normally, ProjectionPainters are expected to receive
* the projection, gather/create OMGraphics that apply to the projection,
* and render them into the Graphics provided. This is supposed to be done
* in the same thread that calls this function, so the caller knows that
* when this method returns, everything that the ProjectionPainter needed to
* do is complete.
* <P>
* If the layer doesn't override this method, then the paint(Graphics)
* method will be called.
*
* @param proj Projection of the map.
* @param g java.awt.Graphics to draw into.
*/
public synchronized void renderDataForProjection(Projection proj, Graphics g) {
if (proj == null) {
Debug.error("Layer(" + getName()
+ ").renderDataForProjection: null projection!");
return;
} else if (!proj.equals(getProjection())) {
setProjection(proj.makeClone());
setList(prepare());
}
paint(g);
}
/**
* The default action is to get the OMGraphicList and render it.
*
* @param g java.awt.Graphics object to render OMGraphics into.
*/
public void paint(Graphics g) {
getRenderPolicy().paint(g);
}
/**
* A method that will launch a LayerWorker thread to call the prepare
* method. This method will set in motion all the steps needed to create and
* render the current OMGraphicList with the current projection. Nothing
* more needs to be called, because the LayerWorker will be started, it will
* call prepare(). Inside the prepare() method, the OMGraphicList should be
* created and the OMGraphics generated for the current projection that can
* be picked up in the getProjection() method, and the LayerWorker will call
* workerComplete() which will call repaint() on this layer.
*/
public void doPrepare() {
synchronized (LAYERWORKER_LOCK) {
if (isWorking()) {
if (Debug.debugging("layer")) {
Debug.output(getName()
+ " layer already working in prepare(), cancelling");
}
setCancelled(true);
return;
}
// If there isn't a worker thread working on a projection
// changed or other doPrepare call, then create a thread that
// will do the real work. If there is a thread working on
// this, then set the cancelled flag in the layer.
setLayerWorker(createLayerWorker());
}
}
/**
* A check to see if the SwingWorker is doing something.
*/
public boolean isWorking() {
synchronized (LAYERWORKER_LOCK) {
return (layerWorker != null && !layerWorker.isInterrupted());
}
}
/**
* This is the main method you should be concerned with when overriding this
* class. You have to make sure that this method returns an OMGraphicList
* that is ready to be rendered. That means they need to be generated with
* the current projection, which can be retrieved by calling
* getProjection().
* <P>
*
* This method will be called in a separate thread if doPrepare() is called
* on the layer. This will automatically cause repaint() to be called, which
* lets java know to call paint() on this class.
* <P>
*
* Note that the default action of this method is to get the OMGraphicList
* as it is currently set in the layer, reprojects the list with the current
* projection (calls generate() on them), and then returns the current list.
* <P>
*
* If your layer needs to change what is on the list based on what the
* current projection is, you can either clear() the list yourself and add
* new OMGraphics to it (remember to call generate(Projection) on them), and
* return the list. You also have the option of setting a ListResetPCPolicy,
* which will automatically set the list to null when the projection changes
* before calling this method. The OMGraphicHandlerList will ignore a null
* OMGraphicList.
* <P>
*
* NOTE: If you call prepare directly, you may need to call repaint(), too.
* With all invocations of this method that are cause by a projection
* change, repaint() will be called for you.
*
* The method is synchronized in case renderDataForProjection() gets called
* while in the middle of this method. For a different projection, that
* would be bad.
*/
public synchronized OMGraphicList prepare() {
OMGraphicList currentList = getList();
Projection proj = getProjection();
// if the layer hasn't been added to the MapBean
// the projection could be null.
if (currentList != null && proj != null) {
currentList.generate(proj);
}
return currentList;
}
/**
* Set when the something has changed while a swing worker is gathering
* graphics, and we want it to stop early.
*/
// protected boolean cancelled = false;
// protected Object CANCELLED_LOCK = new Object();
protected final Object LAYERWORKER_LOCK = new Object();
/**
* Used to set the cancelled flag in the layer. The swing worker checks this
* once in a while to see if the projection has changed since it started
* working. If this is set to true, the swing worker quits when it is safe.
*/
public void setCancelled(boolean set) {
// synchronized (CANCELLED_LOCK) {
synchronized (LAYERWORKER_LOCK) {
// cancelled = set;
if (set) {
interrupt();// if the layerWorker is busy, stop it.
// System.out.println(">>Interrupting (setCancelled)");
}
}
}
/** Check to see if the cancelled flag has been set. */
public boolean isCancelled() {
synchronized (LAYERWORKER_LOCK) {
return layerWorker != null && layerWorker.isInterrupted();
}
/*
* boolean ret = false; synchronized (CANCELLED_LOCK) { ret = cancelled; }
* return ret;
*/
}
/**
* The LayerWorker calls this method on the layer when it is done working.
* If the calling worker is not the same as the "current" worker, then a new
* worker is created.
*
* @param worker the worker that has the graphics.
*/
protected void workerComplete(LayerWorker worker) {
synchronized (LAYERWORKER_LOCK) {
if (layerWorker != worker) {
return; //
}
if (layerWorker.isInterrupted()) {
setCancelled(false); // reset
setLayerWorker(createLayerWorker()); // try again with
// current proj
return;
}
// success!
setLayerWorker(null);
getProjectionChangePolicy().workerComplete((OMGraphicList) worker.get());
}
repaint();
/*
* if (!isCancelled()) { setLayerWorker(null);
* getProjectionChangePolicy().workerComplete((OMGraphicList)
* worker.get()); repaint(); } else { setCancelled(false);
* setLayerWorker(createLayerWorker()); }
*/
}
/**
* Since we can't have the main thread taking up the time to do the work to
* create OMGraphics, we use this worker thread to do it.
*/
class LayerWorker extends SwingWorker {
/** Constructor used to create a worker thread. */
public LayerWorker() {
super();
}
/**
* Compute the value to be returned by the <code>get</code> method.
*/
public Object construct() {
Debug.message("layer", getName() + "|LayerWorker.construct()");
fireStatusUpdate(LayerStatusEvent.START_WORKING);
String msg;
try {
long start = System.currentTimeMillis();
OMGraphicList list = getRenderPolicy().prepare();
long stop = System.currentTimeMillis();
if (Debug.debugging("layer")) {
Debug.output(getName()
+ "|LayerWorker.construct(): fetched "
+ (list == null ? "null list "
: (list.size() + " graphics ")) + "in "
+ (double) ((stop - start) / 1000d) + " seconds");
}
return list;
} catch (OutOfMemoryError e) {
msg = getName() + "|LayerWorker.construct(): " + e.getMessage();
if (Debug.debugging("layer")) {
Debug.output(msg);
e.printStackTrace();
} else {
Debug.output(getName()
+ " layer ran out of memory, attempting to recover...");
}
} catch (Exception e) {
msg = getName() + "|LayerWorker.construct(): " + e.getMessage();
Debug.output(msg);
if (Debug.debugging("layer")) {
e.printStackTrace();
}
}
// This is only called if there is an error.
if (Debug.debugging("displayLayerErrors")) {
fireRequestMessage(new InfoDisplayEvent(this, msg));
}
return null;
}
/**
* Called on the event dispatching thread (not on the worker thread)
* after the <code>construct</code> method has returned.
*/
public void finished() {
workerComplete(this);
if (!isInterrupted()) {
fireStatusUpdate(LayerStatusEvent.FINISH_WORKING);
}
}
public String toString() {
return getName() + " LayerWorker";
}
}
/**
* Overrides the Layer setProperties method. Also calls Layer's version. If
* the ProjectionChangePolicy and RenderPolicy objects are set
* programmatically and are PropertyConsumers, they will still have access
* to properties if this method is called. Their property prefix will be
* scoped as if the OMGraphicHandlerLayer had them created, with their
* prefix being prefix + . + PropertyChangePolicyProperty and prefix + . +
* RenderPolicyProperty.
*
* @param prefix the token to prefix the property names
* @param props the <code>Properties</code> object
*/
public void setProperties(String prefix, Properties props) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?