All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.gui.DockStation Maven / Gradle / Ivy

There is a newer version: 1.1.2p6a
Show 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;

import java.awt.Component;
import java.awt.Rectangle;

import javax.swing.JFrame;

import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.DockElementRepresentative;
import bibliothek.gui.dock.DockFactory;
import bibliothek.gui.dock.accept.DockAcceptance;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.event.DockStationListener;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.station.DockableDisplayer;
import bibliothek.gui.dock.station.StationPaint;
import bibliothek.gui.dock.station.support.PlaceholderList;
import bibliothek.gui.dock.station.support.PlaceholderMap;
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
import bibliothek.gui.dock.title.DockTitle;
import bibliothek.gui.dock.title.DockTitleFactory;
import bibliothek.gui.dock.title.DockTitleManager;
import bibliothek.gui.dock.title.DockTitleRequest;
import bibliothek.gui.dock.title.DockTitleVersion;

/**
 * A DockStation is some area (e.g. a {@link Component}) showing
 * a set of {@link Dockable}s called "children". The station is free to decide how and if to
 * show its children.
* Although a station can take any form, there are some (optional) practices to follow: *
    *
  • Each {@link Dockable} should be child of a {@link DockableDisplayer}. The displayer will * paint border and title of the item.
  • *
  • This station should be aware of the current {@link DockTheme} and use its factories and delegates whenever possible.
  • *
  • Drag and drop is handled by the {@link DockController}. Methods like {@link #canDrag(Dockable)}, {@link #drag(Dockable)}, * {@link #drop()} or {@link #move()} need to be implemented for this. Also {@link #accept(Dockable)}, {@link Dockable#accept(DockStation)}, * {@link Dockable#accept(DockStation, Dockable)} and the {@link DockAcceptance} of the current {@link DockController} should be checked before * allowing a drag and drop operation.
  • *
  • For each child there should be at least one {@link DockTitle}. This station needs to derive a {@link DockTitleVersion} from * its controller using the {@link DockController#getDockTitleManager() DockTitleManager} and its * {@link DockTitleManager#registerDefault(String, DockTitleFactory) factory method}. With the {@link DockTitleVersion}-object one * {@link DockTitleRequest} for each required {@link DockTitle} can be created.
  • *
  • One child can be focused. If this station changes the focus it should use {@link DockController#setAtLeastFocusedDockable(Dockable, Component)}.
  • *
  • This station should support placeholders. The current {@link PlaceholderStrategy} can be used to convert {@link Dockable}s to placeholders. * A {@link PlaceholderList} is a good datastructure to store {@link Dockable}s and placeholders at the same time.
  • *
  • Additional points where the user can start drag and drop operations can be installed by implementing a {@link DockElementRepresentative}. It * has to be installed using {@link DockController#addRepresentative(DockElementRepresentative)}.
  • *
  • And a new {@link DockFactory} will be required to persistently store the layout of this station.
  • *
* @author Benjamin Sigg */ public interface DockStation extends DockElement{ /** * Sets the controller of this station. If the station wants to * show any {@link DockTitle}, then the titles have to be replaced * by new instances (assuming the controller is really new). The * title has to get new {@link DockTitleVersion DockTitleVersions} through * the {@link DockTitleManager} of controller.
* An argument of null means that this station is currently * not shown. * @param controller the owner of this station, can be null */ public void setController( DockController controller ); /** * Gets the controller of this station. * @return the controller or null if no controller is set * @see #setController(DockController) */ public DockController getController(); /** * Updates the {@link DockTheme} of this station. The new theme * has to be read from the {@link #getController() controller} of * this station. If the controller is null, this method * should return immediately.
* You may use {@link DockUI#updateTheme(DockStation, DockFactory)} * to implement this method. */ public void updateTheme(); /** * Gets the current theme of this station. The theme can be null, * but that means that the station is not fully initialized, and might not * work correct. * @return the theme of this station or null. */ public DockTheme getTheme(); /** * Gets a list of actions which should be available for the user and * affect the child dockable. * @param dockable a child of this station * @return actions for dockable, can be null */ public DockActionSource getDirectActionOffers( Dockable dockable ); /** * Gets a list of actions which should be available for the user and * affect dockable. The argument dockable * can be a child of this station, or a child of any station which is * below this station. * @param dockable a child of this station or a child of another station * which is below this station * @return actions for dockable or null */ public DockActionSource getIndirectActionOffers( Dockable dockable ); /** * Adds a listener to this station. The station has to invoke the * methods of the listener such that its requirements are full filled. * @param listener the listener to add */ public void addDockStationListener( DockStationListener listener ); /** * Removes a listener from this station. * @param listener the listener to remove */ public void removeDockStationListener( DockStationListener listener ); /** * Tells whether the child dockable is visible or not. Visible * means that the {@link Dockable#getComponent() component} of dockable * can be seen by the user. The result must be false if * this station is not visible. * @param dockable the child whose visibility-state is questioned * @return whether dockable is visible or not * @see #isStationVisible() */ public boolean isVisible( Dockable dockable ); /** * Tells whether this station is visible or not. For example a station on * a {@link JFrame} is not visible if the frame is minimized. * @return whether this station is visible */ public boolean isStationVisible(); /** * Gets the number of children. * @return the number of children on this station */ public int getDockableCount(); /** * Gets the index'th child of this station. * @param index a value between 0 (incl.) and {@link #getDockableCount()} * (excl.). * @return a child of this station */ public Dockable getDockable( int index ); /** * Gets the favorite child of this station. The favorite child is the one * child which is specially designated for the user. An example: if the * station behaves like a stack, and only the top child is visible, then * the favorite child could the the top.
* A result of null indicates that there are no children * at all, or that there is no favorite child (all children are equal important).
* Stations should not change this property directly, they should call * {@link DockController#setFocusedDockable(Dockable, boolean)} * which will then call {@link #setFrontDockable(Dockable)}. Note that the * DockController itself listens to the DockTitles, and maybe the station * doesn't need a logic to decide which child is important. * @return the most important child or null */ public Dockable getFrontDockable(); /** * Sets the most important child. The station should ensure that this child * is visible (assuming the station itself is visible). Read the * comment on {@link #getFrontDockable()} how stations can change * this property. * @param dockable the new favorite child, can be null * @see #getFrontDockable() */ public void setFrontDockable( Dockable dockable ); /** * Gets a snapshot of all placeholders that are currently stored in this {@link DockStation}. * A {@link DockStation} is free in the format it chooses to fill the map. The map is to be * created with the assumptions that {@link #getDockableCount()} is 0, meaning * any existing {@link Dockable} gets replaced by its placeholder. The current * {@link PlaceholderStrategy} should be used to convert {@link Dockable}s to placeholders. * @return the map of placeholders or null if this station does not support * placeholders */ public PlaceholderMap getPlaceholders(); /** * Sets an earlier snapshot of the placeholders of this station. This station can assume that * it currently does not have any children (that {@link #getDockableCount()} is 0).
* This method does nothing if it cannot handle the format or the version of placeholders. * @param placeholders some set of placeholders * @throws IllegalStateException if {@link #getDockableCount()} is not equal to 0 */ public void setPlaceholders( PlaceholderMap placeholders ); /** * Called by the {@link DockController} of this station to indicate that * the active-state of title has been changed. This station * should call the method title.{@link DockTitle#changed(bibliothek.gui.dock.event.DockTitleEvent) changed} * with an appropriate event. The station may add some additional information * to this call. * @param dockable the child whose title is changed * @param title the changed title, may not be bound * @param active the new state of the title */ public void changed( Dockable dockable, DockTitle title, boolean active ); /** * Provides a {@link DockTitle} for a child of this station. This method * must call {@link DockTitleRequest#answer(DockTitle)} to set the result.
* Most {@link DockStation}s won't have the need to implement this method, * leaving it empty will advice the framework to use another source for * new {@link DockTitle}s. * @param request the request to answer, not null */ public void requestChildDockTitle( DockTitleRequest request ); /** * Tells whether this station accepts child as a new child, * or refuses child. The user will not be able to drop * a {@link Dockable} onto this station if this method returns * false. * @param child a {@link Dockable} which may become a child * @return true if child is accepted */ public boolean accept( Dockable child ); /** * Gets precise information about the location of a child of this station. * The result of this method could later be used to invoke * {@link #drop(Dockable, DockableProperty)}. * @param child a child of this station, this childs location is asked * @param target an optional hint telling for which dockable the location information * will be used, can be null. This hint can be used to find a placeholder * that should be part of the result. * @return the location * @see bibliothek.gui.dock.util.DockUtilities#getPropertyChain(DockStation, Dockable) */ public DockableProperty getDockableProperty( Dockable child, Dockable target ); /** * Prepares this station to get the new child dockable. The * station has to store a possible location of the child, and should draw * some indicators where the child will be put. The station can refuse * dockable, in this case nothing has to be painted and * this method returns false.
* There are some constraints: *
    *
  • The result should be false if this station is dockable, * checkOverrideZone is true and the mouse is in * the override-zone. of the parent. However, that condition is just "good manners" and may * be broken.
  • *
  • This method should use {@link #accept(Dockable)} and {@link Dockable#accept(DockStation)} * or {@link Dockable#accept(DockStation, Dockable)} to ensure that the desired * drop-location is valid.
  • *
  • The method should use the {@link DockAcceptance} of its controller * (see {@link DockController#getAcceptance()}) to ensure that the drop/location is valid.
  • *
* This method gets two points: mouseX/mouseY is the location * of the mouse, titleX/titleY is the location of the dragged * title. The second point may be interesting if the title of a dropped * child should have the same coordinates as the image of the dragged title.
* This method is never called if dockable is a child of this * station. In such a case {@link #prepareMove(int, int, int, int, boolean, Dockable) prepareMove} * is invoked. * @param mouseX the x-coordinate of the mouse on the screen * @param mouseY the y-coordinate of the mouse on the screen * @param titleX the x-location of the dragged title or mouseX if no * title is dragged * @param titleY the y-location of the dragged title or mouseY if no * title is dragged * @param checkOverrideZone whether this station has to check if the mouse * is in the override-zone of its parent * @param dockable the element which will be dropped * @return true if dockable can be added at the * current location, false otherwise. */ public boolean prepareDrop( int mouseX, int mouseY, int titleX, int titleY, boolean checkOverrideZone, Dockable dockable ); /** * Adds the {@link Dockable} of the last run of * {@link #prepareDrop(int, int, int, int, boolean, Dockable) prepareDrop} to this station. * This method is only called if the new child and this station accepted * each other, prepareDrop returned true and * the new child is not yet a child of this station. */ public void drop(); /** * Adds dockable to this station. The station can decide * by its own where to put dockable. * @param dockable a new child */ public void drop( Dockable dockable ); /** * Tries to add dockable to this station such that the location * given by property is matched. If property * has a {@link DockableProperty#getSuccessor() successor} and points to * another station, just call the drop-method of this * child-station. Note that property can be of any type and * contain invalid information. * @param dockable the new child * @param property the location of the child, may be invalid data * @return true if property could be read * and dockable was dropped, false * otherwise. */ public boolean drop( Dockable dockable, DockableProperty property ); /** * Prepares the station that one of its children is moved from one * location to another location. See {@link #prepareDrop(int, int, int, int, boolean, Dockable) prepareDrop} * for detailed information about the behavior of this method. The only * difference between this method and prepareDrop is, that * dockable is a child of this station. * @param mouseX the x-coordinate of the mouse on the screen * @param mouseY the y-coordinate of the mouse on the screen * @param titleX the x-location of the dragged title or mouseX if no * title is dragged * @param titleY the y-location of the dragged title or mouseY if no * title is dragged * @param checkOverrideZone whether this station has to check if the * mouse is in the override-zone of its parent * @param dockable the element which will be moved * @return true if dockable can be added at the * current location, false otherwise. */ public boolean prepareMove( int mouseX, int mouseY, int titleX, int titleY, boolean checkOverrideZone, Dockable dockable ); /** * Moves a child of this station to a new location according to the * information gathered by {@link #prepareMove(int, int, int, int, boolean, Dockable) prepareMove}. */ public void move(); /** * Tries to move the child dockable in such a way, that * {@link DockStation#getDockableProperty(Dockable, Dockable)} would return a * {@link DockableProperty} that equals property.
* There is no need to give a guarantee that the move successes, and clients * should always be prepared for the possibility that this {@link DockStation} * does nothing at all. * @param dockable a child of this station * @param property the preferred position of dockable */ public void move( Dockable dockable, DockableProperty property ); /** * Informs this station that the information gathered by * {@link #prepareDrop(int, int, int, int, boolean, Dockable) prepareDrop} or * {@link #prepareMove(int, int, int, int, boolean, Dockable) prepareMove} should * be painted somehow onto this station.
* The station should use the {@link StationPaint} of its theme * to draw. */ public void draw(); /** * Tells this station that a possible drop or move on this station * was canceled. The station can throw away any information gathered by * the last call {@link #prepareDrop(int, int, int, int, boolean, Dockable) prepareDrop} * or {@link #prepareMove(int, int, int, int, boolean, Dockable) prepareMove}
* If the station is drawing some markings because of a call to * {@link #draw()}, than the station can throw away these markings too. */ public void forget(); /** * If the controller asks a station if a child could be dropped or moved, * the controller assumes that no other station has interest in this event. * However if this station is a dockable, and has a parent, the parent might * be interested in the new child. This dockable station has to ask the * parent if the current location of the mouse is in the override-zone. This * station should not accept a child if the parent returns true.
* On the other hand, this station could be asked by a child whether the mouse * is in the override-zone. If the mouse hits a point of special interest, * then the method should return true.
* Note: if this station is asked and is a dockable station itself, then * this method should ask the parent for his override-zone too. * @param x the x-coordinate of the mouse on the screen * @param y the y-coordinate of the mouse on the screen * @param invoker a child of this station which invoked the method * @param drop a {@link Dockable} which might become a child * @param the type of invoker * @return true if the location of the mouse is of special * interest */ public boolean isInOverrideZone( int x, int y, D invoker, Dockable drop ); /** * Tells whether dockable can be removed from this station or not. * This method assumes that dockable is a child of * this station, if not, then the behavior of this method is unspecified.
* Note that the result of this method may not be respected every time, * it's more a hint for the controller how to act. * @param dockable a child of this station * @return true if dockable can be dragged */ public boolean canDrag( Dockable dockable ); /** * Removes a child from this station. This method may be called even * if {@link #canDrag(Dockable)} returned false.
* Note: clients may need to invoke {@link DockController#freezeLayout()} * and {@link DockController#meltLayout()} to ensure noone else adds or * removes Dockables. * @param dockable the child to remove */ public void drag( Dockable dockable ); /** * Tells whether its possible to replace the child old * with next where next is not a child of this station. * @param old a child of this station * @param next the replacement of next. * @return true if the replacement is possible * @throws IllegalArgumentException if next is a child * of this station */ public boolean canReplace( Dockable old, Dockable next ); /** * Replaces the child old by next which is * not yet a child of this station. This method should not be * called if {@link #canReplace(Dockable, Dockable) canReplace} returned * false. * @param old a child * @param next the replacement of old * @throws IllegalArgumentException if next is a child of * this station or if old is not a child */ public void replace( Dockable old, Dockable next ); /** * Replaces the child old by next which is * not yet a child of this station. This method should not be * called if {@link #canReplace(Dockable, Dockable) canReplace} returned * false. This method can assume that next was * a child of old but no longer is. * @param old a dockable station that is a child of this station * @param next the replacement of old * @throws IllegalArgumentException if next is a child of * this station, if old is not a child or if old * is not a {@link Dockable} */ public void replace( DockStation old, Dockable next ); /** * Gets a rectangle in which all points of the station are. The user is * only able to move a {@link Dockable} into this area onto this station. * @return the bounds, relative to the screen, null to indicate that * this station has not any bounds */ public Rectangle getStationBounds(); /** * Tells whether this station knows a rule how to compare itself with * station. See {@link #compare(DockStation)} for more * details. * @param station another station * @return true if a call to {@link #compare(DockStation) compare} * will not end in an exception and return another value than 0 */ public boolean canCompare( DockStation station ); /** * Compares this station with station. The comparison is needed * if the {@link #getStationBounds() stations bounds} of the two station * have common points. On a drag-event, the controller needs a way to * decide which station is more important (and receives the opportunity * to get a new child first). The controller will use the method * compare to do this. This method works like * {@link Comparable#compareTo(Object)}. * @param station another station * @return a number less/equal/higher than zero, if this station has * higher/equal/lesser priority than station. */ public int compare( DockStation station ); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy