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

bibliothek.gui.dock.control.focus.DefaultMouseFocusObserver Maven / Gradle / Ivy

The newest version!
/*
 * 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) 2010 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.control.focus;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElementRepresentative;
import bibliothek.gui.dock.control.ControllerSetupCollection;
import bibliothek.gui.dock.control.DockRelocator;
import bibliothek.gui.dock.control.GlobalMouseDispatcher;
import bibliothek.gui.dock.control.relocator.DockRelocatorEvent;
import bibliothek.gui.dock.control.relocator.VetoableDockRelocatorAdapter;
import bibliothek.gui.dock.control.relocator.VetoableDockRelocatorListener;
import bibliothek.gui.dock.event.ControllerSetupListener;
import bibliothek.gui.dock.event.FocusVetoListener;
import bibliothek.gui.dock.event.FocusVetoListener.FocusVeto;
import bibliothek.gui.dock.util.DockUtilities;

/**
 * This implementation of a {@link MouseFocusObserver} offers methods to handle
 * {@link FocusVetoListener}s and registers a {@link VetoableDockRelocatorListener}. On a
 * {@link VetoableDockRelocatorListener#dropped(DockRelocatorEvent) drop event} this observer
 * will automatically transfer the focus to the dropped {@link Dockable}.
 * @author Benjamin Sigg
 */
public class DefaultMouseFocusObserver implements MouseFocusObserver{
    
    /** The controller to be informed about changes */
    private DockController controller;
    
    /** 
     * Listener added to the {@link DockRelocator}, updates the focused {@link Dockable} after a 
     * drag and drop operation completed. 
     */
    private VetoableDockRelocatorListener relocatorListener = new VetoableDockRelocatorAdapter(){
    	public void dropped( final DockRelocatorEvent event ){
    		EventQueue.invokeLater( new Runnable(){
                public void run(){
                	FocusController focus = controller.getFocusController();
                	FocusStrategy strategy = focus.getStrategy();
                	if( strategy == null || strategy.shouldFocusAfterDrop( event.getDockable() )){
                		controller.setFocusedDockable( new DefaultFocusRequest( event.getDockable(), null, true ));
                	}
                }
            });
    	};
	};
	
	/** Listener added to the {@link GlobalMouseDispatcher} for registering any {@link MouseEvent} */
	private GlobalMouseListener listener = new GlobalMouseListener();

    /**
     * Creates a new FocusController.
     * @param controller the controller which will be informed about
     * focus-changes
     * @param setup an observable informing this object when controller
     * is set up.
     */
    public DefaultMouseFocusObserver( DockController controller, ControllerSetupCollection setup ){
        this.controller = controller;
        setup.add( new ControllerSetupListener(){
            public void done( DockController controller ) {
                controller.getRelocator().addVetoableDockRelocatorListener( relocatorListener );
                GlobalMouseDispatcher dispatcher = controller.getGlobalMouseDispatcher();
                dispatcher.addMouseListener( listener );
                dispatcher.addMouseMotionListener( listener );
                dispatcher.addMouseWheelListener( listener );
            }
        });
    }
    
    /**
     * Stops this FocusController. This controller will remove all
     * its listeners and become ready for the garbage collector. 
     */
    public void kill(){
        getController().getRelocator().removeVetoableDockRelocatorListener( relocatorListener );
        GlobalMouseDispatcher dispatcher = controller.getGlobalMouseDispatcher();
        dispatcher.removeMouseListener( listener );
        dispatcher.removeMouseMotionListener( listener );
        dispatcher.removeMouseWheelListener( listener );
    }
    
    /**
     * Gets the affected controller.
     * @return the controller
     */
    public DockController getController() {
        return controller;
    }
    
    /**
     * This method may be called at any time by any component that received 
     * the {@link MouseEvent} event.  This observer may transfer the
     * focus because of this call.
* If this application runs in a {@link DockController#isRestrictedEnvironment() restricted environment} * than any {@link DockStation} of this framework will call this method. * @param event the event to check */ public void check( MouseEvent event ){ if( interact( event )){ check( (AWTEvent)event ); } } /** * This method may be called at any time by any component that received * the {@link MouseWheelEvent} event. This observer may transfer the * focus because of this call.
* If this application runs in a {@link DockController#isRestrictedEnvironment() restricted environment} * than any {@link DockStation} of this framework will call this method. * @param event the event to check */ public void check( MouseWheelEvent event ){ if( interact( event )){ check( (AWTEvent)event ); } } /** * Lets check this controller whether the focus should change, or not. Clients * invoking this method should first check whether event is * allowed to change the focus or not. This check can be done through the * method {@link #interact(AWTEvent)}. * @param event The event to react on. * @see #interact(AWTEvent) */ protected void check( AWTEvent event ){ if( controller.getRelocator().isOnPut() || controller.isOnFocusing() ) return; Object source = event.getSource(); if( source instanceof Component ){ Component component = (Component)source; if( event.getID() == MouseEvent.MOUSE_PRESSED ){ if( component.isFocusable() && component.isEnabled()){ check( component, false, true, event ); } else{ check( component, true, false, event ); } } else{ check( component, event ); } } } /** * Tells whether this event should change the focus. * @param event the event * @return true if the focus could be changed */ protected boolean interact( AWTEvent event ){ int id = event.getID(); return id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_WHEEL; } /** * Handles the veto that was given when trying to forward * event. The default implementation calls * {@link InputEvent#consume()} to get rid of the event. * @param event the event to handle * @param veto which veto was called by a {@link FocusVetoListener} */ protected void handleVeto( AWTEvent event, FocusVeto veto ){ if( veto == FocusVeto.VETO ){ if( event instanceof InputEvent ){ ((InputEvent)event).consume(); } } } /** * Tries to find the Dockable which owns component * and sets this Dockable to the focusedDockable. The method * only succeeds if no veto-listener reacts. * @param component the component whose dockable parent is to set * focused * @param event the event that causes this check */ protected void check( Component component, AWTEvent event ){ check( component, true, false, event ); } /** * Tries to find the Dockable which owns component * and sets this Dockable to the focusedDockable. The method * only succeeds if no veto-listener reacts. * @param component the component whose dockable parent is to set * focused * @param ensureFocus whether the DockController should ensure * that the focus is set correctly or not. * @param requestFocusInWindow whether {@link Component#requestFocusInWindow()} should be * called or not * @param event the event that causes this check */ protected void check( final Component component, final boolean ensureFocus, boolean requestFocusInWindow, final AWTEvent event ){ DockElementRepresentative element = getDockable( component, event ); if( element == null ){ return; } Dockable dock = element.getElement().asDockable(); if( dock == null ){ return; } Dockable focused = controller.getFocusedDockable(); boolean change = true; if( focused != null ) change = !DockUtilities.isAncestor( dock, focused ); if( change ){ if( component instanceof FocusAwareComponent ){ FocusAwareComponent aware = (FocusAwareComponent)component; if( requestFocusInWindow ){ aware.maybeRequestFocus(); } aware.invokeOnFocusRequest(new Runnable(){ public void run(){ DockElementRepresentative element = getDockable( component, event ); if( element != null ){ Dockable dock = element.getElement().asDockable(); if( dock != null ){ controller.setFocusedDockable( new DefaultFocusRequest( dock, component, false, ensureFocus, element.shouldTransfersFocus() )); } } } }); } else{ if( requestFocusInWindow ){ component.requestFocusInWindow(); } controller.setFocusedDockable( new DefaultFocusRequest( dock, component, false, ensureFocus, element.shouldTransfersFocus() )); } } } /** * Gets the top-dockable which has component or * parent of component as base Component. * @param component a Component * @param event the event that causes this check * @return a Dockable or null if nothing was found */ protected DockElementRepresentative getDockable( Component component, AWTEvent event ){ DockElementRepresentative element = controller.searchElement( component ); if( element == null ) return null; if( event instanceof MouseEvent || event instanceof MouseWheelEvent ){ if( !element.shouldFocus() ){ return null; } } Dockable dockable = element.getElement().asDockable(); if( dockable == null ) return null; FocusVeto veto = controller.getFocusController().checkFocusedDockable( element ); if( veto != null && veto != FocusVeto.NONE ){ handleVeto( event, veto ); return null; } return element; } /** * This listener forwards all {@link MouseEvent}s to the {@link DefaultMouseFocusObserver#check(MouseEvent)} * and {@link DefaultMouseFocusObserver#check(MouseWheelEvent)}. * @author Benjamin Sigg */ private class GlobalMouseListener implements MouseListener, MouseMotionListener, MouseWheelListener{ public void mouseWheelMoved( MouseWheelEvent e ){ check( e ); } public void mouseDragged( MouseEvent e ){ check( e ); } public void mouseMoved( MouseEvent e ){ check( e ); } public void mouseClicked( MouseEvent e ){ check( e ); } public void mousePressed( MouseEvent e ){ check( e ); } public void mouseReleased( MouseEvent e ){ check( e ); } public void mouseEntered( MouseEvent e ){ check( e ); } public void mouseExited( MouseEvent e ){ check( e ); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy