Package com.positive.charts.block

Source Code of com.positive.charts.block.BorderArrangement

/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
*
* Project Info:  http://www.jfree.org/jfreechart/index.html
*
* 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.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ----------------------
* BorderArrangement.java
* ----------------------
* (C) Copyright 2004-2008, by Object Refinery Limited.
*
* Original Author:  David Gilbert (for Object Refinery Limited);
* Contributor(s):   -;
*
* Changes:
* --------
* 22-Oct-2004 : Version 1 (DG);
* 08-Feb-2005 : Updated for changes in RectangleConstraint (DG);
* 24-Feb-2005 : Improved arrangeRR() method (DG);
* 03-May-2005 : Implemented Serializable and added equals() method (DG);
* 13-May-2005 : Fixed bugs in the arrange() method (DG);
* 08-Apr-2008 : Fixed bug in arrangeFF() method where width is too small for
*               left and right blocks (DG);
*
*/

package com.positive.charts.block;

import java.io.Serializable;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;

import com.positive.charts.common.RectangleEdge;
import com.positive.charts.data.Range;
import com.positive.charts.data.util.ObjectUtilities;
import com.positive.charts.util.Size2D;

/**
* An arrangement manager that lays out blocks in a similar way to Swing's
* BorderLayout class.
*/
public class BorderArrangement implements Arrangement, Serializable {

  /** For serialization. */
  private static final long serialVersionUID = 506071142274883745L;

  /** The block (if any) at the center of the layout. */
  private Block centerBlock;

  /** The block (if any) at the top of the layout. */
  private Block topBlock;

  /** The block (if any) at the bottom of the layout. */
  private Block bottomBlock;

  /** The block (if any) at the left of the layout. */
  private Block leftBlock;

  /** The block (if any) at the right of the layout. */
  private Block rightBlock;

  /**
   * Creates a new instance.
   */
  public BorderArrangement() {
  }

  /**
   * Adds a block to the arrangement manager at the specified edge.
   *
   * @param block
   *            the block (<code>null</code> permitted).
   * @param key
   *            the edge (an instance of {@link RectangleEdge}) or
   *            <code>null</code> for the center block.
   */
  public void add(final Block block, final Object key) {

    if (key == null) {
      this.centerBlock = block;
    } else {
      final RectangleEdge edge = (RectangleEdge) key;
      if (edge == RectangleEdge.TOP) {
        this.topBlock = block;
      } else if (edge == RectangleEdge.BOTTOM) {
        this.bottomBlock = block;
      } else if (edge == RectangleEdge.LEFT) {
        this.leftBlock = block;
      } else if (edge == RectangleEdge.RIGHT) {
        this.rightBlock = block;
      }
    }
  }

  /**
   * Arranges the items in the specified container, subject to the given
   * constraint.
   *
   * @param container
   *            the container.
   * @param g2
   *            the graphics device.
   * @param constraint
   *            the constraint.
   *
   * @return The block size.
   */
  public Size2D arrange(final BlockContainer container, final GC g2,
      final RectangleConstraint constraint) {
    final RectangleConstraint contentConstraint = container
        .toContentConstraint(constraint);
    Size2D contentSize = null;
    final LengthConstraintType w = contentConstraint
        .getWidthConstraintType();
    final LengthConstraintType h = contentConstraint
        .getHeightConstraintType();
    if (w == LengthConstraintType.NONE) {
      if (h == LengthConstraintType.NONE) {
        contentSize = this.arrangeNN(container, g2);
      } else if (h == LengthConstraintType.FIXED) {
        throw new RuntimeException("Not implemented.");
      } else if (h == LengthConstraintType.RANGE) {
        throw new RuntimeException("Not implemented.");
      }
    } else if (w == LengthConstraintType.FIXED) {
      if (h == LengthConstraintType.NONE) {
        contentSize = this.arrangeFN(container, g2, constraint
            .getWidth());
      } else if (h == LengthConstraintType.FIXED) {
        contentSize = this.arrangeFF(container, g2, constraint);
      } else if (h == LengthConstraintType.RANGE) {
        contentSize = this.arrangeFR(container, g2, constraint);
      }
    } else if (w == LengthConstraintType.RANGE) {
      if (h == LengthConstraintType.NONE) {
        throw new RuntimeException("Not implemented.");
      } else if (h == LengthConstraintType.FIXED) {
        throw new RuntimeException("Not implemented.");
      } else if (h == LengthConstraintType.RANGE) {
        contentSize = this.arrangeRR(container, constraint
            .getWidthRange(), constraint.getHeightRange(), g2);
      }
    }
    return new Size2D(
        container.calculateTotalWidth(contentSize.getWidth()),
        container.calculateTotalHeight(contentSize.getHeight()));
  }

