/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.das2.graph; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; /** * DasCanvasStateSupport is a registery where objects can tell the canvas they * intend to mutate the canvas, so canvas clients should know that its result * may be incomplete. This is first introduced to support server-side * processing, where in Autoplot the Autolayout feature knows then layout is * going to be adjusted, but doesn't have enough information to perform the * function. * * Also, this may be used to address bugs like * https://bugs-pw.physics.uiowa.edu/mantis/view.php?id=303, * "strange intermediate states in transitions," since canvas painting can * be halted while the change is being performed. * * @author jbf */ public class DasCanvasStateSupport { DasCanvas canvas; Map changesPending; private static final Logger logger= Logger.getLogger( "das2.graphics" ); DasCanvasStateSupport( DasCanvas canvas ) { this.canvas= canvas; this.changesPending= new HashMap(); // client->lock } /** * the client knows a change will be coming, and the canvas' clients should * know that its current state will change soon. Example pending changes * would be: * layout because tick labels are changing * data is loading * * @param client the object that will perform the change. This allows the * canvas (and developers) identify who has registered the change. * @param lockObject object identifying the change. */ synchronized void registerPendingChange( Object client, Object lockObject ) { logger.fine( "registerPendingChange "+lockObject+" by "+client); Object existingClient= changesPending.get(lockObject); if ( existingClient!=null ) { if ( existingClient!=client ) { throw new IllegalStateException( "lock object in use: "+lockObject + ", by "+changesPending.get(lockObject) ); } else { return; } } boolean oldVal= this.isPendingChanges(); changesPending.put( lockObject, client ); canvas.firePropertyChange( PROP_PENDINGCHANGES, oldVal, true ); } /** * performingChange tells that the change is about to be performed. This * is a place holder in case we use a mutator lock, but currently does * nothing. * @param lockObject */ synchronized void performingChange( Object client, Object lockObject ) { } /** * the change is complete, and as far as the client is concerned, the canvas * is valid. * @param lockObject */ synchronized void changePerformed( Object client, Object lockObject ) { logger.fine( "clearPendingChange "+lockObject+" by "+client); if ( changesPending.get(lockObject)==null ) { // throw new IllegalStateException( "no such lock object: "+lockObject ); //TODO: handle multiple registrations by the same client } boolean oldVal= this.isPendingChanges(); changesPending.remove(lockObject); canvas.firePropertyChange( PROP_PENDINGCHANGES, oldVal, true ); } // --- properties /** * someone has registered a pending change. */ public static final String PROP_PENDINGCHANGES = "pendingChanges"; public boolean isPendingChanges() { return changesPending.size() > 0; } }