/* * 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 * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.control; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.event.MouseInputAdapter; import bibliothek.gui.DockController; import bibliothek.gui.Dockable; import bibliothek.gui.dock.DockElementRepresentative; import bibliothek.gui.dock.event.ControllerSetupListener; import bibliothek.gui.dock.event.DockControllerRepresentativeListener; import bibliothek.gui.dock.event.DoubleClickListener; import bibliothek.gui.dock.event.LocatedListenerList; import bibliothek.gui.dock.title.DockTitle; /** * Adds a {@link MouseListener} to all {@link Dockable}s, {@link DockTitle}s * and other {@link DockElementRepresentative}s, informs the registered {@link DoubleClickListener}s * whenever the user clicks twice on such an element. * @author Benjamin Sigg */ public class DoubleClickController { /** the list of all observers */ private LocatedListenerList<DoubleClickListener> observers = new LocatedListenerList<DoubleClickListener>(); /** A map that tells which listener was added to which {@link Dockable} */ private Map<DockElementRepresentative, GlobalDoubleClickListener> listeners = new HashMap<DockElementRepresentative, GlobalDoubleClickListener>(); /** * Creates a new <code>DoubleClickController</code>. * @param setup an observable that informs this object when <code>controller</code> * is set up. */ public DoubleClickController( ControllerSetupCollection setup ){ setup.add( new ControllerSetupListener(){ public void done( DockController controller ) { controller.addRepresentativeListener( new DockControllerRepresentativeListener(){ public void representativeAdded( DockController controller, DockElementRepresentative representative ) { Dockable dockable = representative.getElement().asDockable(); if( dockable != null ){ GlobalDoubleClickListener listener = new GlobalDoubleClickListener( dockable ); representative.addMouseInputListener( listener ); listeners.put( representative, listener ); } } public void representativeRemoved( DockController controller, DockElementRepresentative representative ) { Dockable dockable = representative.getElement().asDockable(); if( dockable != null ){ GlobalDoubleClickListener listener = listeners.remove( representative ); if( listener != null ){ representative.removeMouseInputListener( listener ); } } } }); } }); } /** * Adds a listener to this controller. * @param listener the new observer */ public void addListener( DoubleClickListener listener ){ observers.addListener( listener ); } /** * Removes a listener from this controller. * @param listener the observer to remove */ public void removeListener( DoubleClickListener listener ){ observers.removeListener( listener ); } /** * Fires an event to the {@link DoubleClickListener}s whose location in the * tree is equal or below <code>dockable</code>. The order in which the * observers receive the event depends on their distance to the <code>dockable</code>. * @param dockable the dockable which was selected by the user * @param event the cause of the invocation, its click count must be 2. */ public void send( Dockable dockable, MouseEvent event ){ if( dockable == null ) throw new NullPointerException( "dockable must not be null" ); if( event == null ) throw new NullPointerException( "event must not be null" ); if( event.getClickCount() != 2 ) throw new IllegalArgumentException( "click count must be equal to 2" ); List<DoubleClickListener> list = observers.affected( dockable ); for( DoubleClickListener observer : list ){ if( observer.process( dockable, event )){ event.consume(); break; } } } /** * A listener which waits for a double-click-event. * @author Benjamin Sigg */ protected class GlobalDoubleClickListener extends MouseInputAdapter{ /** The Dockable for which this listener is waiting */ private Dockable dockable; /** * Constructs a new listener. * @param dockable the element that will become the source * of the forwarded event */ public GlobalDoubleClickListener( Dockable dockable ){ this.dockable = dockable; } @Override public void mousePressed( MouseEvent event ) { if( !event.isConsumed() && event.getClickCount() == 2 ){ send( dockable, event ); } } } }