示例#1
0
 private Dimension minimumNodeSize(Node root) {
   if (root instanceof Leaf) {
     Component child = childForNode(root);
     return (child != null) ? child.getMinimumSize() : new Dimension(0, 0);
   } else if (root instanceof Divider) {
     int dividerSize = getDividerSize();
     return new Dimension(dividerSize, dividerSize);
   } else {
     Split split = (Split) root;
     List<Node> splitChildren = split.getChildren();
     int width = 0;
     int height = 0;
     if (split.isRowLayout()) {
       for (Node splitChild : splitChildren) {
         Dimension size = minimumNodeSize(splitChild);
         width += size.width;
         height = Math.max(height, size.height);
       }
     } else {
       for (Node splitChild : splitChildren) {
         Dimension size = minimumNodeSize(splitChild);
         width = Math.max(width, size.width);
         height += size.height;
       }
     }
     return new Dimension(width, height);
   }
 }
示例#2
0
 private Dimension preferredNodeSize(Node root) {
   if (root instanceof Leaf) return preferredComponentSize(root);
   else if (root instanceof Divider) {
     int dividerSize = getDividerSize();
     return new Dimension(dividerSize, dividerSize);
   } else {
     Split split = (Split) root;
     List<Node> splitChildren = split.getChildren();
     int width = 0;
     int height = 0;
     if (split.isRowLayout()) {
       for (Node splitChild : splitChildren) {
         Dimension size = preferredNodeSize(splitChild);
         width += size.width;
         height = Math.max(height, size.height);
       }
     } else {
       for (Node splitChild : splitChildren) {
         Dimension size = preferredNodeSize(splitChild);
         width = Math.max(width, size.width);
         height += size.height;
       }
     }
     return new Dimension(width, height);
   }
 }
示例#3
0
 private void minimizeSplitBounds(Split split, Rectangle bounds) {
   Rectangle splitBounds = new Rectangle(bounds.x, bounds.y, 0, 0);
   List<Node> splitChildren = split.getChildren();
   Node lastChild = splitChildren.get(splitChildren.size() - 1);
   Rectangle lastChildBounds = lastChild.getBounds();
   if (split.isRowLayout()) {
     int lastChildMaxX = lastChildBounds.x + lastChildBounds.width;
     splitBounds.add(lastChildMaxX, bounds.y + bounds.height);
   } else {
     int lastChildMaxY = lastChildBounds.y + lastChildBounds.height;
     splitBounds.add(bounds.x + bounds.width, lastChildMaxY);
   }
   split.setBounds(splitBounds);
 }
示例#4
0
 /* Second pass of the layout algorithm: branch to layoutGrow/Shrink
  * as needed.
  */
 private void layout2(Node root, Rectangle bounds) {
   if (root instanceof Leaf) {
     Component child = childForNode(root);
     if (child != null) {
       child.setBounds(bounds);
     }
     root.setBounds(bounds);
   } else if (root instanceof Divider) {
     root.setBounds(bounds);
   } else if (root instanceof Split) {
     Split split = (Split) root;
     boolean grow =
         split.isRowLayout()
             ? (split.getBounds().width <= bounds.width)
             : (split.getBounds().height <= bounds.height);
     if (grow) {
       layoutGrow(split, bounds);
       root.setBounds(bounds);
     } else {
       layoutShrink(split, bounds);
       // split.setBounds() called in layoutShrink()
     }
   }
 }
示例#5
0
  /* First pass of the layout algorithm.
   *
   * If the Dividers are "floating" then set the bounds of each
   * node to accomodate the preferred size of all of the
   * Leaf's java.awt.Components.  Otherwise, just set the bounds
   * of each Leaf/Split node so that it's to the left of (for
   * Split.isRowLayout() Split children) or directly above
   * the Divider that follows.
   *
   * This pass sets the bounds of each Node in the layout model.  It
   * does not resize any of the parent Container's
   * (java.awt.Component) children.  That's done in the second pass,
   * see layoutGrow() and layoutShrink().
   */
  private void layout1(Node root, Rectangle bounds) {
    if (root instanceof Leaf) {
      root.setBounds(bounds);
    } else if (root instanceof Split) {
      Split split = (Split) root;
      Iterator<Node> splitChildren = split.getChildren().iterator();
      Rectangle childBounds = null;
      int dividerSize = getDividerSize();

      /* Layout the Split's child Nodes' along the X axis.  The bounds
       * of each child will have the same y coordinate and height as the
       * layout1() bounds argument.
       *
       * Note: the column layout code - that's the "else" clause below
       * this if, is identical to the X axis (rowLayout) code below.
       */
      if (split.isRowLayout()) {
        double x = bounds.getX();
        while (splitChildren.hasNext()) {
          Node splitChild = splitChildren.next();
          Divider dividerChild =
              (splitChildren.hasNext()) ? (Divider) (splitChildren.next()) : null;

          double childWidth = 0.0;
          if (getFloatingDividers()) {
            childWidth = preferredNodeSize(splitChild).getWidth();
          } else {
            if (dividerChild != null) {
              childWidth = dividerChild.getBounds().getX() - x;
            } else {
              childWidth = split.getBounds().getMaxX() - x;
            }
          }
          childBounds = boundsWithXandWidth(bounds, x, childWidth);
          layout1(splitChild, childBounds);

          if (getFloatingDividers() && (dividerChild != null)) {
            double dividerX = childBounds.getMaxX();
            Rectangle dividerBounds = boundsWithXandWidth(bounds, dividerX, dividerSize);
            dividerChild.setBounds(dividerBounds);
          }
          if (dividerChild != null) {
            x = dividerChild.getBounds().getMaxX();
          }
        }
      }

      /* Layout the Split's child Nodes' along the Y axis.  The bounds
       * of each child will have the same x coordinate and width as the
       * layout1() bounds argument.  The algorithm is identical to what's
       * explained above, for the X axis case.
       */
      else {
        double y = bounds.getY();
        while (splitChildren.hasNext()) {
          Node splitChild = splitChildren.next();
          Divider dividerChild =
              (splitChildren.hasNext()) ? (Divider) (splitChildren.next()) : null;

          double childHeight = 0.0;
          if (getFloatingDividers()) {
            childHeight = preferredNodeSize(splitChild).getHeight();
          } else {
            if (dividerChild != null) {
              childHeight = dividerChild.getBounds().getY() - y;
            } else {
              childHeight = split.getBounds().getMaxY() - y;
            }
          }
          childBounds = boundsWithYandHeight(bounds, y, childHeight);
          layout1(splitChild, childBounds);

          if (getFloatingDividers() && (dividerChild != null)) {
            double dividerY = childBounds.getMaxY();
            Rectangle dividerBounds = boundsWithYandHeight(bounds, dividerY, dividerSize);
            dividerChild.setBounds(dividerBounds);
          }
          if (dividerChild != null) {
            y = dividerChild.getBounds().getMaxY();
          }
        }
      }
      /* The bounds of the Split node root are set to be just
       * big enough to contain all of its children, but only
       * along the axis it's allocating space on.  That's
       * X for rows, Y for columns.  The second pass of the
       * layout algorithm - see layoutShrink()/layoutGrow()
       * allocates extra space.
       */
      minimizeSplitBounds(split, bounds);
    }
  }
示例#6
0
  private void layoutGrow(Split split, Rectangle bounds) {
    Rectangle splitBounds = split.getBounds();
    ListIterator<Node> splitChildren = split.getChildren().listIterator();
    Node lastWeightedChild = split.lastWeightedChild();

    /* Layout the Split's child Nodes' along the X axis.  The bounds
     * of each child will have the same y coordinate and height as the
     * layoutGrow() bounds argument.  Extra width is allocated to the
     * to each child with a non-zero weight:
     *     newWidth = currentWidth + (extraWidth * splitChild.getWeight())
     * Any extraWidth "left over" (that's availableWidth in the loop
     * below) is given to the last child.  Note that Dividers always
     * have a weight of zero, and they're never the last child.
     */
    if (split.isRowLayout()) {
      double x = bounds.getX();
      double extraWidth = bounds.getWidth() - splitBounds.getWidth();
      double availableWidth = extraWidth;

      while (splitChildren.hasNext()) {
        Node splitChild = splitChildren.next();
        Rectangle splitChildBounds = splitChild.getBounds();
        double splitChildWeight = splitChild.getWeight();

        if (!splitChildren.hasNext()) {
          double newWidth = bounds.getMaxX() - x;
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth);
          layout2(splitChild, newSplitChildBounds);
        } else if ((availableWidth > 0.0) && (splitChildWeight > 0.0)) {
          double allocatedWidth =
              (splitChild.equals(lastWeightedChild))
                  ? availableWidth
                  : Math.rint(splitChildWeight * extraWidth);
          double newWidth = splitChildBounds.getWidth() + allocatedWidth;
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth);
          layout2(splitChild, newSplitChildBounds);
          availableWidth -= allocatedWidth;
        } else {
          double existingWidth = splitChildBounds.getWidth();
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, existingWidth);
          layout2(splitChild, newSplitChildBounds);
        }
        x = splitChild.getBounds().getMaxX();
      }
    }

    /* Layout the Split's child Nodes' along the Y axis.  The bounds
     * of each child will have the same x coordinate and width as the
     * layoutGrow() bounds argument.  Extra height is allocated to the
     * to each child with a non-zero weight:
     *     newHeight = currentHeight + (extraHeight * splitChild.getWeight())
     * Any extraHeight "left over" (that's availableHeight in the loop
     * below) is given to the last child.  Note that Dividers always
     * have a weight of zero, and they're never the last child.
     */
    else {
      double y = bounds.getY();
      double extraHeight = bounds.getMaxY() - splitBounds.getHeight();
      double availableHeight = extraHeight;

      while (splitChildren.hasNext()) {
        Node splitChild = splitChildren.next();
        Rectangle splitChildBounds = splitChild.getBounds();
        double splitChildWeight = splitChild.getWeight();

        if (!splitChildren.hasNext()) {
          double newHeight = bounds.getMaxY() - y;
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight);
          layout2(splitChild, newSplitChildBounds);
        } else if ((availableHeight > 0.0) && (splitChildWeight > 0.0)) {
          double allocatedHeight =
              (splitChild.equals(lastWeightedChild))
                  ? availableHeight
                  : Math.rint(splitChildWeight * extraHeight);
          double newHeight = splitChildBounds.getHeight() + allocatedHeight;
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight);
          layout2(splitChild, newSplitChildBounds);
          availableHeight -= allocatedHeight;
        } else {
          double existingHeight = splitChildBounds.getHeight();
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, existingHeight);
          layout2(splitChild, newSplitChildBounds);
        }
        y = splitChild.getBounds().getMaxY();
      }
    }
  }
示例#7
0
  private void layoutShrink(Split split, Rectangle bounds) {
    Rectangle splitBounds = split.getBounds();
    ListIterator<Node> splitChildren = split.getChildren().listIterator();

    if (split.isRowLayout()) {
      int totalWidth = 0; // sum of the children's widths
      int minWeightedWidth = 0; // sum of the weighted childrens' min widths
      int totalWeightedWidth = 0; // sum of the weighted childrens' widths
      for (Node splitChild : split.getChildren()) {
        int nodeWidth = splitChild.getBounds().width;
        int nodeMinWidth = Math.min(nodeWidth, minimumNodeSize(splitChild).width);
        totalWidth += nodeWidth;
        if (splitChild.getWeight() > 0.0) {
          minWeightedWidth += nodeMinWidth;
          totalWeightedWidth += nodeWidth;
        }
      }

      double x = bounds.getX();
      double extraWidth = splitBounds.getWidth() - bounds.getWidth();
      double availableWidth = extraWidth;
      boolean onlyShrinkWeightedComponents = (totalWeightedWidth - minWeightedWidth) > extraWidth;

      while (splitChildren.hasNext()) {
        Node splitChild = splitChildren.next();
        Rectangle splitChildBounds = splitChild.getBounds();
        double minSplitChildWidth = minimumNodeSize(splitChild).getWidth();
        double splitChildWeight =
            (onlyShrinkWeightedComponents)
                ? splitChild.getWeight()
                : (splitChildBounds.getWidth() / totalWidth);

        if (!splitChildren.hasNext()) {
          double newWidth = Math.max(minSplitChildWidth, bounds.getMaxX() - x);
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth);
          layout2(splitChild, newSplitChildBounds);
        } else if ((availableWidth > 0.0) && (splitChildWeight > 0.0)) {
          double allocatedWidth = Math.rint(splitChildWeight * extraWidth);
          double oldWidth = splitChildBounds.getWidth();
          double newWidth = Math.max(minSplitChildWidth, oldWidth - allocatedWidth);
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, newWidth);
          layout2(splitChild, newSplitChildBounds);
          availableWidth -= (oldWidth - splitChild.getBounds().getWidth());
        } else {
          double existingWidth = splitChildBounds.getWidth();
          Rectangle newSplitChildBounds = boundsWithXandWidth(bounds, x, existingWidth);
          layout2(splitChild, newSplitChildBounds);
        }
        x = splitChild.getBounds().getMaxX();
      }
    } else {
      int totalHeight = 0; // sum of the children's heights
      int minWeightedHeight = 0; // sum of the weighted childrens' min heights
      int totalWeightedHeight = 0; // sum of the weighted childrens' heights
      for (Node splitChild : split.getChildren()) {
        int nodeHeight = splitChild.getBounds().height;
        int nodeMinHeight = Math.min(nodeHeight, minimumNodeSize(splitChild).height);
        totalHeight += nodeHeight;
        if (splitChild.getWeight() > 0.0) {
          minWeightedHeight += nodeMinHeight;
          totalWeightedHeight += nodeHeight;
        }
      }

      double y = bounds.getY();
      double extraHeight = splitBounds.getHeight() - bounds.getHeight();
      double availableHeight = extraHeight;
      boolean onlyShrinkWeightedComponents =
          (totalWeightedHeight - minWeightedHeight) > extraHeight;

      while (splitChildren.hasNext()) {
        Node splitChild = splitChildren.next();
        Rectangle splitChildBounds = splitChild.getBounds();
        double minSplitChildHeight = minimumNodeSize(splitChild).getHeight();
        double splitChildWeight =
            (onlyShrinkWeightedComponents)
                ? splitChild.getWeight()
                : (splitChildBounds.getHeight() / totalHeight);

        if (!splitChildren.hasNext()) {
          double oldHeight = splitChildBounds.getHeight();
          double newHeight = Math.max(minSplitChildHeight, bounds.getMaxY() - y);
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight);
          layout2(splitChild, newSplitChildBounds);
          availableHeight -= (oldHeight - splitChild.getBounds().getHeight());
        } else if ((availableHeight > 0.0) && (splitChildWeight > 0.0)) {
          double allocatedHeight = Math.rint(splitChildWeight * extraHeight);
          double oldHeight = splitChildBounds.getHeight();
          double newHeight = Math.max(minSplitChildHeight, oldHeight - allocatedHeight);
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, newHeight);
          layout2(splitChild, newSplitChildBounds);
          availableHeight -= (oldHeight - splitChild.getBounds().getHeight());
        } else {
          double existingHeight = splitChildBounds.getHeight();
          Rectangle newSplitChildBounds = boundsWithYandHeight(bounds, y, existingHeight);
          layout2(splitChild, newSplitChildBounds);
        }
        y = splitChild.getBounds().getMaxY();
      }
    }

    /* The bounds of the Split node root are set to be
     * big enough to contain all of its children. Since
     * Leaf children can't be reduced below their
     * (corresponding java.awt.Component) minimum sizes,
     * the size of the Split's bounds maybe be larger than
     * the bounds we were asked to fit within.
     */
    minimizeSplitBounds(split, bounds);
  }
示例#8
0
 /**
  * Convenience method, returns true if the Divider's parent is a Split row (a Split with
  * isRowLayout() true), false otherwise. In other words if this Divider's major axis is
  * vertical, return true.
  *
  * @return true if this Divider is part of a Split row.
  */
 public final boolean isVertical() {
   Split parent = parent_get();
   return (parent != null) ? parent.isRowLayout() : false;
 }