📄 defaultdockingstrategy.java
字号:
*
* @param dockable
* the {@code Dockable} we wish to dock
* @param port
* the {@code DockingPort} into which we wish to dock
* @param region
* the region of the specified {@code DockingPort} into which we
* wish to dock.
* @return {@code true} if the docking operation was successful,
* {@code false}. otherwise.
* @see #dock(Dockable, DockingPort, String, DragOperation)
* @see Dockable#getDockingProperties()
* @see DockablePropertySet#isTerritoryBlocked(String)
*/
public boolean dock(Dockable dockable, DockingPort port, String region,
DragOperation operation) {
if (!isDockingPossible(dockable, port, region, operation))
return false;
if (!dragThresholdElapsed(operation))
return false;
// cache the old parent
DockingPort oldPort = dockable.getDockingPort();
// perform the drop operation.
DockingResults results = dropComponent(dockable, port, region,
operation);
// perform post-drag operations
DockingPort newPort = results.dropTarget;
int evtType = results.success ? DockingEvent.DOCKING_COMPLETE
: DockingEvent.DOCKING_CANCELED;
Map dragContext = DragManager.getDragContext(dockable);
DockingEvent evt = new DockingEvent(dockable, oldPort, newPort,
evtType, dragContext);
// populate DockingEvent status info
evt.setRegion(region);
evt.setOverWindow(operation == null ? true : operation.isOverWindow());
// notify the old docking port, new dockingport,and dockable
Object[] evtTargets = { oldPort, newPort, dockable };
EventManager.dispatch(evt, evtTargets);
return results.success;
}
protected boolean dragThresholdElapsed(DragOperation token) {
if (token == null || token.isPseudoDrag() || token.getStartTime() == -1)
return true;
long elapsed = System.currentTimeMillis() - token.getStartTime();
// make sure the elapsed time of the drag is at least over .2 seconds.
// otherwise, we'll probably be responding to inadvertent clicks (maybe
// double-clicks)
return elapsed > 200;
}
protected boolean isDockingPossible(Dockable dockable, DockingPort port,
String region, DragOperation token) {
// superclass blocks docking if the 'port' or 'region' are null. If
// we've dragged outside
// the bounds of the parent frame, then both of these will be null. This
// is expected here and
// we intend to float in this case.
if (isFloatable(dockable, token))
return true;
// check to see if we're already floating and we're trying to drop into
// the
// same dialog.
DockingPort oldPort = DockingManager.getDockingPort(dockable);
if (oldPort instanceof FloatingDockingPort && oldPort == port) {
// only allow this situation if we're not the *last* dockable
// in the viewport. if we're removing the last dockable, then
// the dialog will disappear before we redock, and we don't want
// this
// to happen.
FloatingDockingPort floatingDockingPort = (FloatingDockingPort) oldPort;
if (floatingDockingPort.getDockableCount() == 1)
return false;
}
if (dockable == null || dockable.getComponent() == null || port == null)
return false;
if (!DockingManager.isValidDockingRegion(region))
return false;
Dockable docked = DockingManager.getDockable(port.getDockedComponent());
if (docked == null)
return true;
// don't allow them to dock into this region if the territory there is
// blocked.
if (docked.getDockingProperties().isTerritoryBlocked(region)
.booleanValue())
return false;
// check to see if we're already docked into this region.
// get the parent dockingPort.
Container container = docked.getComponent().getParent();
// now get the grandparent dockingport
DockingPort grandparent = DockingManager.getDockingPort(container);
// if we don't share the grandparent dockingport, then we're definitely
// not split in the same dockingport
// across different region. in this case, it's ok to proceed with the
// dock
if (grandparent == null)
return true;
Component currentlyInRegion = grandparent.getComponent(region);
// block docking if we're already the component docked within the
// specified region
if (currentlyInRegion == dockable.getComponent())
return false;
return true;
}
protected boolean isFloatable(Dockable dockable, DragOperation token) {
// can't float null objects
if (dockable == null || dockable.getComponent() == null
|| token == null)
return false;
// can't float on a fake drag operation
if (token.isPseudoDrag())
return false;
// TODO: break this check out into a separate DropPolicy class.
// should be any customizable criteria, not hardcoded to checking
// for being outside the bounds of a window
if (token.isOverWindow())
return false;
return true;
}
protected DockingResults dropComponent(Dockable dockable,
DockingPort target, String region, DragOperation token) {
if (isFloatable(dockable, token))
return floatComponent(dockable, target, token);
DockingResults results = new DockingResults(target, false);
if (UNKNOWN_REGION.equals(region) || target == null) {
return results;
}
Component docked = target.getDockedComponent();
Component dockableCmp = dockable.getComponent();
if (dockableCmp != null && dockableCmp == docked) {
// don't allow docking the same component back into the same port
return results;
}
// obtain a reference to the content pane that holds the target
// DockingPort.
// MUST happen before undock(), in case the undock() operation removes
// the
// target DockingPort from the container tree.
Container contentPane = SwingUtility.getContentPane((Component) target);
Point contentPaneLocation = token == null ? null : token
.getCurrentMouse(contentPane);
// undock the current Dockable instance from it's current parent
// container
undock(dockable);
// when the original parent reevaluates its container tree after
// undocking, it checks to see how
// many immediate child components it has. split layouts and tabbed
// interfaces may be managed by
// intermediate wrapper components. When undock() is called, the docking
// port
// may decide that some of its intermedite wrapper components are no
// longer needed, and it may get
// rid of them. this isn't a hard rule, but it's possible for any given
// DockingPort implementation.
// In this case, the target we had resolved earlier may have been
// removed from the component tree
// and may no longer be valid. to be safe, we'll resolve the target
// docking port again and see if
// it has changed. if so, we'll adopt the resolved port as our new
// target.
if (contentPaneLocation != null && contentPane != null) {
results.dropTarget = DockingUtility.findDockingPort(contentPane,
contentPaneLocation);
target = results.dropTarget;
}
results.success = target.dock(dockableCmp, region);
SwingUtility.revalidate((Component) target);
return results;
}
/**
* Undocks the specified {@code Dockable} from it's parent
* {@code DockingPort}. If {@code dockable} is {@code null} or is not
* currently docked within a {@code DockingPort}, then this method returns
* {@code false}.
*
* @param dockable
* the {@code Dockable} to be undocked.
* @return {@code true} if the undocking operation was successful,
* {@code false} otherwise.
* @see #dock(Dockable, DockingPort, String)
*/
public boolean undock(Dockable dockable) {
if (dockable == null)
return false;
Component dragSrc = dockable.getComponent();
Container parent = dragSrc.getParent();
RootWindow rootWin = RootWindow.getRootContainer(parent);
// if there's no parent container, then we really don't have anything
// from which to to
// undock this component, now do we?
if (parent == null)
return false;
boolean success = false;
DockingPort dockingPort = DockingUtility.getParentDockingPort(dragSrc);
// notify that we are about to undock
Map dragContext = DragManager.getDragContext(dockable);
DockingEvent dockingEvent = new DockingEvent(dockable, dockingPort,
dockingPort, DockingEvent.UNDOCKING_STARTED, dragContext);
EventManager.dispatch(dockingEvent);
// if(dockingEvent.isConsumed())
// return false;
if (dockingPort != null) {
// if 'dragSrc' is currently docked, then undock it instead of using
// a
// simple remove(). this will allow the DockingPort to do any of its
// own
// cleanup operations associated with component removal.
success = dockingPort.undock(dragSrc);
} else {
// otherwise, just remove the component
parent.remove(dragSrc);
success = true;
}
if (rootWin != null) {
SwingUtility.revalidate(rootWin.getContentPane());
SwingUtility.repaint(rootWin.getContentPane());
}
if (success) {
dockingEvent = new DockingEvent(dockable, dockingPort, dockingPort,
DockingEvent.UNDOCKING_COMPLETE, dragContext);
// notify the docking port and dockable
Object[] evtTargets = { dockingPort, dockable };
EventManager.dispatch(dockingEvent, evtTargets);
}
return success;
}
protected DockingResults floatComponent(Dockable dockable,
DockingPort target, DragOperation token) {
// otherwise, setup a new DockingFrame and retarget to the CENTER region
DockingResults results = new DockingResults(target, false);
// determine the bounds of the new frame
Point screenLoc = token.getCurrentMouse(true);
SwingUtility.add(screenLoc, token.getMouseOffset());
Rectangle screenBounds = dockable.getComponent().getBounds();
screenBounds.setLocation(screenLoc);
// create the frame
FloatManager mgr = DockingManager.getFloatManager();
DockingFrame frame = mgr.floatDockable(dockable, dockable
.getComponent(), screenBounds);
// grab a reference to the frame's dockingPort for posterity
results.dropTarget = frame.getDockingPort();
results.success = true;
return results;
}
protected static class DockingResults {
public DockingResults(DockingPort port, boolean status) {
dropTarget = port;
success = status;
}
public DockingPort dropTarget;
public boolean success;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -