bibliothek.gui.dock.station.stack.DefaultStackDockComponent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of docking-frames-core Show documentation
Show all versions of docking-frames-core Show documentation
A window docking framework for Swing
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) 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.station.stack; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.Icon; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.MouseInputAdapter; import bibliothek.gui.DockController; import bibliothek.gui.Dockable; import bibliothek.gui.dock.DockElement; import bibliothek.gui.dock.DockElementRepresentative; import bibliothek.gui.dock.action.ActionPopup; import bibliothek.gui.dock.action.DockActionSource; import bibliothek.gui.dock.control.RemoteRelocator; import bibliothek.gui.dock.control.RemoteRelocator.Reaction; import bibliothek.gui.dock.disable.TabDisablingStrategyObserver; import bibliothek.gui.dock.station.stack.tab.layouting.TabPlacement; import bibliothek.gui.dock.util.SimpleDockElementRepresentative; /** * The standard-implementation of {@link StackDockComponent}. This implementation * uses a {@link JTabbedPane} to display its children. * * @author Janni Kovacs * @author Benjamin Sigg * @see StackDockComponent * @see JTabbedPane */ public class DefaultStackDockComponent extends JTabbedPane implements StackDockComponent { /** The Dockables shown on this component and their RemoteRelocators to control drag&drop operations */ private List
* if this tab is no longer used, or when the connection to a * {@link DockController} is lost. * @param controller the new source of information, can bedockables = new ArrayList (); /** The controller for which this component is shown */ private DockController controller; /** the tab to which mouse-events are currently redirected */ private Tab mouseTarget; /** listeners to be informed if the selection changes */ private List listeners = new ArrayList (); /** keeps track of all tabs that need to be disabled */ private TabDisablingStrategyObserver tabDisabling = new TabDisablingStrategyObserver(){ @Override public void setDisabled( Dockable dockable, boolean disabled ){ int index = indexOf( dockable ); if( index >= 0 ){ setEnabledAt( index, !disabled ); } } }; /** * Constructs the component, sets the location of the tabs to bottom. */ public DefaultStackDockComponent(){ super(BOTTOM); Listener listener = new Listener(); addMouseListener( listener ); addMouseMotionListener( listener ); addChangeListener( listener ); setOpaque( false ); } public void addStackDockComponentListener( StackDockComponentListener listener ){ listeners.add( listener ); } public void removeStackDockComponentListener( StackDockComponentListener listener ){ listeners.remove( listener ); } public void setDockTabPlacement( TabPlacement tabSide ){ switch( tabSide ){ case BOTTOM_OF_DOCKABLE: setTabPlacement( BOTTOM ); break; case LEFT_OF_DOCKABLE: setTabPlacement( LEFT ); break; case TOP_OF_DOCKABLE: setTabPlacement( TOP ); break; case RIGHT_OF_DOCKABLE: setTabPlacement( RIGHT ); break; } } public TabPlacement getDockTabPlacement(){ switch( getTabPlacement() ){ case BOTTOM: return TabPlacement.BOTTOM_OF_DOCKABLE; case LEFT: return TabPlacement.LEFT_OF_DOCKABLE; case RIGHT: return TabPlacement.RIGHT_OF_DOCKABLE; case TOP: return TabPlacement.TOP_OF_DOCKABLE; } throw new IllegalStateException( "unknown position: " + getTabPlacement() ); } public void insertTab(String title, Icon icon, Component comp, Dockable dockable, int index) { insertTab(title, icon, comp, (String)null, index); Tab tab = createTab( dockable ); dockables.add( index, tab ); tab.setController( controller ); tabDisabling.add( dockable ); } /** * Creates a new representation of a tab on this component. * @param dockable the element which is represented by the tab * @return the new tab */ protected Tab createTab( Dockable dockable ){ return new Tab( dockable ); } public void addTab( String title, Icon icon, Component comp, Dockable dockable ){ addTab( title, icon, comp ); Tab tab = createTab( dockable ); dockables.add( tab ); tab.setController( controller ); tabDisabling.add( dockable ); } public Dockable getDockableAt( int index ){ return dockables.get( index ).getDockable(); } /** * The structure of the {@link JTabbedPane} does not allow its tabs to recognized as {@link DockElementRepresentative}, * hence this method always returns null
. * @param index ignored * @returnnull
*/ public DockElementRepresentative getTabAt( int index ){ return null; } public void moveTab( int source, int destination ){ if( source == destination ){ return; } if( destination < 0 || destination >= getTabCount() ){ throw new ArrayIndexOutOfBoundsException(); } int selected = getSelectedIndex(); String title = getTitleAt( source ); String tooltip = getToolTipTextAt( source ); Icon icon = getIconAt( source ); Component comp = getComponentAt( source ); Dockable dockable = dockables.get( source ).getDockable(); remove( source ); insertTab( title, icon, comp, dockable, destination ); setTooltipAt( destination, tooltip ); if( selected == source ){ selected = destination; } else if( selected > source && selected <= destination ){ selected++; } setSelectedIndex( selected ); } @Override public void removeAll(){ for( Tab tab : dockables ){ tab.setController( null ); tabDisabling.remove( tab.getDockable() ); } super.removeAll(); dockables.clear(); } @Override public void remove( int index ){ Tab tab = dockables.remove( index ); tab.setController( null ); tabDisabling.remove( tab.getDockable() ); super.remove( index ); } public Component getComponent() { return this; } @Override public void setTitleAt( int index, String title ){ super.setTitleAt( index, title == null ? "" : title ); } public void setTooltipAt( int index, String newTooltip ) { setToolTipTextAt( index, newTooltip ); } public void setController( DockController controller ){ if( this.controller != controller ){ if( mouseTarget != null ){ if( mouseTarget.relocator != null ){ mouseTarget.relocator.cancel(); } mouseTarget = null; } this.controller = controller; tabDisabling.setController( controller ); for( Tab tab : dockables ){ tab.setController( controller ); } } } public boolean hasBorder() { return true; } public boolean isSingleTabComponent(){ return false; } public DockElementRepresentative createDefaultRepresentation( DockElement target ){ return new SimpleDockElementRepresentative( target, this ); } public int getIndexOfTabAt( Point mouseLocation ){ for( int i = 0, n = getTabCount(); inull null
*/ public void setController( DockController controller ){ if( controller == null ) relocator = null; else relocator = controller.getRelocator().createRemote( dockable ); } public void popup( MouseEvent event ){ if( !event.isConsumed() && event.isPopupTrigger() ){ super.popup( event ); } } protected DockActionSource getActions(){ return dockable.getGlobalActionOffers(); } @Override protected Object getSource(){ return this; } protected boolean isEnabled(){ return true; } } /** * A listener to the enclosing component, using some {@link RemoteRelocator} * to do drag & drop operations. * @author Benjamin Sigg */ private class Listener extends MouseInputAdapter implements ChangeListener{ public void stateChanged( ChangeEvent e ){ for( StackDockComponentListener listener : listeners.toArray( new StackDockComponentListener[ listeners.size() ] )){ listener.selectionChanged( DefaultStackDockComponent.this ); } } /** * Updates the value of {@link DefaultStackDockComponent#mouseTarget relocator} * @param x the x-coordinate of the mouse * @param y the y-coordinate of the mouse * @param searchDockable iftrue
, then a new current relocator can be * selected, otherwise the relocator may only be canceled by not exchanged * @param forceSearch iftrue
then a search is always made, even if the user is * not allowed to move a tab anyways */ private void updateRelocator( int x, int y, boolean searchDockable, boolean forceSearch ){ boolean allowed = controller == null || !controller.getRelocator().isDragOnlyTitle(); if( mouseTarget != null ){ if( !allowed ){ mouseTarget.relocator.cancel(); if( !forceSearch ){ mouseTarget = null; } } return; } if( !allowed && !forceSearch ){ return; } if( searchDockable ){ for( int i = 0, n = getTabCount(); i