📄 dockingutility.java
字号:
/*
* Created on Mar 14, 2005
*/
package org.flexdock.util;
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import javax.swing.JComponent;
import javax.swing.JRootPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import org.flexdock.docking.Dockable;
import org.flexdock.docking.DockingConstants;
import org.flexdock.docking.DockingManager;
import org.flexdock.docking.DockingPort;
import org.flexdock.docking.defaults.DefaultRegionChecker;
import org.flexdock.docking.props.DockablePropertySet;
import org.flexdock.docking.state.DockingState;
import org.flexdock.docking.state.MinimizationManager;
/**
* @author Christopher Butler
*/
public class DockingUtility implements DockingConstants {
private DockingUtility() {
// does nothing
}
/**
* Returns the {@code DockingPort} that contains the specified
* {@code Dockable}. If the {@code Dockable} is {@code null}, then a
* {@code null} reference is returned.
* <p>
* This method will only return the immediate parent {@code DockingPort} of
* the specified {@code Dockable} This means that a check is performed for
* the {@code Component} returned by the {@code Dockable's}
* {@code getComponent()} method. The {@code DockingPort} returned by this
* method will not only be an ancestor {@code Container} of this
* {@code Component}, but invoking the {@code DockingPort's}
* {@code isParentDockingPort(Component comp)} with the this
* {@code Component} will also return {@code true}. If both of these
* conditions cannot be satisfied, then this method returns a {@code null}
* reference.
*
* @param d
* the {@code Dockable} whose parent {@code DockingPort} is to be
* returned.
* @return the imediate parent {@code DockingPort} that contains the
* specified {@code Dockable}.
* @see #getParentDockingPort(Component)
*/
public static DockingPort getParentDockingPort(Dockable d) {
return d == null ? null : getParentDockingPort(d.getComponent());
}
/**
* Returns the {@code DockingPort} that contains the specified
* {@code Component}. If the {@code Component} is {@code null}, then a
* {@code null} reference is returned.
* <p>
* This method will only return the immediate parent {@code DockingPort} of
* the specified {@code Component} This means that the {@code DockingPort}
* returned by this method will not only be an ancestor {@code Container} of
* the specified {@code Component}, but invoking its
* {@code isParentDockingPort(Component comp)} with the specified
* {@code Component} will also return {@code true}. If both of these
* conditions cannot be satisfied, then this method returns a {@code null}
* reference.
*
* @param comp
* the {@code Component} whose parent {@code DockingPort} is to
* be returned.
* @return the immediate parent {@code DockingPort} that contains the
* specified {@code Component}.
*/
public static DockingPort getParentDockingPort(Component comp) {
DockingPort port = comp == null ? null : (DockingPort) SwingUtilities
.getAncestorOfClass(DockingPort.class, comp);
if (port == null)
return null;
return port.isParentDockingPort(comp) ? port : null;
}
/**
* Returns {@code true} if the specified {@code DockingPort} has an ancestor
* {@code DockingPort}; {@code false} otherwise. If the specified
* {@code DockingPort} is {@code null}, then this method returns
* {@code false}.
*
* @param dockingPort
* the {@code DockingPort} to check for an ancestor port
* @return {@code true} if the specified {@code DockingPort} has an ancestor
* {@code DockingPort}; {@code false} otherwise.
* @see SwingUtilities#getAncestorOfClass(java.lang.Class,
* java.awt.Component)
*/
public static boolean isSubport(DockingPort dockingPort) {
return dockingPort == null ? false : SwingUtilities.getAncestorOfClass(
DockingPort.class, (Component) dockingPort) != null;
}
/**
* Returns the deepest {@code DockingPort} within the specified
* {@code Container} at the specified {@code location}. If either
* {@code container} or {@code location} are {@code null}, then this method
* returns {@code null}.
* <p>
* This method will find the deepest {@code Component} within the specified
* container that the specified {@code Point} via
* {@code SwingUtilities.getDeepestComponentAt(Component parent, int x, int y)}.
* If no {@code Component} is resovled, then this method returns
* {@code null}. If the resolved {@code Component} is a {@code DockingPort},
* then it is returned. Otherwise, the {@code Component's}
* {@code DockingPort} ancestor is resovled and returned from
* {@code SwingUtilities.getAncestorOfClass(Class c, Component comp)},
* passing {@code DockingPort.class} for the ancestor class parameter.
*
* @param container
* the {@code Container} within which to find a
* {@code DockingPort}.
* @param location
* the point within the specified {@code Container} at which to
* search for a {@code DockingPort}.
* @return the deepest {@code DockingPort} within the specified
* {@code Container} at the specified {@code location}.
* @see SwingUtilities#getDeepestComponentAt(java.awt.Component, int, int)
* @see SwingUtilities#getAncestorOfClass(java.lang.Class,
* java.awt.Component)
*/
public static DockingPort findDockingPort(Container container,
Point location) {
if (container == null || location == null)
return null;
Component deepestComponent = SwingUtilities.getDeepestComponentAt(
container, location.x, location.y);
if (deepestComponent == null)
return null;
// we're assured here that the deepest component is both a Component and
// DockingPort in
// this case, so we're okay to return here.
if (deepestComponent instanceof DockingPort)
return (DockingPort) deepestComponent;
// getAncestorOfClass() will either return a null or a Container that is
// also an instance of
// DockingPort. Since Container is a subclass of Component, we're fine
// in returning both
// cases.
return (DockingPort) SwingUtilities.getAncestorOfClass(
DockingPort.class, deepestComponent);
}
/**
* Returns the specified {@code region's} cross-axis equivalent region in
* accordance with the orientation used by the specified {@code JSplitPane}.
* If the {@code JSplitPane} is {@code null}, or the specified
* {@code region} is invalid according to
* {@code DockingManager.isValidDockingRegion(String region)}, then this
* method returns {@code null}.
*
* {@code NORTH_REGION} and {@code SOUTH_REGION} are considered "vertical"
* regions, while {@code WEST_REGION} and {@code EAST_REGION} are considered
* horizontal regions. If the {@code JSplitPane} orientation matches the
* specified {@code region} orientation, then the original {@code region}
* value is returned. For instance, if the specified {@code region} is
* {@code EAST_REGION}, and the {@code JSplitPane} is of a horizontal
* orientation, then there is no need to translate the {@code region}
* parameter across axes since its current axis is already horizontal. In
* this case, {@code EAST_REGION} would be returned by this method.
* <p>
* If the axis of the specified {@code region} does not match the
* orientation of the {@code JSplitPane}, then the region is translated to
* its cross-axis equivalent and returns. In this case, {@code NORTH_REGION}
* will be translated to {@code WEST_REGION}, {@code SOUTH_REGION} to
* {@code EAST_REGION}, {@code WEST_REGION} to {@code NORTH_REGION}, and
* {@code EAST_REGION} to {@code SOUTH_REGION}. {@code CENTER_REGION} is
* never altered.
*
* @param splitPane
* the {@code JSplitPane} whose orientation is to be used as a
* target axis
* @param region
* the docking region to translate to the target axis
* @return the specified {@code region's} cross-axis equivalent region in
* accordance with the orientation used by the specified
* {@code JSplitPane}.
* @see DockingManager#isValidDockingRegion(String)
* @see JSplitPane#getOrientation()
* @see #isAxisEquivalent(String, String)
*/
public static String translateRegionAxis(JSplitPane splitPane, String region) {
if (splitPane == null || !DockingManager.isValidDockingRegion(region))
return null;
boolean horizontal = splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT;
if (horizontal) {
if (NORTH_REGION.equals(region))
region = WEST_REGION;
else if (SOUTH_REGION.equals(region))
region = EAST_REGION;
} else {
if (WEST_REGION.equals(region))
region = NORTH_REGION;
else if (EAST_REGION.equals(region))
region = SOUTH_REGION;
}
return region;
}
/**
* Returns the opposite docking region of the specified {@code region}. For
* {@code NORTH_REGION}, this method returns {@code SOUTH_REGION}. For
* {@code SOUTH_REGION}, this method returns {@code NORTH_REGION}. For
* {@code EAST_REGION}, this method returns {@code WEST_REGION}. For
* {@code WEST_REGION}, this method returns {@code EAST_REGION}. For
* {@code CENTER_REGION} or an invalid region, as specified by
* {@code DockingManager.isValidDockingRegion(String region)}, this method
* return {@code CENTER_REGION}.
*
* @param region
* the region whose opposite is to be returned.
* @return the opposite docking region of the specified {@code region}.
* @see DockingManager#isValidDockingRegion(String)
*/
public static String flipRegion(String region) {
if (!DockingManager.isValidDockingRegion(region)
|| CENTER_REGION.equals(region))
return CENTER_REGION;
if (NORTH_REGION.equals(region))
return SOUTH_REGION;
if (SOUTH_REGION.equals(region))
return NORTH_REGION;
if (EAST_REGION.equals(region))
return WEST_REGION;
return EAST_REGION;
}
/**
* Tests for region equivalency between the specified region parameters
* across horizontal and vertical axes. If either {@code region} or
* {@code otherRegion} are {@code null} or invalid according to
* {@code DockingManager.isValidDockingRegion(String region)}, then this
* method returns {@code false}.
* <p>
* Equivalency within the same axis means that the two specified regions are
* the same value, as each region is unique within its axis. Thus, this
* method returns {@code true} if {@code region.equals(otherRegion)} returns
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -