/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2007-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.renderer3d.utils; import java.awt.Component; import java.awt.Cursor; import java.awt.Point; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.util.Stack; /** * @author Hans H�ggstr�m */ public final class CursorChangerImpl implements CursorChanger { //====================================================================== // Private Fields private Component myComponent = null; private Cursor myOriginalCursor = null; private Stack<CursorEntry> myCursorStack = new Stack<CursorEntry>(); //====================================================================== // Private Constants private static final Cursor EMPTY_CURSOR = createEmptyCursor(); //====================================================================== // Public Methods //---------------------------------------------------------------------- // Constructors /** * Creates a new CursorChangerImpl. You can use setComponent to set the component to manage. */ public CursorChangerImpl() { } /** * @param component some component whose cursor should be managed by this cursor changer. */ public CursorChangerImpl( final Component component ) { setComponent( component ); } //---------------------------------------------------------------------- // CursorChanger Implementation public void setCursor( Object cursorSetter, Cursor cursor ) { ParameterChecker.checkNotNull( cursorSetter, "cursorSetter" ); myCursorStack.push( new CursorEntry( cursorSetter, cursor ) ); setCursor( cursor ); } public void resetCursor( final Object cursorSetter ) { ParameterChecker.checkNotNull( cursorSetter, "cursorSetter" ); // If the setter is topmost, change the cursor to the previous cursor. if ( !myCursorStack.isEmpty() && myCursorStack.peek().cursorSetter.equals( cursorSetter ) ) { myCursorStack.pop(); if ( myCursorStack.isEmpty() ) { setCursor( myOriginalCursor ); } else { setCursor( myCursorStack.peek().cursor ); } } else { // Otherwise just remove the entry from the stack removeEntry( cursorSetter ); } } //---------------------------------------------------------------------- // Other Public Methods /** * @param component some component whose cursor should be managed by this cursor changer. */ public void setComponent( final Component component ) { ParameterChecker.checkNotNull( component, "component" ); // Restore cursor for previous component if ( myComponent != null ) { myComponent.setCursor( myOriginalCursor ); } // Set new component myComponent = component; myOriginalCursor = myComponent.getCursor(); // Set latest cursor if ( !myCursorStack.isEmpty() ) { setCursor( myCursorStack.peek().cursor ); } } //====================================================================== // Private Methods private void setCursor( Cursor cursor ) { if ( cursor == null ) { cursor = EMPTY_CURSOR; } if ( myComponent != null ) { myComponent.setCursor( cursor ); } } private static Cursor createEmptyCursor() { final BufferedImage emptyImage = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_ARGB ); emptyImage.setRGB( 0, 0, 0 ); return Toolkit.getDefaultToolkit().createCustomCursor( emptyImage, new Point( 0, 0 ), "EmptyCursor" ); } private void removeEntry( final Object cursorSetter ) { CursorEntry entryToRemove = null; for ( CursorEntry cursorEntry : myCursorStack ) { if ( cursorEntry.cursorSetter.equals( cursorSetter ) ) { entryToRemove = cursorEntry; break; } } if ( entryToRemove != null ) { myCursorStack.remove( entryToRemove ); } } //====================================================================== // Inner Classes private static final class CursorEntry { //====================================================================== // Non-Private Fields final Object cursorSetter; final Cursor cursor; //====================================================================== // Public Methods //---------------------------------------------------------------------- // Constructors public CursorEntry( final Object cursorSetter, final Cursor cursor ) { this.cursorSetter = cursorSetter; this.cursor = cursor; } //---------------------------------------------------------------------- // Caononical Methods public boolean equals( final Object o ) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } final CursorEntry that = (CursorEntry) o; if ( cursorSetter != null ? !cursorSetter.equals( that.cursorSetter ) : that.cursorSetter != null ) { return false; } return true; } public int hashCode() { return ( cursorSetter != null ? cursorSetter.hashCode() : 0 ); } } }