  /**
   * Arranges the items within a container.
   *
   * @param container
   *            the container.
   * @param constraint
   *            the constraint.
   * @param g2
   *            the graphics device.
   *
   * @return The container size after the arrangement.
   */
  protected Size2D arrangeFF(final BlockContainer container, final GC g2,
      final RectangleConstraint constraint) {
    final double[] w = new double[5];
    final double[] h = new double[5];
    w[0] = constraint.getWidth();
    if (this.topBlock != null) {
      final RectangleConstraint c1 = new RectangleConstraint(w[0], null,
          LengthConstraintType.FIXED, 0.0, new Range(0.0, constraint
              .getHeight()), LengthConstraintType.RANGE);
      final Size2D size = this.topBlock.arrange(g2, c1);
      h[0] = size.height;
    }
    w[1] = w[0];
    if (this.bottomBlock != null) {
      final RectangleConstraint c2 = new RectangleConstraint(w[0], null,
          LengthConstraintType.FIXED, 0.0, new Range(0.0, constraint
              .getHeight()
              - h[0]), LengthConstraintType.RANGE);
      final Size2D size = this.bottomBlock.arrange(g2, c2);
      h[1] = size.height;
    }
    h[2] = constraint.getHeight() - h[1] - h[0];
    if (this.leftBlock != null) {
      final RectangleConstraint c3 = new RectangleConstraint(0.0,
          new Range(0.0, constraint.getWidth()),
          LengthConstraintType.RANGE, h[2], null,
          LengthConstraintType.FIXED);
      final Size2D size = this.leftBlock.arrange(g2, c3);
      w[2] = size.width;
    }
    h[3] = h[2];
    if (this.rightBlock != null) {
      final RectangleConstraint c4 = new RectangleConstraint(
          0.0,
          new Range(0.0, Math.max(constraint.getWidth() - w[2], 0.0)),
          LengthConstraintType.RANGE, h[2], null,
          LengthConstraintType.FIXED);
      final Size2D size = this.rightBlock.arrange(g2, c4);
      w[3] = size.width;
    }
    h[4] = h[2];
    w[4] = constraint.getWidth() - w[3] - w[2];
    final RectangleConstraint c5 = new RectangleConstraint(w[4], h[4]);
    if (this.centerBlock != null) {
      this.centerBlock.arrange(g2, c5);
    }

    if (this.topBlock != null) {
      this.topBlock.setBounds(RectUtils.doubleRect(0.0, 0.0, w[0], h[0]));
    }
    if (this.bottomBlock != null) {
      this.bottomBlock.setBounds(RectUtils.doubleRect(0.0, h[0] + h[2],
          w[1], h[1]));
    }
    if (this.leftBlock != null) {
      this.leftBlock.setBounds(RectUtils
          .doubleRect(0.0, h[0], w[2], h[2]));
    }
    if (this.rightBlock != null) {
      this.rightBlock.setBounds(RectUtils.doubleRect(w[2] + w[4], h[0],
          w[3], h[3]));
    }
    if (this.centerBlock != null) {
      this.centerBlock.setBounds(RectUtils.doubleRect(w[2], h[0], w[4],
          h[4]));
    }
    return new Size2D(constraint.getWidth(), constraint.getHeight());
  }

  /**
   * Arranges the container width a fixed width and no constraint on the
   * height.
   *
   * @param container
   *            the container.
   * @param g2
   *            the graphics device.
   * @param width
   *            the fixed width.
   *
   * @return The container size after arranging the contents.
   */
  protected Size2D arrangeFN(final BlockContainer container, final GC g2,
      final double width) {
    final double[] w = new double[5];
    final double[] h = new double[5];
    final RectangleConstraint c1 = new RectangleConstraint(width, null,
        LengthConstraintType.FIXED, 0.0, null,
        LengthConstraintType.NONE);
    if (this.topBlock != null) {
      final Size2D size = this.topBlock.arrange(g2, c1);
      w[0] = size.width;
      h[0] = size.height;
    }
    if (this.bottomBlock != null) {
      final Size2D size = this.bottomBlock.arrange(g2, c1);
      w[1] = size.width;
      h[1] = size.height;
    }
    final RectangleConstraint c2 = new RectangleConstraint(0.0, new Range(
        0.0, width), LengthConstraintType.RANGE, 0.0, null,
        LengthConstraintType.NONE);
    if (this.leftBlock != null) {
      final Size2D size = this.leftBlock.arrange(g2, c2);
      w[2] = size.width;
      h[2] = size.height;
    }
    if (this.rightBlock != null) {
      final double maxW = Math.max(width - w[2], 0.0);
      final RectangleConstraint c3 = new RectangleConstraint(0.0,
          new Range(Math.min(w[2], maxW), maxW),
          LengthConstraintType.RANGE, 0.0, null,
          LengthConstraintType.NONE);
      final Size2D size = this.rightBlock.arrange(g2, c3);
      w[3] = size.width;
      h[3] = size.height;
    }

    h[2] = Math.max(h[2], h[3]);
    h[3] = h[2];

    if (this.centerBlock != null) {
      final RectangleConstraint c4 = new RectangleConstraint(width - w[2]
          - w[3], null, LengthConstraintType.FIXED, 0.0, null,
          LengthConstraintType.NONE);
      final Size2D size = this.centerBlock.arrange(g2, c4);
      w[4] = size.width;
      h[4] = size.height;
    }
    final double height = h[0] + h[1]
        + Math.max(h[2], Math.max(h[3], h[4]));
    return this.arrange(container, g2, new RectangleConstraint(width,
        height));
  }

  /**
   * Performs an arrangement with a fixed width and a range for the height.
   *
   * @param container
   *            the container.
   * @param g2
   *            the graphics device.
   * @param constraint
   *            the constraint.
   *
   * @return The container size after the arrangement.
   */
  protected Size2D arrangeFR(final BlockContainer container, final GC g2,
      final RectangleConstraint constraint) {
    final Size2D size1 = this.arrangeFN(container, g2, constraint
        .getWidth());
    if (constraint.getHeightRange().contains(size1.getHeight())) {
      return size1;
    } else {
      final double h = constraint.getHeightRange().constrain(
          size1.getHeight());
      final RectangleConstraint c2 = constraint.toFixedHeight(h);
      return this.arrange(container, g2, c2);
    }
  }

  /**
   * Performs an arrangement without constraints.
   *
   * @param container
   *            the container.
   * @param g2
   *            the graphics device.
   *
   * @return The container size after the arrangement.
   */
  protected Size2D arrangeNN(final BlockContainer container, final GC g2) {
    final double[] w = new double[5];
    final double[] h = new double[5];
    if (this.topBlock != null) {
      final Size2D size = this.topBlock.arrange(g2,
          RectangleConstraint.NONE);
      w[0] = size.width;
      h[0] = size.height;
    }
    if (this.bottomBlock != null) {
      final Size2D size = this.bottomBlock.arrange(g2,
          RectangleConstraint.NONE);
      w[1] = size.width;
      h[1] = size.height;
    }
    if (this.leftBlock != null) {
      final Size2D size = this.leftBlock.arrange(g2,
          RectangleConstraint.NONE);
      w[2] = size.width;
      h[2] = size.height;
    }
    if (this.rightBlock != null) {
      final Size2D size = this.rightBlock.arrange(g2,
          RectangleConstraint.NONE);
      w[3] = size.width;
      h[3] = size.height;
    }

    h[2] = Math.max(h[2], h[3]);
    h[3] = h[2];

    if (this.centerBlock != null) {
      final Size2D size = this.centerBlock.arrange(g2,
          RectangleConstraint.NONE);
      w[4] = size.width;
      h[4] = size.height;
    }
    final double width = Math.max(w[0], Math.max(w[1], w[2] + w[4] + w[3]));
    final double centerHeight = Math.max(h[2], Math.max(h[3], h[4]));
    final double height = h[0] + h[1] + centerHeight;
    if (this.topBlock != null) {
      this.topBlock
          .setBounds(new Rectangle(0, 0, (int) width, (int) h[0]));
    }
    if (this.bottomBlock != null) {
      this.bottomBlock.setBounds(RectUtils.doubleRect(0.0, height - h[1],
          width, h[1]));
    }
    if (this.leftBlock != null) {
      this.leftBlock.setBounds(RectUtils.doubleRect(0.0, h[0], w[2],
          centerHeight));
    }
    if (this.rightBlock != null) {
      this.rightBlock.setBounds(RectUtils.doubleRect(width - w[3], h[0],
          w[3], centerHeight));
    }

    if (this.centerBlock != null) {
      this.centerBlock.setBounds(RectUtils.doubleRect(w[2], h[0], width
          - w[2] - w[3], centerHeight));
    }
    return new Size2D(width, height);
  }

  /**
   * Performs an arrangement with range constraints on both the vertical and
   * horizontal sides.
   *
   * @param container
   *            the container.
   * @param widthRange
   *            the allowable range for the container width.
   * @param heightRange
   *            the allowable range for the container height.
   * @param g2
   *            the graphics device.
   *
   * @return The container size.
   */
  protected Size2D arrangeRR(final BlockContainer container,
      final Range widthRange, final Range heightRange, final GC g2) {
    final double[] w = new double[5];
    final double[] h = new double[5];
    if (this.topBlock != null) {
      final RectangleConstraint c1 = new RectangleConstraint(widthRange,
          heightRange);
      final Size2D size = this.topBlock.arrange(g2, c1);
      w[0] = size.width;
      h[0] = size.height;
    }
    if (this.bottomBlock != null) {
      final Range heightRange2 = Range.shift(heightRange, -h[0], false);
      final RectangleConstraint c2 = new RectangleConstraint(widthRange,
          heightRange2);
      final Size2D size = this.bottomBlock.arrange(g2, c2);
      w[1] = size.width;
      h[1] = size.height;
    }
    final Range heightRange3 = Range.shift(heightRange, -(h[0] + h[1]));
    if (this.leftBlock != null) {
      final RectangleConstraint c3 = new RectangleConstraint(widthRange,
          heightRange3);
      final Size2D size = this.leftBlock.arrange(g2, c3);
      w[2] = size.width;
      h[2] = size.height;
    }
    final Range widthRange2 = Range.shift(widthRange, -w[2], false);
    if (this.rightBlock != null) {
      final RectangleConstraint c4 = new RectangleConstraint(widthRange2,
          heightRange3);
      final Size2D size = this.rightBlock.arrange(g2, c4);
      w[3] = size.width;
      h[3] = size.height;
    }

    h[2] = Math.max(h[2], h[3]);
    h[3] = h[2];
    final Range widthRange3 = Range
        .shift(widthRange, -(w[2] + w[3]), false);
    if (this.centerBlock != null) {
      final RectangleConstraint c5 = new RectangleConstraint(widthRange3,
          heightRange3);
      final Size2D size = this.centerBlock.arrange(g2, c5);
      w[4] = size.width;
      h[4] = size.height;
    }
    final double width = Math.max(w[0], Math.max(w[1], w[2] + w[4] + w[3]));
    final double height = h[0] + h[1]
        + Math.max(h[2], Math.max(h[3], h[4]));
    if (this.topBlock != null) {
      this.topBlock
          .setBounds(RectUtils.doubleRect(0.0, 0.0, width, h[0]));
    }
    if (this.bottomBlock != null) {
      this.bottomBlock.setBounds(RectUtils.doubleRect(0.0, height - h[1],
          width, h[1]));
    }
    if (this.leftBlock != null) {
      this.leftBlock.setBounds(RectUtils
          .doubleRect(0.0, h[0], w[2], h[2]));
    }
    if (this.rightBlock != null) {
      this.rightBlock.setBounds(RectUtils.doubleRect(width - w[3], h[0],
          w[3], h[3]));
    }

    if (this.centerBlock != null) {
      this.centerBlock.setBounds(RectUtils.doubleRect(w[2], h[0], width
          - w[2] - w[3], height - h[0] - h[1]));
    }
    return new Size2D(width, height);
  }

  /**
   * Clears the layout.
   */
  public void clear() {
    this.centerBlock = null;
    this.topBlock = null;
    this.bottomBlock = null;
    this.leftBlock = null;
    this.rightBlock = null;
  }

  /**
   * Tests this arrangement for equality with an arbitrary object.
   *
   * @param obj
   *            the object (<code>null</code> permitted).
   *
   * @return A boolean.
   */
  public boolean equals(final Object obj) {
    if (obj == this) {
      return true;
    }
    if (!(obj instanceof BorderArrangement)) {
      return false;
    }
    final BorderArrangement that = (BorderArrangement) obj;
    if (!ObjectUtilities.equal(this.topBlock, that.topBlock)) {
      return false;
    }
    if (!ObjectUtilities.equal(this.bottomBlock, that.bottomBlock)) {
      return false;
    }
    if (!ObjectUtilities.equal(this.leftBlock, that.leftBlock)) {
      return false;
    }
    if (!ObjectUtilities.equal(this.rightBlock, that.rightBlock)) {
      return false;
    }
    if (!ObjectUtilities.equal(this.centerBlock, that.centerBlock)) {
      return false;
    }
    return true;
  }
}
TOP

Related Classes of com.positive.charts.block.BorderArrangement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.