package prolog.ui;

import java.awt.*;
import javax.swing.*;
import java.util.*;

/**
 * Title: GuiLocker
 * Description: This class locks a complete gui to perform background work,
 * components that should not be locked must implement the IUnlockable
 * interface. This is a class is an alternative for the glasspane hacks.
 */

public class UiLocker
{
	protected static Map preventClassMap = new HashMap();
	static
	{
		preventClassMap.put( JScrollBar.class, null );
		preventClassMap.put( JSplitPane.class, null );
	}


	/**
	 * the root pane to lock
	 */
	protected Component rootPane = null;

	/**
	 * the hashtable to save all components that were disabled
	 */
	protected HashMap map = new HashMap();

	/**
	 * set to prevent double locking
	 */
	protected boolean itWasMeWhoLocked = false;

	public UiLocker( Component component )
	{
		this.rootPane = component;
	}

	/**
	 * constructs the gui locker
	 */
	public UiLocker( RootPaneContainer rp )
	{
		this.rootPane = rp.getRootPane();
	}

	/**
	 * returns the locked state
	 */
	public boolean getIsLocked()
	{
		return this.itWasMeWhoLocked;
	}

	/**
	 * locks the gui
	 */
	public synchronized void lock()
	{
		if( ! itWasMeWhoLocked )
		{
			lock( rootPane );
			itWasMeWhoLocked = true;
		}
	}

	/**
	 * unlocks the gui
	 */
	public synchronized void unlock()
	{
		if( itWasMeWhoLocked )
		{
			SwingUtilities.invokeLater( new Runnable()
			{
				public void run()
				{
					unlock( rootPane );
					map.clear();
					itWasMeWhoLocked = false;
				}
			});
		}
	}

	/**
	 * the recursive lock method
	 */
	private void lock( Component component )
	{
		if( component instanceof Container )
		{
			Container container = (Container) component;
			int count = container.getComponentCount();
			for( int i=0;i<count;i++ )
				lock( container.getComponent( i ) );
		}
		if( component instanceof Component &&
			preventClassMap.get( component.getClass() ) == null )
		{
			if( component instanceof JComponent )
			{
				JComponent jComponent = (JComponent) component;
				if( jComponent.isEnabled() )
				{
					jComponent.setEnabled( false );
				}
				else
				{
					map.put( jComponent, jComponent );
				}
			}
		}
	}

	/**
	 * the recursive unlock method
	 */
	private void unlock( Component component )
	{
		if( component instanceof Container )
		{
			Container container = (Container) component;
			int count = container.getComponentCount();
			for( int i=0;i<count;i++ )
				unlock( container.getComponent( i ) );
		}
		if( component instanceof Component &&
			preventClassMap.get( component.getClass() ) == null )
		{
			if( component instanceof JComponent )
			{
				JComponent jComponent = (JComponent) component;
				if( ! map.containsKey( jComponent ) )
					jComponent.setEnabled( true );
			}
		}
	}
}
