// // @(#)MapRenderer2.java 5/2003 // // Copyright 2003 Zachary DelProposto. All rights reserved. // Use is subject to license terms. // // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Or from http://www.gnu.org/ // package dip.gui.map; import dip.gui.map.RenderCommandFactory.RenderCommand; //import dip.gui.ClientFrame; //import dip.gui.AbstractCFPListener; import dip.gui.order.GUIOrder; import dip.order.Orderable; import dip.misc.Log; import dip.world.Province; import dip.world.TurnState; import dip.world.Location; import dip.world.Power; import dip.world.Unit; import java.util.LinkedList; import java.util.Iterator; import org.w3c.dom.svg.SVGDocument; //import org.apache.batik.swing.JSVGCanvas; import org.apache.batik.util.RunnableQueue; import org.apache.batik.util.RunnableQueue.RunnableQueueState; //import org.apache.batik.bridge.UpdateManagerListener; //import org.apache.batik.bridge.UpdateManagerEvent; /** * Base class for the new MapRenderer. * <p> * Implementation notes: remember to <b>always</b> synchronize around the * <code>renderQueue</code> object. * */ public abstract class MapRenderer2 { // constant key values for getRenderSetting() // /** Key for getSettings(): */ public static final String KEY_LABELS = "KEY_LABELS"; /** Key for getSettings(): */ public static final String KEY_SHOW_SUPPLY_CENTERS = "KEY_SHOW_SUPPLY_CENTERS"; /** Key for getSettings(): */ public static final String KEY_SHOW_UNITS = "KEY_SHOW_UNITS"; /** Key for getSettings(): */ public static final String KEY_SHOW_DISLODGED_UNITS = "KEY_SHOW_DISLODGED_UNITS"; /** Key for getSettings(): */ public static final String KEY_SHOW_UNORDERED = "KEY_SHOW_UNORDERED"; /** Key for getSettings(): */ public static final String KEY_SHOW_ORDERS_FOR_POWERS = "KEY_SHOW_ORDERS_FOR_POWERS"; /** Key for getSettings(): */ public static final String KEY_INFLUENCE_MODE = "KEY_INFLUENCE_MODE"; /** Key for getSettings(): */ public static final String KEY_SHOW_MAP = "KEY_SHOW_MAP"; // constant return values for getRenderSetting() // /** Value returned from getSettings(): */ public static final String VALUE_LABELS_NONE = "VALUE_LABELS_NONE"; /** Value returned from getSettings(): */ public static final String VALUE_LABELS_FULL = "VALUE_LABELS_FULL"; /** Value returned from getSettings(): */ public static final String VALUE_LABELS_BRIEF = "VALUE_LABELS_BRIEF"; // instance variables // private boolean isReady = false; // internal flag indicating if turnstate has been set private LinkedList tempQueue = null; //private RunnableQueue runqueue; //protected final MapPanel mapPanel; //protected CFPropertyListener propListener = null; //protected final JSVGCanvas svgCanvas; protected SVGDocument doc; public MapRenderer2(){} /** * Default Constructor * JSVGCanvas and SVGDocument of MapPanel <b>must not be null</b> */ public MapRenderer2(SVGDocument svg) { //Log.printTimed(mp.startTime, "MR2 constructor start"); //mapPanel = mp; //svgCanvas = mapPanel.getJSVGCanvas(); doc = svg; //runqueue = null //propListener = new CFPropertyListener(); //mapPanel.getClientFrame().addPropertyChangeListener(propListener); tempQueue = new LinkedList(); //Log.printTimed(mp.startTime, "MR2 constructor end"); }// MapRenderer() /** Convenience method */ //public final ClientFrame getClientFrame() //{ // return mapPanel.getClientFrame(); //}// getClientFrame() /** * Gets the Runnable Queue for the canvas. * Return null if this cannot be done (e.g., we are exiting). */ // public final RunnableQueue getRunnableQueue() // { // return runqueue; // }// getRunnableQueue() /** * Get a setting (as defined by the KEY_ constants) */ public abstract Object getRenderSetting(final Object key); /** * Execute a RenderCommand. No commands are executed until the TurnState * has been set. * @throws InterruptedException */ public synchronized void execRenderCommand(RenderCommand rc) { if(rc instanceof RenderCommandFactory.RCSetTurnstate) { // focus //mapPanel.requestFocusInWindow(); // dequeue pending events isReady = true; Log.println("MR2:execRenderCommand(): first RCSetTurnstate: ", rc); clearAndExecute(rc, null); // dequeue pending events, if any if(!tempQueue.isEmpty()) { Log.println("MR2::execRenderCommand(): removing pending events from queue. size: ", String.valueOf(tempQueue.size())); //RunnableQueue rq = getRunnableQueue(); // if(rq != null) // { Iterator iter = tempQueue.iterator(); while(iter.hasNext()) { ((RenderCommand) iter.next()).execute(); } tempQueue.clear(); // } } } else if(true) { // a RCSetTurnstate() has been issued. We can accept render events. // if we have queued events, add them. Log.println("MR2::execRenderCommand(): adding to RunnableQueue: ", rc); //RunnableQueue rq = getRunnableQueue(); // if(rq != null) // { rc.execute(); // } } else { // we are not yet ready -- add the rendering events to a temporary queue. Log.println("MR2::execRenderCommand(): adding to tempQueue: ", rc); tempQueue.add(rc); } }// execRenderCommand() /** Clean up any resources used by the MapRenderer. */ public void close() { isReady = false; //mapPanel.getClientFrame().removePropertyChangeListener(propListener); }// close() /** Get the RenderCommandFactory */ public abstract RenderCommandFactory getRenderCommandFactory(); /** Get the MapMetadata object */ //public abstract MapMetadata getMapMetadata(); /** Get the Symbol Name for the given unit type */ public abstract String getSymbolName(Unit.Type unitType); /** Get a location that corresponds to an ID */ public abstract Location getLocation(String id); /** Called when an order has been deleted from the order list */ protected abstract void orderDeleted(GUIOrder order); /** Called when an order has been added to the order list */ protected abstract void orderCreated(GUIOrder order); /** Called when multiple orders have been deleted from the order list */ protected abstract void multipleOrdersDeleted(GUIOrder[] orders); /** Called when multiple orders have been added from the order list */ protected abstract void multipleOrdersCreated(GUIOrder[] orders); /** Called when the displayable powers have changed * @throws InterruptedException */ protected abstract void displayablePowersChanged(Power[] powers) throws InterruptedException; /** * Prevents any enqueued RenderCommands from being executed. * If a command is currently executing, it is not affected. * Adds the given commands (or none, if null) to the queue. * @throws InterruptedException */ protected void clearAndExecute(RenderCommand rc1, RenderCommand rc2) { Log.println("MR2::clearAndExecute()"); //RunnableQueue rq = getRunnableQueue(); // if(rq != null) // { // synchronized(rq.getIteratorLock()) // { // kill our pending render events //Iterator iter = rq.iterator(); // while(iter.hasNext()) // { // Object obj = iter.next(); // if(obj instanceof RenderCommand) // { // Log.println(" killing: ", obj); // ((RenderCommand) obj).die(); // } // } // add our new render commands // NOTE: not sure if this should be in synchronized block. if(rc1 != null) { rc1.execute(); } if(rc2 != null) { rc2.execute(); } // } // } }// clearAndExecute() /** * Listener class for order updates and TurnState changes * */ // private class CFPropertyListener extends AbstractCFPListener // { // public void actionOrderCreated(Orderable order) // { // orderCreated((GUIOrder) order); // } // // public void actionOrderDeleted(Orderable order) // { // orderDeleted((GUIOrder) order); // } // // public void actionOrdersCreated(Orderable[] orders) // { // GUIOrder[] guiOrders = new GUIOrder[orders.length]; // for(int i=0; i<guiOrders.length; i++) // { // guiOrders[i] = (GUIOrder) orders[i]; // } // // multipleOrdersCreated(guiOrders); // } // // public void actionOrdersDeleted(Orderable[] orders) // { // GUIOrder[] guiOrders = new GUIOrder[orders.length]; // for(int i=0; i<guiOrders.length; i++) // { // guiOrders[i] = (GUIOrder) orders[i]; // } // // multipleOrdersDeleted(guiOrders); // } // // public void actionDisplayablePowersChanged(Power[] oldPowers, Power[] newPowers) // { // displayablePowersChanged(newPowers); // } // // public void actionTurnstateChanged(TurnState ts) // { // // OPTIMIZATION: // // any pending queued events may be deleted, because // // we are changing the turnstate and doing a complete re-render. // // // RenderCommand rc1 = // getRenderCommandFactory().createRCSetTurnstate( // MapRenderer2.this, ts); // // RenderCommand rc2 = // getRenderCommandFactory().createRCRenderAll( // MapRenderer2.this); // // clearAndExecute(rc1, rc2); // } // // }// inner class CFPropertyListener /** * Returns a Label-Level constant for the given label level. * Does a case-insensitive compare. Instance equality is preserved. * Returns the given default if parsing fails. */ public static String parseLabelValue(String in, String defaultValue) { if(defaultValue != VALUE_LABELS_NONE && defaultValue != VALUE_LABELS_FULL && defaultValue != VALUE_LABELS_BRIEF && defaultValue != null) { throw new IllegalArgumentException(); } if(VALUE_LABELS_NONE.equalsIgnoreCase(in)) { return VALUE_LABELS_NONE; } else if(VALUE_LABELS_BRIEF.equalsIgnoreCase(in)) { return VALUE_LABELS_BRIEF; } else if(VALUE_LABELS_FULL.equalsIgnoreCase(in)) { return VALUE_LABELS_FULL; } return defaultValue; }// parseLabelValue() }// abstract class MapRenderer2