/* * 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.common.intern; import java.awt.Component; import java.awt.Dimension; import bibliothek.gui.DockTheme; import bibliothek.gui.Dockable; import bibliothek.gui.dock.FlapDockStation; import bibliothek.gui.dock.common.CControl; import bibliothek.gui.dock.common.CLocation; import bibliothek.gui.dock.common.CStation; import bibliothek.gui.dock.common.ColorMap; import bibliothek.gui.dock.common.DefaultMultipleCDockable; import bibliothek.gui.dock.common.DefaultSingleCDockable; import bibliothek.gui.dock.common.EnableableItem; import bibliothek.gui.dock.common.FontMap; import bibliothek.gui.dock.common.action.CAction; import bibliothek.gui.dock.common.event.CDockableLocationListener; import bibliothek.gui.dock.common.event.CDockablePropertyListener; import bibliothek.gui.dock.common.event.CDockableStateListener; import bibliothek.gui.dock.common.event.CDoubleClickListener; import bibliothek.gui.dock.common.event.CFocusListener; import bibliothek.gui.dock.common.event.CKeyboardListener; import bibliothek.gui.dock.common.event.CVetoClosingEvent; import bibliothek.gui.dock.common.event.CVetoClosingListener; import bibliothek.gui.dock.common.grouping.DockableGrouping; import bibliothek.gui.dock.common.intern.action.CloseActionSource; import bibliothek.gui.dock.common.layout.RequestDimension; import bibliothek.gui.dock.common.mode.CLocationModeManager; import bibliothek.gui.dock.common.mode.ExtendedMode; import bibliothek.gui.dock.layout.DockableProperty; import bibliothek.util.Filter; import bibliothek.util.FrameworkOnly; import bibliothek.util.Todo; import bibliothek.util.Todo.Compatibility; import bibliothek.util.Todo.Priority; import bibliothek.util.Todo.Version; /** * A basic element representing some {@link java.awt.Component} and a wrapper * around a {@link Dockable}.<br> * <b>Note:</b> This interface is not intended to be implemented by clients. * Clients should either extend the class {@link AbstractCDockable} or use * one of {@link DefaultSingleCDockable} or {@link DefaultMultipleCDockable}. * @author Benjamin Sigg */ @FrameworkOnly public interface CDockable { /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} * with an argument of {@link ExtendedMode#MINIMIZED}. */ public static final String ACTION_KEY_MINIMIZE = "cdockable.minimize"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} * with an argument of {@link ExtendedMode#MAXIMIZED}. */ public static final String ACTION_KEY_MAXIMIZE = "cdockable.maximize"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} * with an argument of {@link ExtendedMode#NORMALIZED}. */ public static final String ACTION_KEY_NORMALIZE = "cdockable.normalize"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} * with an argument of {@link ExtendedMode#EXTERNALIZED}. */ public static final String ACTION_KEY_EXTERNALIZE = "cdockable.externalize"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} with * an argument of {@link ExtendedMode#NORMALIZED}. */ public static final String ACTION_KEY_UNEXTERNALIZE = "cdockable.unexternalize"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setExtendedMode(ExtendedMode)} with * an argument of {@link ExtendedMode#EXTERNALIZED}. */ public static final String ACTION_KEY_UNMAXIMIZE_EXTERNALIZED = "cdockable.unmaximize_externalized"; /** * Key for an action of {@link #getAction(String)}. The action behind this * key should call {@link #setVisible(boolean)} with the argument * <code>false</code>. */ public static final String ACTION_KEY_CLOSE = "cdockable.close"; /** * Key for an action of {@link #getAction(String)}. The action behind * this key should toggle {@link CDockable#setMinimizedHold(boolean)}. */ public static final String ACTION_KEY_MINIMIZE_HOLD = "cdockable.hold"; /** * Adds a state listener to this dockable, the listener will be informed of * changes of this dockable. * @param listener the new listener */ public void addCDockableStateListener( CDockableStateListener listener ); /** * Adds a property listener to this dockable, the listener will be informed of * changes of this dockable. * @param listener the new listener */ public void addCDockablePropertyListener( CDockablePropertyListener listener ); /** * Adds a listener to this dockable which gets informed if the location or * the visibility changes. * @param listener the new listener */ public void addCDockableLocationListener( CDockableLocationListener listener ); /** * Removes a state listener from this dockable. * @param listener the listener to remove */ public void removeCDockableStateListener( CDockableStateListener listener ); /** * Removes a property listener from this dockable. * @param listener the listener to remove */ public void removeCDockablePropertyListener( CDockablePropertyListener listener ); /** * Removes <code>listener</code> from this dockable * @param listener the listener to remove */ public void removeCDockableLocationListener( CDockableLocationListener listener ); /** * Adds a focus listener to this dockable. The focus listener gets informed * when this dockable gains or loses the focus. * @param listener the new listener */ public void addFocusListener( CFocusListener listener ); /** * Removes a focus listener from this dockable. * @param listener the listener to remove */ public void removeFocusListener( CFocusListener listener ); /** * Adds a keyboard listener to this dockable. The listener gets informed * when a key is pressed or released on this dockable. * @param listener the new listener */ public void addKeyboardListener( CKeyboardListener listener ); /** * Removes a listener from this dockable. * @param listener the listener to remove */ public void removeKeyboardListener( CKeyboardListener listener ); /** * Adds a new listener to this dockable. The listener gets informed * when the mouse is clicked twice on this dockable. * @param listener the new listener */ public void addDoubleClickListener( CDoubleClickListener listener ); /** * Removes a listener from this dockable. * @param listener the listener to remove */ public void removeDoubleClickListener( CDoubleClickListener listener ); /** * Adds a veto-listener to this dockable, the listener will be informed before this * dockable gets closed and can issue a veto. The listener will receive a * {@link CVetoClosingEvent} which contains only this {@link CDockable} (even if * other dockables are closed at the same time).<br> * {@link CVetoClosingListener}s added to the {@link CControl} are invoked before listeners that * are added to a {@link CDockable}. * @param listener the new listener * @see CControl#addVetoClosingListener(CVetoClosingListener) */ public void addVetoClosingListener( CVetoClosingListener listener ); /** * Removes <code>listener</code> from this <code>CDockable</code>. * @param listener the listener to remove */ public void removeVetoClosingListener( CVetoClosingListener listener ); /** * Tells whether this <code>CDockable</code> can be minimized by the user. * @return <code>true</code> if this element can be minimized */ public boolean isMinimizable(); /** * Tells whether this <code>CDockable</code> can be maximized by the user. * @return <code>true</code> if this element can be maximized */ public boolean isMaximizable(); /** * Tells whether this <code>CDockable</code> can be externalized by the user. * @return <code>true</code> if this element can be externalized */ public boolean isExternalizable(); /** * Tells whether this <code>CDockable</code> can be normalized by the user. Usually this method should * return <code>true</code> for any dockable, as "normalizing" is the default mode.<br> * Clients should not override this method. * @return <code>true</code>, unless a subclass requires very special behavior. */ public boolean isNormalizeable(); /** * Tells whether this <code>CDockable</code> can be combined with another * <code>Dockable</code> to create a stack. * @return <code>true</code> if this element can be combined with * another <code>Dockable</code>, normally <code>true</code> should be the answer. */ public boolean isStackable(); /** * Tells whether this <code>CDockable</code> can be closed by the user. A close-button * has to be provided by the <code>CDockable</code> itself. The best way to do that is * to instantiate a {@link CloseActionSource} and include this source * in the array that is returned by {@link CommonDockable#getSources()}. * @return <code>true</code> if this element can be closed */ public boolean isCloseable(); /** * Tells whether the height of this <code>CDockable</code> should remain the same when * its parent changes the size. This has only effect if the parent can * choose the size of its children. A lock is no guarantee for staying * with the same size, the user still can resize this <code>CDockable</code>. * @return <code>true</code> if the height of this <code>CDockable</code> should remain * the same during resize events of the parent. */ public boolean isResizeLockedVertically(); /** * Tells whether the width of this <code>CDockable</code> should remain the same when * its parent changes the size. This has only effect if the parent can * choose the size of its children. A lock is no guarantee for staying * with the same size, the user still can resize this <code>CDockable</code>. * @return <code>true</code> if the width of this <code>CDockable</code> should remain * the same during resize events of the parent. */ public boolean isResizeLockedHorizontally(); /** * Gets the preferred size of this {@link CDockable}. The preferred size * will be used to resize this <code>CDockable</code> when * {@link CControl#handleResizeRequests()} is called. There are no guarantees * that the request can be granted, or will be handled at all.<br> * Calling this method should delete the request, so calling this method * twice should have the effect, that the second time <code>null</code> is * returned. * @return the next requested size or <code>null</code> */ public RequestDimension getAndClearResizeRequest(); /** * Shows or hides this <code>CDockable</code>. If this <code>CDockable</code> is not visible and * is made visible, then the framework tries to set its location at the last known position.<br> * Subclasses should call {@link CControlAccess#show(CDockable)} or {@link CControlAccess#hide(CDockable)}. * @param visible the new visibility state * @see #isVisible() * @throws IllegalStateException if this dockable can't be made visible */ public void setVisible( boolean visible ); /** * Tells whether this <code>CDockable</code> is currently visible or not. Visibility * means that this <code>CDockable</code> is in the tree structure of DockingFrames and has a parent. Being * in the structure does not imply being visible on the screen: If some * <code>JFrame</code> is not shown, or some <code>DockStation</code> not * properly added to a parent component, then a visible <code>CDockable</code> can * be invisible for the user. For {@link CDockable}s that are also root-{@link CStation} this method will * always return <code>true</code>.<br> * Clients interested in whether the user can actually see this dockable should call {@link #isShowing()}.<br> * Subclasses should return the result of {@link CControlAccess#isVisible(CDockable)}. * @return <code>true</code> if this <code>CDockable</code> can be accessed by the user * through a graphical user interface. * @see #hasParent() * @see #isShowing() */ public boolean isVisible(); /** * Tells whether this {@link CDockable} has a root station as parent. Having a root station as parent * implies {@link #isVisible()}. For root-{@link CStation} this method will return <code>false</code> if they * do not have a parent, they are not considered to be parents of themselves.<br> * Subclasses should return the result of {@link CControlAccess#hasParent(CDockable)}. * @return <code>true</code> if this dockable has a parent and is in the tree */ public boolean hasParent(); /** * Tells whether this <code>CDockable</code> is currently visible to the user. A <code>CDockable</code> * which is not {@link #isVisible() visible}, is not <code>dockable visible</code> either. The method * does not take into account that a frame may be positioned such that it is not entirely visible on the * screen. Neither does the method take into account, that a frame may be minimized. * @return <code>true</code> if the user should be able to see this item * @deprecated this method gets replaced by {@link #isShowing()}, which offers the exact same information. This method * will be removed in a future release */ @Deprecated @Todo( compatibility=Compatibility.BREAK_MAJOR, priority=Priority.ENHANCEMENT, target=Version.VERSION_1_1_3, description="remove this method" ) public boolean isDockableVisible(); /** * Tells whether this <code>CDockable</code> is currently visible to the user. A <code>CDockable</code> * which is not {@link #isVisible() visible}, is not <code>showing</code> either. The method * does not take into account that a frame may be positioned such that it is not entirely visible on the * screen. The method may or may not take into account, that a frame may be minimized.<br> * Clients interested in monitoring this property can add a {@link CDockableLocationListener} to this dockable. * @return <code>true</code> if the user should be able to see this item * @see CDockableLocationListener * @see #addCDockableLocationListener(CDockableLocationListener) */ public boolean isShowing(); /** * Sets the location of this <code>CDockable</code>. If this <code>CDockable</code> is visible, than * this method will take immediately effect. Otherwise the location will be * stored in a cache and read as soon as this <code>CDockable</code> is made visible.<br> * Note that the location can only be seen as a hint, the framework tries * to fit the location as good as possible, but there are no guarantees.<br> * Subclasses should call {@link CControlAccess#getLocationManager()} and * {@link CLocationModeManager#setLocation(bibliothek.gui.Dockable, CLocation)}. * @param location the new location, <code>null</code> is possible, but * will not move the <code>CDockable</code> immediately * @see #getBaseLocation() */ public void setLocation( CLocation location ); /** * Sets the location of this {@link CDockable} aside <code>dockable</code> in all {@link ExtendedMode}s. If this * {@link Dockable} is visible, then it may or may not change its location and {@link ExtendedMode}. Note that <code>dockable</code> and <code>this</code> * must not be the same object, and that both {@link CDockable}s must be {@link CControl#addDockable(bibliothek.gui.dock.common.SingleCDockable) registered} * at a {@link CControl}. * @param dockable the item whose locations should be copied * @throws IllegalArgumentException if <code>dockable</code> is <code>null</code>, not registered, the same * as <code>this</code>, or has a different {@link #getWorkingArea() working area} * @throws IllegalStateException if <code>this</code> is not registered at the same {@link CControl} as <code>dockable</code> */ public void setLocationsAside( CDockable dockable ); /** * Traverses the history of focused {@link CDockable}s, and selects the newest item with focus and matching * <code>filter</code> for calling {@link #setLocationsAside(CDockable)}. * @param filter to select a {@link CDockable} which did have the focus * @return <code>true</code> if an old focused {@link Dockable} was found, <code>false</code> if not */ public boolean setLocationsAside( Filter<CDockable> filter ); /** * Searches for the last focused {@link CDockable} with the same {@link #getWorkingArea() working area} as * <code>this</code>, and calls {@link #setLocationsAside(CDockable)} with it.<br> * Note that if this <code>dockable</code> is visible, then it may or may not change its location. This method * should be called <i>before</i> making the <code>dockable</code> visible. * @return <code>true</code> if the last focused {@link CDockable} was found, <code>false</code> otherwise. If * <code>false</code> then no action was performed */ public boolean setLocationsAsideFocused(); /** * Gets the location of this <code>CDockable</code>. If this <code>CDockable</code> is visible, then * a location will always be returned. Otherwise a location will only * be returned if it just was set using {@link #setLocation(CLocation)}. * @return the location or <code>null</code> */ public CLocation getBaseLocation(); /** * Tries to find out at which location this {@link CDockable} may appear if it would be made visible. The default * implementation of this method has severe limitations: * <ul> * <li>Random placements are not considered and the result will be <code>null</code></li> * <li>Placeholders are not considered, if this {@link CDockable} is associated with a placeholder, then the * placeholder information will be completely lost.</li> * <li>This {@link CDockable} must not be visible and it must be registered at a {@link CControl}.</li> * </ul> * To be more precise: the location returned by this method may not be the actual location where this dockable * appears because this method does not consider all circumstances.<br> * Clients can make use of this method in two ways: * <ul> * <li>They can find out whether the dockable has a location, or will be placed randomly (in which case the result * of this method is <code>null</code>)</li> * <li>They can override this method in which case the {@link CDockable} will appear at the exact location that * is returned by this method ignoring any other settings.</li> * </ul> * * @param noBackwardsTransformation if <code>true</code>, then this method should not convert any {@link DockableProperty} * back to a {@link CLocation}, instead it should return <code>null</code> if such a conversion would be necessary. This * way the method does return <code>null</code> in any case where information (e.g. placeholders) could be lost * due to the limitations of {@link CLocation} * * @return The expected location of this invisible {@link CDockable}, this may either be the location that was set * by calling {@link #setLocation(CLocation)}, the last location of this dockable when it was visible, the * {@link CControl#getDefaultLocation() default location} of the <code>CControl</code> or the default location for the * {@link ExtendedMode#NORMALIZED normalized extended mode}. A value of <code>null</code> is returned if this * {@link CDockable} would appear at a random location, is not registered at a {@link CControl} or is already visible. */ public CLocation getAutoBaseLocation( boolean noBackwardsTransformation ); /** * Sets how and where this <code>CDockable</code> should be shown. Conflicts with * {@link #isExternalizable()}, {@link #isMaximizable()} and {@link #isMinimizable()} * will just be ignored. Implementations should call {@link CLocationModeManager#setMode(Dockable, ExtendedMode)}.<br> * If this dockable is not visible, then it will be made visible in order to apply the <code>extendedMode</code>. * @param extendedMode the size and location */ public void setExtendedMode( ExtendedMode extendedMode ); /** * Gets the size and location of this <code>CDockable</code>. Implementations should * return {@link CLocationModeManager#getMode(Dockable)}. * @return the size and location or <code>null</code> if this <code>CDockable</code> * is not part of an {@link CControl}. May be <code>null</code> if this dockable is not visible. */ public ExtendedMode getExtendedMode(); /** * Gets an algorithm that tells how this {@link CDockable} attempts to group itself automatically with other {@link Dockable}s. * The algorithm is able to rewrite the location of this {@link CDockable} every time when it is moved to a new location, assuming * that no stronger mechanism, or the user, already defined a location. * @return the grouping behavior, or <code>null</code> */ public DockableGrouping getGrouping(); /** * Sets the parent of this <code>CDockable</code>. This method can be called by the client * or indirectly through {@link #setLocation(CLocation)}. * @param area the new parent or <code>null</code> */ public void setWorkingArea( CStation<?> area ); /** * Gets the parent of this <code>CDockable</code>, this should be the same as * set by the last call of {@link #setWorkingArea(CStation)}. * @return the parent or <code>null</code> */ public CStation<?> getWorkingArea(); /** * Sets the size of this <code>CDockable</code> when this <code>CDockable</code> is minimized and * on a popup window. * @param size the size */ public void setMinimizedSize( Dimension size ); /** * Gets the size which is used when this <code>CDockable</code> is minimized and * on a popup window. If a value below 0 is set, then the default size * is used. * @return the size */ public Dimension getMinimizedSize(); /** * Sets whether this <code>CDockable</code> should remain visible when minimized * and without focus. * @param sticky whether to remain visible */ public void setSticky( boolean sticky ); /** * Tells whether this <code>CDockable</code> remains visible when minimized and * without focus. * @return <code>true</code> if this remains visible, <code>false</code> * otherwise */ public boolean isSticky(); /** * Sets whether the user can switch the {@link #isSticky()} property by clicking * on a button that is presented by the {@link FlapDockStation}. * @param switchable whether the user is able to switch the hold property */ public void setStickySwitchable( boolean switchable ); /** * Tells whether the {@link #isSticky()} property can be changed by the user * by clicking a button that is displayed on the {@link FlapDockStation}. * @return <code>true</code> if the user is able to switch the property, <code>false</code> * otherwise */ public boolean isStickySwitchable(); /** * Tells whether this <code>CDockable</code> shows its title or not. Note that some * {@link DockTheme}s might override this setting. * @return <code>true</code> if the title is shown, <code>false</code> * otherwise. */ public boolean isTitleShown(); /** * Tells whether a single tab should be shown for this <code>CDockable</code>. Some * {@link DockTheme}s might ignore this setting. * @return <code>true</code> if a single tab should be shown, * <code>false</code> if not */ public boolean isSingleTabShown(); /** * Tells whether a part of this dockable is enabled. * @param item the part to check * @return whether <code>item</code> is enabled, the default result should be <code>true</code> */ public boolean isEnabled( EnableableItem item ); /** * Gets the {@link Component} which should receive the focus once this <code>CDockable</code> is focused. * @return the element which should receive the focus, can be <code>null</code> */ public Component getFocusComponent(); /** * Gets the intern representation of this <code>CDockable</code>. * @return the intern representation. */ public CommonDockable intern(); /** * Gets <code>this</code> or an object representing <code>this</code> as * {@link CStation}. * @return this as station or <code>null</code> */ public CStation<?> asStation(); /** * Sets the {@link CControl} which is responsible for this <code>CDockable</code>. Subclasses * must call {@link CControlAccess#link(CDockable, CDockableAccess)} to grant * the <code>CControl</code> access to the internal properties of this * {@link CDockable}. <code>link</code> can also be used to revoke access. * @param control the new control or <code>null</code> */ @FrameworkOnly public void setControlAccess( CControlAccess control ); /** * Gets the control which is responsible for this dockable. Clients * should not use this method unless they know exactly what they are doing. * @return the control */ @FrameworkOnly public CControlAccess getControlAccess(); /** * Gets the control which is responsible for this dockable. This property is set as long as this * {@link CDockable} is registered at a {@link CControl}. * @return the control in whose realm this dockable is used, can be <code>null</code> */ public CControl getControl(); /** * Searches the first {@link CStation} that is a parent of this {@link CDockable}. * @return the closest station, may be <code>null</code> */ public CStation<?> getParentStation(); /** * Gets an action which is not added to the title by this {@link CDockable} * put by another module. * @param key the name of the action * @return an action or <code>null</code> */ public CAction getAction( String key ); /** * Gets a mutable map of colors. Clients can put colors into this map, and * the colors will be presented on the screen by various effects. * @return the map, this has always to be the same object */ public ColorMap getColors(); /** * Gets a mutable map of fonts. Clients can put fonts into this map, and * the fonts will be presented on the screen through various effects. * @return the map, this has always to be the same object */ public FontMap getFonts(); }