/* * Copyright (c) 2004 Christopher M Butler * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.flexdock.docking; import java.awt.Component; import java.beans.PropertyChangeListener; import java.util.List; import java.util.Set; import org.flexdock.docking.event.DockingListener; import org.flexdock.docking.event.DockingMonitor; import org.flexdock.docking.props.DockablePropertySet; /** * This interface is designed to specify the API's required by * {@code DockingManager} and {@code DockingPort} for dealing with dockable * components in a drag-n-drop fashion. A {@code Dockable} is the child * component that is docked into a {@code DockingPort}. * * @author Christopher Butler */ public interface Dockable extends DockingListener, DockingMonitor { /** * A constant property key to signify that a component is dockable. */ String DOCKABLE_INDICATOR = "Dockable.DOCKABLE_INDICATOR"; /** * Returns the value of the property with the specified key. Only properties * added with {@code putClientProperty} will return a non-{@code null} * value. * * @param key * the key that is being queried * @return the value of this property or {@code null} * @see javax.swing.JComponent#getClientProperty(java.lang.Object) */ Object getClientProperty(Object key); /** * Returns the Component that is to be dragged and docked. This may or may * not be included in the list returned by {@code getDragSources()}. * <p> * The framework performs indexing on the underlying {@code Component}. * Consequently, this method may <b>not</b> return a {@code null} * reference. * * @return the component wrapped by this dockable. */ Component getComponent(); /** * Returns the DockingPort within which this Dockable is currently docked. * If not currently docked, this method will return null. * * @return the docking port this dockable resides in, or {@code null} if the * dockable is not currently docked (i.e. in the middle of a drag * operation). */ DockingPort getDockingPort(); /** * Returns a {@code List} of the {@code Components} that are event sources * for drag operations. The list may or may not include the Component * returned by {@code getComponent()}. * * @return a list containing the components that may be used to drag this * dockable. */ List getDragSources(); /** * Returns a {@code Set} of the {@code Components} that are used as frame * drag sources. When a {@code Dockable} is floated into an external frame, * that frame may or may not have a titlebar for repositioning. The * Components returned by this method will be setup with appropriate event * listeners such that dragging them will serve to reposition the containing * frame as if they were the frame titlebar. If a Component exists in both * the Set returned by this method and the List returned by * {@code getDragSources()}, the "frame reposition" behavior will supercede * any "drag-to-dock" behavior while the Dockable is in a floating state. * * @return a set containing the components that may be used to drag the * frame this dockable resides in, if the dockable is floating. */ Set getFrameDragSources(); /** * Returns a {@code String} identifier that is unique within a JVM instance, * but persistent across JVM instances. This is used for configuration * mangement, allowing the JVM to recognize a {@code Dockable} instance * within an application instance, persist the ID, and recall it in later * application instances. The ID should be unique within an appliation * instance so that there are no collisions with other {@code Dockable} * instances, but it should also be consistent from JVM to JVM so that the * association between a {@code Dockable} instance and its ID can be * remembered from session to session. * <p> * The framework performs indexing on the persistent ID. Consequently, this * method may <b>not</b> return a {@code null} reference. * * @return the persistence id for this dockable. This id ensures that only * one copy of a given dockable will exist. */ String getPersistentId(); /** * Adds an arbitrary key/value "client property" to this {@code Dockable}. * {@code null} values are allowed. * * @param key * the new client property key. * @param value * the new client property value; if <code>null</code> this * method will remove the property. * @see javax.swing.JComponent#putClientProperty(java.lang.Object, * java.lang.Object) */ void putClientProperty(Object key, Object value); /** * Returns a {@code DockablePropertySet} instance associated with this * {@code Dockable}. Developers implementing the {@code Dockable} interface * may or may not choose to provide their own {@code DockablePropertySet} * implementation for use with this method. A default implementation is * supplied by the framework and most {@code Dockable} implementations, * including all implementations provided by the framework, will return the * default {@code DockablePropertySet} via a call to * {@code org.flexdock.docking.props.PropertyManager}. Developers are * encouraged to take advantage of this by calling * {@code PropertyManager.getDockablePropertySet(this)}. * * @return the {@code DockablePropertySet} associated with this * {@code Dockable} This method may not return a {@code null} * reference. * @see org.flexdock.docking.props.DockablePropertySet * @see org.flexdock.docking.props.PropertyManager#getDockablePropertySet(Dockable) */ DockablePropertySet getDockingProperties(); /** * Implements the semantics for docking an external {@code Dockable} to this * {@code Dockable} and returns a {@code boolean} indicating whether or not * the docking operation was successful. <p> The framework already * provides a default implementation for this method through * {@code DockingManager.dock(Dockable dockable, Dockable parent)}. While * users are free to provide their own implementation for this method, the * recommended approach is to use the default implementation with the * following line: <p> {@code return DockingManager.dock(dockable, this);} * * @param dockable * the {@code Dockable} to dock relative to this {@code Dockable} * @return {@code true} if the docking operation was successful; * {@code false} otherwise. * @see #dock(Dockable, String) * @see #dock(Dockable, String, float) * @see DockingManager#dock(Dockable, Dockable) */ boolean dock(Dockable dockable); /** * Implements the semantics for docking an external {@code Dockable} to the * specified region of this {@code Dockable} and returns a {@code boolean} * indicating whether or not the docking operation was successful. If the * docking operation results in a split layout, this method should determine * an appropriate ratio of available space to allot to the new sibling * {@code Dockable}. <p> The framework already provides a default * implementation for this method through * {@code DockingManager.dock(Dockable dockable, Dockable parent, String region)}. * While users are free to provide their own implementation for this method, * the recommended approach is to use the default implementation with the * following line: <p> * {@code return DockingManager.dock(dockable, this, relativeRegion);} * * @param dockable * the {@code Dockable} to dock relative to this {@code Dockable} * @param relativeRegion * the docking region into which to dock the specified * {@code Dockable} * @return {@code true} if the docking operation was successful; * {@code false} otherwise. * @see #dock(Dockable, String, float) * @see DockingManager#dock(Dockable, Dockable, String) */ boolean dock(Dockable dockable, String relativeRegion); /** * Implements the semantics for docking an external {@code Dockable} to the * specified region of this {@code Dockable} with the specified layout * ratio, returning a {@code boolean} indicating whether or not the docking * operation was successful. If the docking operation results in a split * layout, this method should use the specified {@code ratio} to determine * the amount of available space to allot to the new sibling * {@code Dockable}. * <p> * The framework already provides a default implementation for this method * through * {@code DockingManager.dock(Dockable dockable, Dockable parent, String region, float proportion)}. * While users are free to provide their own implementation for this method, * the recommended approach is to use the default implementation with the * following line: * <p> * {@code return DockingManager.dock(dockable, this, relativeRegion, ratio);} * * @param dockable * the {@code Dockable} to dock relative to this {@code Dockable} * @param relativeRegion * the docking region into which to dock the specified * {@code Dockable} * @param ratio * the proportion of available space in the resulting layout to * allot to the new sibling {@code Dockable}. * @return {@code true} if the docking operation was successful; * {@code false} otherwise. * @see DockingManager#dock(Dockable, Dockable, String, float) */ boolean dock(Dockable dockable, String relativeRegion, float ratio); /** * Adds a PropertyChangeListener to the listener list. The listener is * registered for all bound properties of this class. Note that if this * Dockable is inheriting a bound property, then no event will be fired in * response to a change in the inherited property. * <p> * If listener is null, no exception is thrown and no action is performed. * * @param listener * the PropertyChangeListener to be added * * @see #removePropertyChangeListener(PropertyChangeListener) */ void addPropertyChangeListener(PropertyChangeListener listener); /** * Removes a PropertyChangeListener from the listener list. This method * should be used to remove PropertyChangeListeners that were registered for * all bound properties of this class. * <p> * If listener is null, no exception is thrown and no action is performed. * * @param listener * the PropertyChangeListener to be removed * * @see #addPropertyChangeListener */ void removePropertyChangeListener(PropertyChangeListener listener); }