Package ch.sahits.game.graphic.layout

Source Code of ch.sahits.game.graphic.layout.SahitsMaximalGridLayout

package ch.sahits.game.graphic.layout;

import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Rectangle;
import java.util.Hashtable;

import ch.sahits.game.graphic.display.ISahitsComponent;
import ch.sahits.game.graphic.display.ISahitsContainer;
import ch.sahits.game.graphic.display.ISahitsLayoutConstraint;
import ch.sahits.game.graphic.display.ISahitsLayoutManager;
/**
* Grid layout that sizes the cells according the the biggest
* sized ISahitsComponent in the same row/column. If the ISahitsComponent does
* not fill the whole size of the cell it is by default positioned in the
* center.
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on May 27, 2011
*
*/
public class SahitsMaximalGridLayout implements ISahitsLayoutManager {
  private final int nbCols;
  private final int nbRows;
  private final int[] maxWidth;
  private final int[] maxHight;
  private final int gap;
  private final ECellPosition position;
 
  private final Hashtable<ISahitsComponent, MaximalGridLayoutConstraints> compTable;
 
  /**
   * Initialize the layout with the number of columns and rows
   * @param cols
   * @param rows
   */
  public SahitsMaximalGridLayout(int cols, int rows) {
    this(cols, rows, 0, ECellPosition.TOP_LEFT);
  }
  /**
   * Initialize the layout with the number of columns and rows and the gaping between them as
   * well as the positioning of the whole if there is any space.
   * @param cols
   * @param rows
   * @param gapWidth
   * @param positioning
   */
  public SahitsMaximalGridLayout(int cols, int rows,int gapWidth, ECellPosition positioning) {
    super();
    this.nbCols = cols;
    this.nbRows = rows;
    gap=gapWidth;
    position=positioning;
    maxWidth = new int[nbCols];
    maxHight = new int[nbRows];
    resetSizeCache();
    compTable = new Hashtable<ISahitsComponent, MaximalGridLayoutConstraints>();
  }
  /**
   * Default constructor initializing a grid of size 1x1.
   */
  public SahitsMaximalGridLayout(){
    this(1,1);
  }
 
  private void resetSizeCache(){
    for (int i = 0; i < maxWidth.length; i++) {
      maxWidth[i]=0;
    }
    for (int i = 0; i < maxWidth.length; i++) {
      maxWidth[i]=0;
    }
  }
  /**
   * Compute the width of the widest ISahitsComponent in the specified
   * column.
   * @param column number of the column (starting with index 1)
   * @param parent parent ISahitsContainer
   * @return
   */
  final int computeWidth(int column, ISahitsContainer parent){
    if (column>nbCols){
      throw new IllegalArgumentException("Layout has only "+nbCols+" columns");
    }
    if (this.maxWidth[column-1]>0){
      return this.maxWidth[column-1];
    }
        int nComps = parent.getComponentCount();
        Dimension d = null;
        int maxWidth=0;
        for (int i = 0; i < nComps; i++) {
          ISahitsComponent c = parent.get(i);
            if ( computeColumnIndex(i)==column) {
              d = c.getPreferredSize();
              if (d.width>maxWidth){
                maxWidth=d.width;
              }
            }
        }
        this.maxWidth[column-1] = maxWidth;
     return maxWidth;
  }
  /**
   * Compute the height of the highest ISahitsComponent in the specified
   * row.
   * @param row number of the row (starting with index 1)
   * @param parent parent ISahitsContainer
   * @return
   */
  final int computeHeight(int row, ISahitsContainer parent){
    if (row>nbRows){
      throw new IllegalArgumentException("Layout has only "+nbCols+" columns");
    }
    if (this.maxHight[row-1]>0){
      return this.maxHight[row-1];
    }
        int nComps = parent.getComponentCount();
        Dimension d = null;
        int maxHeigth=0;
        for (int i = 0; i < nComps; i++) {
          ISahitsComponent c = parent.get(i);
            if (computeRowIndex(i)==row) {
              d = c.getPreferredSize();
              if (d.height>maxHeigth){
                maxHeigth=d.height;
              }
            }
        }
        this.maxHight[row-1] = maxHeigth;
     return maxHeigth;
  }
  /**
   * Computing the prefered size by adding the sizes of the columns and rows together with the insets
   */
  public Dimension preferredLayoutSize(ISahitsContainer parent) {
        Dimension dim = new Dimension(0, 0);

        //Always add the ISahitsContainer's insets!
        Insets insets = parent.getInsets();
        int preferredWidth = 0;
        int preferredHeight = 0;
        for (int i=1;i<=nbCols;i++){
          preferredWidth+=computeWidth(i, parent);
        }
        for (int i=1;i<=nbRows;i++){
          preferredHeight+=computeHeight(i, parent);
        }
        dim.width = preferredWidth
                    + insets.left + insets.right;
        dim.height = preferredHeight
                     + insets.top + insets.bottom;


        return dim;
  }
  @Override
  public void layoutContainer(ISahitsContainer parent) {
    final Rectangle bounds = parent.getBounds();
        Insets insets = parent.getInsets();
        int nComps = parent.getComponentCount();
        final double widthScale;
        int totalWidth;
        if (checkWidth(parent)){
          widthScale=1;
          totalWidth = addUpColumnWidth(parent);
        } else {
          widthScale = computeWidthScale(parent);
          totalWidth = parent.getWidth();
        }
        final double heightScale;
        int totalHeight;
        if (checkHeight(parent)){
          heightScale=1;
          totalHeight = addUpRowHeight(parent);
        } else {
          heightScale = computeHeightScale(parent);
          totalHeight = parent.getHeight();
        }
        int w = parent.getWidth();
        int h = parent.getHeight();
        int globalXPadding = computeXPadding(w, totalWidth, new MaximalGridLayoutConstraints(position));
        globalXPadding += bounds.x;
       int globalYPadding = computeYPadding(h, totalHeight, new MaximalGridLayoutConstraints(position));
       globalYPadding += bounds.y;
       for (int i = 0 ; i < nComps ; i++) {
            ISahitsComponent c = parent.get(i);
            final int columnIndex = computeColumnIndex(i);
            final int rowIndex = computeRowIndex(i);
            int xColumn = (int) Math.rint(getColumnStart(columnIndex,parent)*widthScale);
            xColumn += (columnIndex-1)*gap;
            int yRow = (int) Math.rint(getRowStart(rowIndex,parent)*heightScale);
            yRow += (rowIndex-1)*gap;
            final int columnWidth = (int) Math.rint(computeWidth(columnIndex, parent)*widthScale);
            final int rowHeight = (int) Math.rint(computeHeight(rowIndex, parent)*heightScale);
            Dimension d = c.getPreferredSize();
            d.width = Math.min(d.width,columnWidth);
            d.height = Math.min(d.height,rowHeight);
           final int xPadding = computeXPadding(columnWidth,d.width,getConstraints(c));
            final int yPadding = computeYPadding(rowHeight,d.height,getConstraints(c));
             // increase x and y, if appropriate
            final int x = insets.left+xColumn+xPadding+globalXPadding;
            final int y = insets.top+yRow+yPadding+globalYPadding;
            // Set the ISahitsComponent's size and position.
            c.setBounds(x, y, d.width, d.height);
        }

    resetSizeCache();
  }
  /**
   * Compute the scale factor that is needed on the ISahitsComponents to resize them to
   * the heigth of the ISahitsContainer
   * @param parent ISahitsContainer
   * @return scale factor
   */
  private double computeHeightScale(ISahitsContainer parent) {
    Insets insets = parent.getInsets();
    int hight = parent.getHeight()-insets.top-insets.bottom;
    int addHeigth = addUpRowHeight(parent);
    int constHeight = insets.top+insets.bottom+(nbRows-1)*gap;
    return 1.0*hight/(addHeigth-constHeight); // compute the scale factor without the gaps
  }
  /**
   * Compute the scale factor that is needed on the ISahitsComponents to resize them to
   * the width of the ISahitsContainer
   * @param parent ISahitsContainer
   * @return scale factor
   */
  private double computeWidthScale(ISahitsContainer parent) {
    Insets insets = parent.getInsets();
       int width = parent.getWidth()-insets.left-insets.right;
        int addWidth = addUpColumnWidth(parent);
    int constWidth = insets.left+insets.right+(nbCols-1)*gap;
    return 1.0*width/(addWidth-constWidth); // compute the scale factor without the gaps
  }
  /**
   * check if the size of the children add up to more than the parents size
   * @param parent ISahitsContainer
   * @return true if the height of the parent ISahitsContainer is larger or equal than the sum of
   * all the rows plus the parents insets.
   */
  private boolean checkHeight(ISahitsContainer parent) {
        int heigth = parent.getHeight();
        int addHeigth = addUpRowHeight(parent);
    return addHeigth<=heigth;
  }
  /**
   * Adding up the row height of a ISahitsContainer. Between each row the gap height is added
   * @param parent ISahitsContainer
   * @return height of all child ISahitsComponents plus the parents insets
   */
  private int addUpRowHeight(ISahitsContainer parent) {
    Insets insets = parent.getInsets();
        int addHeigth=0;
        for (int i=1;i<=nbRows;i++){
          addHeigth += computeHeight(i, parent);
          if (i<nbRows){
            addHeigth += gap;
          }
        }
        addHeigth += insets.top+insets.bottom;
    return addHeigth;
  }
  /**
   * check if the size of the children add up to more than the parents size
   * @param parent ISahitsContainer
   * @return true if the width of the parent ISahitsContainer is larger or equal than the sum of
   * all the columns plus the parents insets.
   */
  private boolean checkWidth(ISahitsContainer parent) {
        int width = parent.getWidth();
        int addWidth = addUpColumnWidth(parent);
    return addWidth<=width;
  }
  /**
   * Adding up the column width of a ISahitsContainer. Between each column the gap width is added
   * @param parent ISahitsContainer
   * @return width of all child ISahitsComponents plus the parents insets
   */
  private int addUpColumnWidth(ISahitsContainer parent) {
        Insets insets = parent.getInsets();
    int addWidth=0;
        for (int i=1;i<=nbCols;i++){
          addWidth += computeWidth(i, parent);
          if (i<nbCols){
            addWidth += gap;
          }
        }
        addWidth += insets.left+insets.right;
    return addWidth;
  }
  /**
   * Compute the vertical padding within a cell based upon the alignment of the ISahitsComponent
   * @param rowHeight height of the cell
   * @param height of the ISahitsComponent
   * @param constraints Objects
   * @return padding from the top
   */
  final int computeYPadding(int rowHeight, int height,
      MaximalGridLayoutConstraints constraints) {
    switch (constraints.getAnchor()) {
    case TOP_LEFT:
    case TOP:
    case TOP_RIGHT:
      return 0;
    case LEFT:
    case CENTER:
    case RIGHT:
      return (rowHeight-height)/2;
    default: // bottom
      return rowHeight-height;
    }
  }
  /**
   * Compute the horizontal padding within a cell based upon the alignment of the ISahitsComponent
   * @param columnWidth width of the cell
   * @param width of the ISahitsComponent
   * @param constraints Object
   * @return padding from the left
   */
  final int computeXPadding(int columnWidth, int width,
      MaximalGridLayoutConstraints constraints) {
    switch (constraints.getAnchor()) {
    case TOP_LEFT:
    case LEFT:
    case BOTTOM_LEFT:
      return 0;
    case TOP:
    case CENTER:
    case BOTTOM:
      return (columnWidth-width)/2;
    default: // the right side
      return columnWidth-width;
    }
  }
  /**
   * Compute the y position where the row with the given index starts
   * @param index of the row
   * @param parent ISahitsContainer
   * @return
   */
  final int getRowStart(int index, ISahitsContainer parent) {
    int yPadding = 0;
    for (int i=1;i<index;i++){
      yPadding+=computeHeight(i, parent);
    }
    return yPadding;
  }
  /**
   * Compute the x position where the column with the given index starts
   * @param index of the column
   * @param parent ISahitsContainer
   * @return
   */
  final int getColumnStart(int index, ISahitsContainer parent) {
    int xPadding = 0;
    for (int i=1;i<index;i++){
      xPadding+=computeWidth(i, parent);
    }
    return xPadding;
  }
  /**
   * Compute the row based on the index of the ISahitsComponent
   * @param i index of the ISahitsComponent
   * @return
   */
  final int computeRowIndex(int i) {
    return (i)/nbCols+1;
  }
  /**
   * Compute the column based on the index of the ISahitsComponent
   * @param i index of the ISahitsComponent
   * @return
   */
  final int computeColumnIndex(int i) {
    int inter = (i)%nbCols;
    return inter+1;
  }
 
    /**
     * Sets the constraints for the specified ISahitsComponent in this layout.
     * @param       comp the ISahitsComponent to be modified
     * @param       constraints the constraints to be applied
     */
    public void setConstraints(ISahitsComponent comp,
        MaximalGridLayoutConstraints constraints) {
        compTable.put(comp, (MaximalGridLayoutConstraints) constraints);
    }
    /**
     * Gets the constraints for the specified ISahitsComponent.  A copy of
     * the actual <code>GridBagConstraints</code> object is returned.
     * @param       comp the ISahitsComponent to be queried
     * @return      the constraint for the specified ISahitsComponent in this
     *                  grid bag layout; a copy of the actual constraint
     *                  object is returned
     */
    public MaximalGridLayoutConstraints getConstraints(ISahitsComponent comp) {
      MaximalGridLayoutConstraints constraints = compTable.get(comp);
        if (constraints == null) {
            setConstraints(comp, new MaximalGridLayoutConstraints());
            constraints = compTable.get(comp);
        }
        return (MaximalGridLayoutConstraints) constraints;
    }   
    /**
   * Adding a ISahitsComponent with a {@link MaximalGridLayoutConstraints}
   */
  @Override
  public void addLayoutComponent(ISahitsComponent comp, ISahitsLayoutConstraint constraints) {
    if (!(constraints instanceof MaximalGridLayoutConstraints)){
      throw new IllegalArgumentException("The constraint must be of type MaximalGridLayoutConstraints");
    }
    setConstraints(comp, (MaximalGridLayoutConstraints) constraints);
  }



}
TOP

Related Classes of ch.sahits.game.graphic.layout.SahitsMaximalGridLayout

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.