/* * 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.station.stack.tab; import java.awt.Component; import java.awt.Dimension; import bibliothek.gui.DockController; import bibliothek.gui.Dockable; import bibliothek.gui.dock.event.DockableFocusEvent; import bibliothek.gui.dock.event.DockableFocusListener; /** * Abstract implementation of {@link Tab} based on a real {@link Component}. Clients * should call {@link #bind()}, {@link #unbind()} and {@link #setController(DockController)} to * fully utilize this class. * @author Benjamin Sigg */ public abstract class AbstractTab extends AbstractTabPaneComponent implements Tab{ private Dockable dockable; /** whether {@link #bind()} was called and {@link #unbind()} was not yet called */ private boolean bound = false; /** the controller in whose realm this tab works */ private DockController controller; /** whether this tab is currently selected */ private boolean selected = false; /** whether this tab is currently focused */ private boolean focused = false; /** * Observes the owner of this tab and changes the selection state * of this tab if the owners selection changes. */ private TabPaneListener selectionListener = new TabPaneListener(){ public void added( TabPane pane, Dockable dockable ){ // ignore } public void removed( TabPane pane, Dockable dockable ){ // ignore } public void selectionChanged( TabPane pane ){ boolean newSelected = pane.getSelectedDockable() == getDockable(); if( newSelected != selected ){ selected = newSelected; informSelectionChanged( selected ); } } public void infoComponentChanged( TabPane pane, LonelyTabPaneComponent oldInfo, LonelyTabPaneComponent newInfo ){ // ignore } public void controllerChanged( TabPane pane, DockController controller ){ // ignore } }; /** * Observers the {@link DockController} in order to find out whether this * tab is currently focused or not. */ private DockableFocusListener focusListener = new DockableFocusListener(){ public void dockableFocused( DockableFocusEvent event ){ boolean newFocused = event.getNewFocusOwner() == getDockable(); if( newFocused != focused ){ focused = newFocused; informFocusChanged( focused ); } } }; /** * Creates a new abstract tab. * @param parent the owner of this tab * @param dockable the element to show, not <code>null</code> */ public AbstractTab( TabPane parent, Dockable dockable ){ super( parent ); if( dockable == null ) throw new IllegalArgumentException( "dockable must not be null" ); this.dockable = dockable; } public Dockable getDockable(){ return dockable; } public Dimension getMinimumSize( Tab[] tabs ){ return getMinimumSize(); } public Dimension getPreferredSize( Tab[] tabs ){ return getPreferredSize(); } /** * Connects this tab with its parent and the {@link DockController}. * @throws IllegalStateException if this method has already been invoked */ public void bind(){ if( bound ) throw new IllegalStateException( "this tab is already bound" ); bound = true; if( controller != null ){ controller.addDockableFocusListener( focusListener ); focused = controller.getFocusedDockable() == getDockable(); informFocusChanged( focused ); } TabPane parent = getTabParent(); parent.addTabPaneListener( selectionListener ); selected = parent.getSelectedDockable() == getDockable(); informSelectionChanged( selected ); } /** * Disconnects this tab from its parent and from the {@link DockController}. * @throws IllegalStateException if this method has already been invoked. */ public void unbind(){ if( !bound ) throw new IllegalStateException( "this tab is not bound" ); bound = false; if( controller != null ){ controller.removeDockableFocusListener( focusListener ); } getTabParent().removeTabPaneListener( selectionListener ); } /** * Tells whether this tab is selected. This property is updated a {@link TabPaneListener} * and might not be the correct value while a selection changes. * @return whether this tab is selected */ public boolean isSelected(){ return selected; } /** * Called when the selection state of this tab has been changed. Subclasses * may choose to ignore the event. * @param selected the new selection state */ protected abstract void informSelectionChanged( boolean selected ); /** * Tells whether this tab is focused. A tab is focused if its * {@link Dockable} is {@link DockController#getFocusedDockable() focused}. * This property is updated by a {@link DockableFocusListener}, hence it * might not be accurate while the focus changes. * @return whether this tab is focused */ public boolean isFocused(){ return focused; } /** * Called when the focus state of this tab has been changed. Subclasses * may choose to ignore the event. * @param focused the new focus state */ protected abstract void informFocusChanged( boolean focused ); /** * Sets the controller in whose realm this {@link AbstractTab} works. * @param controller the controller */ public void setController( DockController controller ){ if( bound ){ if( this.controller != null ){ this.controller.removeDockableFocusListener( focusListener ); } this.controller = controller; if( this.controller != null ){ this.controller.addDockableFocusListener( focusListener ); focused = this.controller.getFocusedDockable() == getDockable(); informFocusChanged( focused ); } } else{ this.controller = controller; } } }