📄 omgraphichandlerlayer.java
字号:
* <p> * * If you need the OMGraphicList cleared out with a new * projection, you can substitute a ListRestPCPolicy for the * StandardPCPolicy. You would want to do this if your * OMGraphicList changes for different projections - The 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 { if (layerWorker != null) { 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() { 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() { boolean ret = false; synchronized (LAYERWORKER_LOCK) { ret = (layerWorker != null); } return ret; } /** * 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 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) { if (set) { interrupt();// if the layerWorker is busy, stop it. } synchronized (CANCELLED_LOCK) { cancelled = set; } } /** Check to see if the cancelled flag has been set. */ public boolean isCancelled() { 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) { 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; Debug.error(msg); e.printStackTrace(); } catch (Exception e) { msg = getName() + "|LayerWorker.construct(): " + e; Debug.error(msg); e.printStackTrace(); } // This is only called if there is an error. if (Debug.debugging("displayLayerErrors")) { fireRequestMessage(new InfoDisplayEvent(this, msg));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -