All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.gui.dock.action.actions.SimpleDockAction Maven / Gradle / Ivy

/*
 * Bibliothek - DockingFrames
 * Library built on Java/Swing, allows the user to "drag and drop"
 * panels containing any Swing-Component the developer likes to add.
 * 
 * Copyright (C) 2007 Benjamin Sigg
 * 
 * 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; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Benjamin Sigg
 * [email protected]
 * CH - Switzerland
 */

package bibliothek.gui.dock.action.actions;

import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;

import javax.swing.Icon;
import javax.swing.KeyStroke;

import bibliothek.extension.gui.dock.preference.editor.KeyStrokeEditor;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.action.ActionContentModifier;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.disable.DisablingStrategy;
import bibliothek.gui.dock.event.DockHierarchyEvent;
import bibliothek.gui.dock.event.DockHierarchyListener;
import bibliothek.gui.dock.event.KeyboardListener;
import bibliothek.gui.dock.station.LayoutLocked;

/**
 * A simple implementation of {@link DockAction}. This action uses for
 * all associated {@link Dockable Dockables} the same settings.
 * @author Benjamin Sigg
 */
public abstract class SimpleDockAction extends AbstractStandardDockAction implements SharingStandardDockAction {
	/** the icons that are used by this action */
	private Map icons = new HashMap();
    
	/** Text of the action */
    private String text;
    
    /** Tooltip for buttons showing this action */
    private String tooltip;
    
    /** Whether this action can be triggered or not */
    private boolean enabled = true;
    
    /** allows to invoke this event by the keyboard, might be null */
    private KeyStroke accelerator;
    
    /** whether to globally listen for all key events */
    private boolean globalAccelerator = false;
    
    /** the {@link Dockable} which is represented by this action and for which drag and drop support may be enabled */
    private Dockable representative;
    
    private Map forwarders = new HashMap();
    
    /**
     * Creates a new action
     * @param monitorDisabling whether the current {@link DisablingStrategy} should be monitored
     */
    public SimpleDockAction( boolean monitorDisabling ){
    	super( monitorDisabling );
    }
    
    @Override
    protected void bound( Dockable dockable ){
    	super.bound( dockable );
    	DockableKeyForwarder forwarder = new DockableKeyForwarder( dockable );
    	forwarders.put( dockable, forwarder );
    }
    
    @Override
    protected void unbound( Dockable dockable ){
    	super.unbound( dockable );
    	DockableKeyForwarder forwarder = forwarders.remove( dockable );
    	forwarder.destroy();
    }
    
    public Icon getIcon( Dockable dockable, ActionContentModifier modifier ){
        return icons.get( modifier );
    }

    public String getText( Dockable dockable ) {
        return text;
    }
    
    public String getText() {
        return text;
    }
    
    public void setText( String text ) {
        this.text = text;
        fireActionTextChanged( getBoundDockables() );
    }

    public String getTooltipText( Dockable dockable ) {
    	return getTooltipText();
    }
    
    public String getTooltipText(){
    	if( accelerator == null )
    		return tooltip;

    	String acceleratorText = KeyStrokeEditor.toString( accelerator, true );

    	if( tooltip == null )
    		return acceleratorText;
    	else
    		return tooltip + " (" + acceleratorText + ")";
    }
    
    public String getTooltip() {
        return tooltip;
    }
    
    public void setTooltip( String tooltip ) {
        this.tooltip = tooltip;
        fireActionTooltipTextChanged( getBoundDockables() );
    }
    
    @Override
    public boolean isEnabled( Dockable dockable ) {
        return enabled && super.isEnabled( dockable );
    }
    
    public boolean isEnabled() {
        return enabled;
    }
    
    public void setEnabled( boolean enabled ) {
        if( this.enabled != enabled ){
            this.enabled = enabled;
            fireActionEnabledChanged( getBoundDockables() );
        }
    }
    
    public Icon getIcon(){
        return icons.get( ActionContentModifier.NONE );
    }
    
    public void setIcon( Icon icon ) {
    	setIcon( ActionContentModifier.NONE, icon );
    }
    
    public ActionContentModifier[] getIconContexts( Dockable dockable ){
    	return icons.keySet().toArray( new ActionContentModifier[ icons.size() ] );
    }
    
    public Icon getDisabledIcon() {
    	return icons.get( ActionContentModifier.DISABLED );
    }
    
    public void setDisabledIcon( Icon icon ) {
		setIcon( ActionContentModifier.DISABLED, icon );	
    }
    
    /**
     * Gets the icon which is shown if the conditions of modifier are met.
     * @param modifier the conditions to met
     * @return the icon to show or null if not set
     */
    public Icon getIcon( ActionContentModifier modifier ){
    	return icons.get( modifier );
    }
    
    /**
     * Sets the icon that is to be used when the conditions of modifier are met.
     * @param modifier the conditions to met
     * @param icon the icon to use or null
     */
    public void setIcon( ActionContentModifier modifier, Icon icon ){
    	if( icon == null ){
    		icons.remove( modifier );
    	}
    	else{
    		icons.put( modifier, icon );
    	}
    	fireActionIconChanged( modifier, getBoundDockables() );
    }
    
    public void setDockableRepresentation( Dockable dockable ){
    	if( this.representative != dockable ){
    		this.representative = dockable;
    		fireActionRepresentativeChanged( getBoundDockables() );
    	}
    }
    
    public Dockable getDockableRepresentation( Dockable dockable ){
    	return representative;
    }
    
    public Dockable getDockableRepresentation(){
    	return representative;
    }
    
    public KeyStroke getAccelerator(){
		return accelerator;
	}
    
    public void setAccelerator( KeyStroke accelerator ){
		this.accelerator = accelerator;
		fireActionTooltipTextChanged( getBoundDockables() );
	}
    
    public void setAcceleratorIsGlobal( boolean global ) {
    	this.globalAccelerator = global;
    }
    
    public boolean isAcceleratorGlobal() {
    	return globalAccelerator;
    }
    
    /**
     * Called when the user hit the {@link #setAccelerator(KeyStroke) accelerator}.
     * This method directly calls trigger( dockable ), subclasses
     * might override this method to further analyze event.
     * @param event the triggering event
     * @param dockable the source of the event
     * @return true if this action could do anything, false
     * if this action was not able to react in any way to the event.
     */
    protected boolean trigger( KeyEvent event, Dockable dockable ){
        return trigger( dockable );
    }
    
    /**
     * Listens to all {@link KeyEvent}s concerning one {@link Dockable}.
     * @author Benjamin Sigg
     */
    @LayoutLocked( locked=false )
    private class DockableKeyForwarder implements KeyboardListener, DockHierarchyListener{
    	/** the element which is observed by this listener */
    	private Dockable dockable;

    	/** the controller which is currently observed by this forwarder, can be null */
    	private DockController controller;
    	
    	/** whether this forwarder has been destroyed */
    	private boolean destroyed = false;
    	
    	/**
    	 * Creates a new forwarder.
    	 * @param dockable the element for which the calls will be forwarded
    	 */
    	public DockableKeyForwarder( Dockable dockable ){
    		this.dockable = dockable;
    		dockable.addDockHierarchyListener( this );
    		setController( dockable.getController() );
    	}
    	
    	public void hierarchyChanged( DockHierarchyEvent event ){
    		// do nothing
    	}
    	
    	public void controllerChanged( DockHierarchyEvent event ){
    		setController( dockable.getController() );
    	}
    	
    	private void setController( DockController controller ){
    		if( this.controller != null )
    			this.controller.getKeyboardController().removeListener( this );
    		
    		if( destroyed ){
    			this.controller = null;
    		}
    		else{
    			this.controller = controller;
    		}
    		
    		if( this.controller != null ){
    			this.controller.getKeyboardController().addListener( this );
    		}
    	}
    	
    	/**
    	 * Removes all listeners added by this forwarder.
    	 */
    	public void destroy(){
    		destroyed = true;
    		setController( null );
    		dockable.removeDockHierarchyListener( this );
    	}
    	
    	/**
    	 * Calls {@link DockAction#trigger(Dockable)}
    	 * if the event matches the accelerator-{@link KeyStroke}.
    	 * @param element the element on which the event occurred
    	 * @param event the event
    	 * @return true if the event has been consumed
    	 */
    	private boolean forward( DockElement element, KeyEvent event ){
    		if( accelerator != null ){
				if( accelerator.equals( KeyStroke.getKeyStrokeForEvent( event ) )){
					return trigger( event, dockable );
				}
			}
			
			return false;
    	}
    	
		public boolean keyPressed( DockElement element, KeyEvent event ){
			return forward( element, event );
		}

		public boolean keyReleased( DockElement element, KeyEvent event ){
			return forward( element, event );
		}

		public boolean keyTyped( DockElement element, KeyEvent event ){
			return forward( element, event );
		}

		public DockElement getTreeLocation(){
			if( isAcceleratorGlobal() ){
				return null;
			}
			else{
				return dockable;
			}
		}
		
		@Override
		public String toString(){
			return getClass().getSimpleName() + " -> " + dockable.getTitleText() + " -> " + getText();
		}
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy