org.flexdock.docking.defaults

## Class DefaultDockingStrategy

- java.lang.Object
- - org.flexdock.docking.defaults.DefaultDockingStrategy

- All Implemented Interfaces:
    DockingConstants, DockingStrategy

      public class DefaultDockingStrategy
      extends java.lang.Object
      implements DockingStrategy, DockingConstants

  Author:
    Christopher Butler

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `protected static class` | `DefaultDockingStrategy.DockingResults`

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static java.lang.String` | `PREFERRED_PROPORTION`

    - ### Fields inherited from interface org.flexdock.docking.DockingConstants

      `ACTIVE_WINDOW, BOTTOM, CENTER, CENTER_REGION, CLOSE_ACTION, DEFAULT_PERSISTENCE_KEY, DOCKING_ID, EAST_REGION, HEAVYWEIGHT_DOCKABLES, HORIZONTAL, LEFT, MOUSE_PRESSED, NORTH_REGION, PERMANENT_FOCUS_OWNER, PIN_ACTION, REGION, RIGHT, SOUTH_REGION, TOP, UNINITIALIZED, UNINITIALIZED_RATIO, UNKNOWN_REGION, UNSPECIFIED_SIBLING_PREF, VERTICAL, WEST_REGION`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `DefaultDockingStrategy()`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `DockingPort` | `createDockingPort(DockingPort base)` Returns a new `DefaultDockingPort` with characteristics similar to the specified base `DockingPort`.
    `protected DockingPort` | `createDockingPortImpl(DockingPort base)`
    `javax.swing.JSplitPane` | `createSplitPane(DockingPort base, java.lang.String region)` Returns a new `DockingSplitPane` based on the specified `DockingPort`.
    `protected javax.swing.JSplitPane` | `createSplitPaneImpl(DockingPort base, java.lang.String region)`
    `boolean` | `dock(Dockable dockable, DockingPort port, java.lang.String region)` Docks the specified `Dockable` into the supplied `region` of the specified `DockingPort`.
    `boolean` | `dock(Dockable dockable, DockingPort port, java.lang.String region, DragOperation operation)` Docks the specified `Dockable` into the supplied `region` of the specified `DockingPort`.
    `protected boolean` | `dragThresholdElapsed(DragOperation token)`
    `protected DefaultDockingStrategy.DockingResults` | `dropComponent(Dockable dockable, DockingPort target, java.lang.String region, DragOperation token)`
    `static java.lang.String` | `findRegion(java.awt.Component comp)` Returns the docking region within the current split docking layout containing the specified `Component`.
    `protected DefaultDockingStrategy.DockingResults` | `floatComponent(Dockable dockable, DockingPort target, DragOperation token)`
    `protected java.lang.String` | `getCreationRegion(javax.swing.JSplitPane splitPane)`
    `double` | `getDividerProportion(DockingPort port, javax.swing.JSplitPane splitPane)` Returns the desired divider proportion of the specified `JSplitPane` after rendering.
    `protected java.awt.Component` | `getElderComponent(javax.swing.JSplitPane splitPane)`
    `int` | `getInitialDividerLocation(DockingPort port, javax.swing.JSplitPane splitPane)` Returns the initial divider location to be used by the specified `JSplitPane` when it is embedded within the specified `DockingPort`.
    `protected static java.lang.Float` | `getPreferredProportion(java.awt.Component c)`
    `protected java.lang.Float` | `getPreferredProportion(javax.swing.JSplitPane splitPane, java.awt.Component controller)`
    `static Dockable` | `getSibling(Dockable dockable)` Returns the specified `Dockable's` sibling `Dockable` within the current docking layout.
    `static Dockable` | `getSibling(Dockable dockable, java.lang.String region)` Returns the sibling `Dockable` relative to the specified `Dockable's` supplied region in the current docking layout.
    `protected boolean` | `isDockingPossible(Dockable dockable, DockingPort port, java.lang.String region, DragOperation token)`
    `protected boolean` | `isElderTopLeft(javax.swing.JSplitPane splitPane)`
    `protected boolean` | `isFloatable(Dockable dockable, DragOperation token)`
    `static void` | `keepConstantPercentage(boolean cstPercent)`
    `static void` | `setDefaultResizeWeight(double rw)`
    `boolean` | `undock(Dockable dockable)` Undocks the specified `Dockable` from it's parent `DockingPort`.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### PREFERRED_PROPORTION

          public static final java.lang.String PREFERRED_PROPORTION

      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### DefaultDockingStrategy

          public DefaultDockingStrategy()

  - ### Method Detail

    - #### getSibling

          public static Dockable getSibling(Dockable dockable)

      Returns the specified `Dockable's` sibling `Dockable` within the current docking layout. This method checks the parent `DockingPort` of a given `Dockable` to see if it is split equally with another `Dockable`. If so, the immediate sibling `Dockable` is returned. If there are more than two `Dockables` within the split layout, then the closest sibling region is determined and this method dispatches to `getSibling(Dockable dockable, String region)`.

      If the specified `Dockable` is `null`, or there are no siblings available in the docking layout, then this methdo returns a `null` reference. If the specified `Dockable` is not currently docked within a `DockingPort`, then this method returns a `null` reference.

      Parameters:
        `dockable` - the `Dockable` whose sibling is to be returned
      Returns:
        the sibling of the specified `Dockable` within the current docking layout.
      See Also:
        `Dockable.getDockingPort()`, `getSibling(Dockable, String)`

    - #### getSibling

          public static Dockable getSibling(Dockable dockable,
                            java.lang.String region)

      Returns the sibling `Dockable` relative to the specified `Dockable's` supplied region in the current docking layout. If `dockable` is `null` or `region` is either invalid or equal to `CENTER_REGION`, then this method returns a `null` reference.

      If the specified `Dockable` is in a `DockingPort` that equally splits the layout between two `Dockables` in a fashion that matches up with the specified region, then the immediate sibling `Dockable` is returned. Otherwise, a fuzzy search is performed throughout the docking layout for a `Dockable` that "looks like" it is docked to the supplied region of the specified `Dockable` from a visual standpoint.

      For instance, a docking layout may consist of four quadrants Dockable1 (top-left), Dockable2 (top-right), Dockable3 (bottom-left) and Dockable4 (bottom-right). The layout is built by docking Dockable2>/i> to the `EAST_REGION` of Dockable1, Dockable3 to the `SOUTH_REGION` of Dockable1, and Dockable4 to the `SOUTH_REGION` of Dockable2. Within this layout, Dockable1 and Dockable3 are immediate siblings, as are Dockable2 and Dockable4. Thus, requesting sibling NORTH_REGION of Dockable3 will easily yield Dockable1. However, Dockable3 has no immediate `EAST_REGION` sibling. In this case, a fuzzy search through the layout is performed to determine the visual sibling, and this method returns Dockable4. Likewise, this method will return a `null` reference for the `WEST_REGION` sibling of Dockable3}, since there are no `Dockables` in the visual layout to the west of this `Dockable`.

      Parameters:
        `dockable` - the `Dockable` whose sibling is to be returned
        `region` - the region of the specified `Dockable` whose visual sibling is to be returned
      Returns:
        the `Dockable` in the supplied region relative to the specified `Dockable`

    - #### findRegion

          public static java.lang.String findRegion(java.awt.Component comp)

      Returns the docking region within the current split docking layout containing the specified `Component`. If `comp` is `null`, then a `null` reference is returned. If `comp` is not in a split layout, then `CENTER_REGION` is returned.

      This method resolves the associated `Dockable` and `DockingPort` for the specified `Component` and backtracks through the docking layout to find a split layout. If a split layout is found, then the region retured by this method is calculated relative to its sibling in the layout.

      Parameters:
        `comp` - the `Component` whose region is to be returned
      Returns:
        the region of the current split layout containing the specified `Dockable`

    - #### dock

          public boolean dock(Dockable dockable,
                     DockingPort port,
                     java.lang.String region)

      Docks the specified `Dockable` into the supplied `region` of the specified `DockingPort`. This method is meant for programmatic docking, as opposed to realtime, event-based docking operations. As such, it defers processing to `dock(Dockable dockable, DockingPort port, String region, DragOperation token)`, passing a `null` argument for the `DragOperation` parameter. This implies that there is no event-based drag operation currently in progress to control the semantics of the docking operation, only that an attempt should be made to dock the specified `Dockable` into the specified `DockingPort`.

      This method will return `false` if `dockable` or `port` are `null`, or if `region` is not a valid region according to the specified `DockingPort`. If a `Dockable` is currently docked within the specified `DockingPort`, then that `Dockable's` territorial properties are also checked and this method may return `false` if the territory is blocked. Finally, this method will return `false` if the specified `Dockable` is already docked within the supplied region of the specified

      Specified by:
        `dock` in interface `DockingStrategy`
      Parameters:
        `dockable` - the `Dockable` we wish to dock
        `port` - the `DockingPort` into which we wish to dock
        `region` - the region of the specified `DockingPort` into which we wish to dock.
      Returns:
        `true` if the docking operation was successful, `false`. otherwise.
      See Also:
        `dock(Dockable, DockingPort, String, DragOperation)`, `Dockable.getDockingProperties()`, `DockablePropertySet.isTerritoryBlocked(String)`

    - #### dock

          public boolean dock(Dockable dockable,
                     DockingPort port,
                     java.lang.String region,
                     DragOperation operation)

      Docks the specified `Dockable` into the supplied `region` of the specified `DockingPort`. This method is meant for realtime, event-based docking based on an in-progress drag operation. It is not recommended for developers to call this method programmatically, except to pass in a `null` `DragOperation` argument. *

      The `DragOperation` parameter, if present, will control the semantics of the docking operation based upon current mouse position, drag threshold, and a customizable drag context `Map`. For instance, the `DragOperation` may contain information regarding the `Dockable` over which the mouse is currently hovered, whether the user is attempting to drag a `Dockable` outside the bounds of any existing windows (perhaps in an attempt to float the `Dockable`), or whether the current distance offset from the original drag point sufficiently warrants a valid docking operation.

      If the `DragOperation` is `null`, then this method will attempt to programmatically dock the specified `Dockable` into the supplied `region` of the specified `DockingPort` without regard to external event-based criteria. This is in accordance with the behavior specified by `dock(Dockable dockable, DockingPort port, String region)`. This method will return `false` if `dockable` or `port` are `null`, or if `region` is not a valid region according to the specified `DockingPort`. If a `Dockable` is currently docked within the specified `DockingPort`, then that `Dockable's` territorial properties are also checked and this method may return `false` if the territory is blocked. If a `DragOperation` is present, then this method will return `false` if the required drag threshold has not been exceeded. Finally, this method will return `false` if the specified `Dockable` is already docked within the supplied region of the specified

      Specified by:
        `dock` in interface `DockingStrategy`
      Parameters:
        `dockable` - the `Dockable` we wish to dock
        `port` - the `DockingPort` into which we wish to dock
        `region` - the region of the specified `DockingPort` into which we wish to dock.
        `operation` - the `DragOperation` describing the state of the application/mouse at the point in time in which we're attempting to dock.
      Returns:
        `true` if the docking operation was successful, `false`. otherwise.
      See Also:
        `dock(Dockable, DockingPort, String, DragOperation)`, `Dockable.getDockingProperties()`, `DockablePropertySet.isTerritoryBlocked(String)`

    - #### dragThresholdElapsed

          protected boolean dragThresholdElapsed(DragOperation token)

    - #### isDockingPossible

          protected boolean isDockingPossible(Dockable dockable,
                                  DockingPort port,
                                  java.lang.String region,
                                  DragOperation token)

    - #### isFloatable

          protected boolean isFloatable(Dockable dockable,
                            DragOperation token)

    - #### dropComponent

          protected DefaultDockingStrategy.DockingResults dropComponent(Dockable dockable,
                                                            DockingPort target,
                                                            java.lang.String region,
                                                            DragOperation token)

    - #### undock

          public boolean undock(Dockable dockable)

      Undocks the specified `Dockable` from it's parent `DockingPort`. If `dockable` is `null` or is not currently docked within a `DockingPort`, then this method returns `false`.
      Specified by:
        `undock` in interface `DockingStrategy`
      Parameters:
        `dockable` - the `Dockable` to be undocked.
      Returns:
        `true` if the undocking operation was successful, `false` otherwise.
      See Also:
        `dock(Dockable, DockingPort, String)`

    - #### floatComponent

          protected DefaultDockingStrategy.DockingResults floatComponent(Dockable dockable,
                                                             DockingPort target,
                                                             DragOperation token)

    - #### createDockingPort

          public DockingPort createDockingPort(DockingPort base)

      Returns a new `DefaultDockingPort` with characteristics similar to the specified base `DockingPort`. If the base `DockingPort` is a `DefaultDockingPort`, then the returned `DockingPort` will share the base `DockingPort's` border manager and tabbed drag-source flag. The returned `DockingPort's` `isRoot()` method will return `false`.
      Specified by:
        `createDockingPort` in interface `DockingStrategy`
      Parameters:
        `base` - the `DockingPort` off of which to base the returned `DockingPort`
      Returns:
        a new `DefaultDockingPort` with characteristics similar to the specified base `DockingPort`.
      See Also:
        `DefaultDockingPort.getBorderManager()`, `DefaultDockingPort.setBorderManager(BorderManager)`, `DefaultDockingPort.isTabsAsDragSource()`, `DefaultDockingPort.setTabsAsDragSource(boolean)`, `DefaultDockingPort.setRoot(boolean)`

    - #### createDockingPortImpl

          protected DockingPort createDockingPortImpl(DockingPort base)

    - #### createSplitPane

          public javax.swing.JSplitPane createSplitPane(DockingPort base,
                                               java.lang.String region)

      Returns a new `DockingSplitPane` based on the specified `DockingPort`. and region. Creation of the `DockingSplitPane` is deferred to an internal protected method to allow for overriding by subclasses. A client property is set on the returned split pane with the key DockingConstants.REGION to indicate the creation region of the split pane for non-`DockingSplitPanes` returned by overriding subclasses.

      This method determines the "elder" component of the split pane by checking whether the new creation region is in the TOP or LEFT (NORTH_REGION or WEST_REGION). If the creation region, representing where the new `Dockable` will be docked, is not in the top or left, then the elder `Component` in the split pane must be. This information is used to initialize the resize weight of the split pane, setting resize weight to `1` if the elder is in the top or left of the split pane and `0` if not. This gives the elder `Component` in the resulting split pane priority in the layout with resizing the split pane.

      If the creation region is `NORTH_REGION` or `SOUTH_REGION`, the returned split pane is initialized with a `VERTICAL_SPLIT` orientation; otherwise a `HORIZONTAL_SPLIT` orientation is used.

      Before returning, the border is removed from the split pane, its divider size is set to 3, and if possible the border is removed from the split pane divider. This is to avoid an excessive compound border effect for embedded `Components` within the split pane that may have their own borders.

      Specified by:
        `createSplitPane` in interface `DockingStrategy`
      Parameters:
        `base` - the `DockingPort` off of which the returned `JSplitPane` will be based.
        `region` - the region within the base `DockingPort` used to determine the orientation of the returned `JSplitPane`.
      Returns:
        a new `DockingSplitPane` based on the specified `DockingPort`. and region.
      See Also:
        `DockingSplitPane.DockingSplitPane(DockingPort, String)`, `createSplitPaneImpl(DockingPort, String)`, `JSplitPane.setResizeWeight(double)`

    - #### createSplitPaneImpl

          protected javax.swing.JSplitPane createSplitPaneImpl(DockingPort base,
                                                   java.lang.String region)

    - #### getInitialDividerLocation

          public int getInitialDividerLocation(DockingPort port,
                                      javax.swing.JSplitPane splitPane)

      Returns the initial divider location to be used by the specified `JSplitPane` when it is embedded within the specified `DockingPort`. It is assumed that the `JSplitPane` parameter is embedded within the specified `DockingPort`, is validated, visible, and its dimensions are non-zero.

      This method gets the "size" of the specified `DockingPort` based on the orientation of the split pane (width for horizontal split, height for vertical split) minus the `DockingPort's` insets. It then dispatches to `getDividerProportion(DockingPort port, JSplitPane splitPane)` to determine the preferred proportion of the split pane divider. The returned value for this method is the product of the `DockingPort` size and the split proportion.

      If either `port` or `splitPane` parameters are `null`, then this method returns `0`.

      Specified by:
        `getInitialDividerLocation` in interface `DockingStrategy`
      Parameters:
        `port` - the `DockingPort` that contains the specified `JSplitPane`.
        `splitPane` - the `JSplitPane` whose initial divider location is to be determined.
      Returns:
        the desired divider location of the supplied `JSplitPane`.
      See Also:
        `DockingStrategy.getInitialDividerLocation(DockingPort, JSplitPane)`, `getDividerProportion(DockingPort, JSplitPane)`

    - #### getDividerProportion

          public double getDividerProportion(DockingPort port,
                                    javax.swing.JSplitPane splitPane)

      Returns the desired divider proportion of the specified `JSplitPane` after rendering. This method assumes that the `JSplitPane` parameter is, or will be embedded within the specified `DockingPort`. This method does not assume that the `JSplitPane` has been validated and that it's current dimensions are non-zero.

      If either `port` or `splitPane` parameters are `null`, then this method returns the default value of `RegionChecker.DEFAULT_SIBLING_SIZE`. Otherwise the "elder" component within the `JSplitPane` is determined to see if it is contained within a sub-`DockingPort`. If the "elder" `Component` cannot be determined, or it is not contained within a sub-`DockingPort`, then the default value of `RegionChecker.DEFAULT_SIBLING_SIZE` is returned.

      If the "elder" `Component` is successfully resolved inside a sub-`DockingPort`, then a check is done on the sub-port for the client property `DefaultDockingStrategy.PREFERRED_PROPORTION`. If this value is found, then the primitive float version of it is returned.

      Failing these checks, the `Dockable` is resolved for the "elder" `Component` in the specified `JSplitPane` via `DockingManager.getDockable(Component comp)`. If no `Dockable` can be found, then `RegionChecker.DEFAULT_SIBLING_SIZE` is returned.

      Otherwise, the `DockingPortPropertySet` is retrieved from the specified `DockingPort` and its `getRegionChecker()` method is called. `getSiblingSize(Component c, String region)` is invoked on the returned `RegionChecker` passing the "elder" `Component` in the split pane and the creation region resolved for the specified `JSplitPane`. This resolves the preferred sibling size for the elder `Dockable` component. If the elder `Component` is in the top/left of the split pane, then `1F-prefSize` is returned. Otherwise, the preferred sibling size is returned.

      Specified by:
        `getDividerProportion` in interface `DockingStrategy`
      Parameters:
        `port` - the `DockingPort` that contains, or will contain the specified `JSplitPane`.
        `splitPane` - the `JSplitPane` whose initial divider location is to be determined.
      Returns:
        the desired divider proportion of the supplied `JSplitPane`.
      See Also:
        `RegionChecker.DEFAULT_SIBLING_SIZE`, `PREFERRED_PROPORTION`, `DockingManager.getDockable(Component)`, `RegionChecker.getSiblingSize(Component, String)`

    - #### getCreationRegion

          protected java.lang.String getCreationRegion(javax.swing.JSplitPane splitPane)

    - #### isElderTopLeft

          protected boolean isElderTopLeft(javax.swing.JSplitPane splitPane)

    - #### getPreferredProportion

          protected java.lang.Float getPreferredProportion(javax.swing.JSplitPane splitPane,
                                               java.awt.Component controller)

    - #### getElderComponent

          protected java.awt.Component getElderComponent(javax.swing.JSplitPane splitPane)

    - #### getPreferredProportion

          protected static java.lang.Float getPreferredProportion(java.awt.Component c)

    - #### setDefaultResizeWeight

          public static void setDefaultResizeWeight(double rw)

    - #### keepConstantPercentage

          public static void keepConstantPercentage(boolean cstPercent)