1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4  
     5  import org.aswing.Component;
     6  import org.aswing.Container;
     7  import org.aswing.EmptyLayout;
     8  import org.aswing.geom.Dimension;
     9  import org.aswing.Insets;
    10  
    11  /**
    12   * @author feynixs(Cai Rong)
    13   * @author iiley
    14   */
    15  class org.aswing.GridLayout extends EmptyLayout{
    16  	/**
    17       * This is the horizontal gap (in pixels) which specifies the space
    18       * between columns.  They can be changed at any time.
    19       * This should be a non-negative integer.
    20       *
    21       * @see #getHgap()
    22       * @see #setHgap(hgap:Number)
    23       */
    24      private var hgap:Number;
    25      /**
    26       * This is the vertical gap (in pixels) which specifies the space
    27       * between rows.  They can be changed at any time.
    28       * This should be a non negative integer.
    29       *
    30       * @see #getVgap()
    31       * @see #setVgap(vgap:Number)
    32       */
    33      private var vgap:Number;
    34      /**
    35       * This is the number of rows specified for the grid.  The number
    36       * of rows can be changed at any time.
    37       * This should be a non negative integer, where '0' means
    38       * 'any number' meaning that the number of Rows in that
    39       * dimension depends on the other dimension.
    40       *
    41       * @see #getRows()
    42       * @see #setRows(rows:Number)
    43       */
    44      private var rows:Number;
    45      /**
    46       * This is the number of columns specified for the grid.  The number
    47       * of columns can be changed at any time.
    48       * This should be a non negative integer, where '0' means
    49       * 'any number' meaning that the number of Columns in that
    50       * dimension depends on the other dimension.
    51       *
    52       * @see #getColumns()
    53       * @see #setColumns(cols:Number)
    54       */
    55      private var cols:Number;
    56  
    57  
    58  
    59      /**
    60       * GridLayout(rows:Number, cols:Number)<br>
    61       * GridLayout(rows:Number, cols:Number, hgap:Number)<br>
    62       * GridLayout(rows:Number, cols:Number, hgap:Number, vgap:Number)
    63       * <p>
    64       * Creates a grid layout with the specified number of rows and 
    65       * columns. All components in the layout are given equal size. 
    66       * <p>
    67       * In addition, the horizontal and vertical gaps are set to the 
    68       * specified values. Horizontal gaps are placed between each
    69       * of the columns. Vertical gaps are placed between each of
    70       * the rows. 
    71       * <p>
    72       * One, but not both, of <code>rows</code> and <code>cols</code> can 
    73       * be zero, which means that any number of objects can be placed in a 
    74       * row or in a column. 
    75       * <p>
    76       * All <code>GridLayout</code> constructors defer to this one.
    77       * @param     rows   the rows, with the value zero meaning 
    78       *                   any number of rows
    79       * @param     cols   the columns, with the value zero meaning 
    80       *                   any number of columns
    81       * @param     hgap   (optional)the horizontal gap, default 0
    82       * @param     vgap   (optional)the vertical gap, default 0
    83       * @throws Error  if the value of both
    84       *			<code>rows</code> and <code>cols</code> is 
    85       *			set to zero
    86       */
    87      public function GridLayout(rows:Number, cols:Number, hgap:Number, vgap:Number) {
    88  		if ((rows == 0) && (cols == 0)) {
    89  	     	trace("rows and cols cannot both be zero");
    90  	     	throw new Error("rows and cols cannot both be zero");
    91  	    }
    92  	    
    93  	    if(rows == undefined) rows = 1;
    94  	    if(cols == undefined) cols = 0;
    95  	    if(hgap == undefined) hgap = 0;
    96  	    if(vgap == undefined) vgap = 0;
    97  	    
    98  		this.rows = rows;
    99  		this.cols = cols;
   100  		this.hgap = hgap;
   101  		this.vgap = vgap;
   102      }
   103  
   104      /**
   105       * Gets the number of rows in this layout.
   106       * @return    the number of rows in this layout
   107       * 
   108       */
   109      public function getRows():Number {
   110  		return rows;
   111      }
   112  
   113      /**
   114       * Sets the number of rows in this layout to the specified value.
   115       * @param        rows   the number of rows in this layout
   116       * @throws    Error  if the value of both 
   117       *               <code>rows</code> and <code>cols</code> is set to zero
   118       */
   119      public function setRows(rows:Number):Void {
   120  		if ((rows == 0) && (this.cols == 0)) {
   121  	    	trace("rows and cols cannot both be zero");
   122  	    	throw new Error("rows and cols cannot both be zero");
   123  		}
   124  		this.rows = rows;
   125      }
   126  
   127      /**
   128       * Gets the number of columns in this layout.
   129       * @return  the number of columns in this layout
   130       * 
   131       */
   132      public function getColumns():Number {
   133  		return cols;
   134      }
   135  
   136      /**
   137       * Sets the number of columns in this layout to the specified value. 
   138       * Setting the number of columns has no affect on the layout 
   139       * if the number of rows specified by a constructor or by 
   140       * the <tt>setRows</tt> method is non-zero. In that case, the number 
   141       * of columns displayed in the layout is determined by the total 
   142       * number of components and the number of rows specified.
   143       * @param        cols   the number of columns in this layout
   144       * @throws    Error  if the value of both 
   145       *               <code>rows</code> and <code>cols</code> is set to zero
   146       * 
   147       */
   148      public function setColumns(cols:Number):Void {
   149  		if ((cols == 0) && (this.rows == 0)) {
   150  	    	trace("rows and cols cannot both be zero");
   151  	    	throw new Error("rows and cols cannot both be zero");
   152  		}
   153  		this.cols = cols;
   154      }
   155  
   156      /**
   157       * Gets the horizontal gap between components.
   158       * @return       the horizontal gap between components
   159       * 
   160       */
   161      public function getHgap():Number {
   162  		return hgap;
   163      }
   164      
   165      /**
   166       * Sets the horizontal gap between components to the specified value.
   167       * @param    hgap   the horizontal gap between components
   168       *
   169       */
   170      public function setHgap(hgap:Number):Void {
   171  		this.hgap = hgap;
   172      }
   173      
   174      /**
   175       * Gets the vertical gap between components.
   176       * @return       the vertical gap between components
   177       * 
   178       */
   179      public function getVgap():Number {
   180  		return vgap;
   181      }
   182      
   183      /**
   184       * Sets the vertical gap between components to the specified value.
   185       * @param         vgap  the vertical gap between components
   186       * 
   187       */
   188      public function setVgap(vgap:Number):Void {
   189  		this.vgap = vgap;
   190      }
   191  	
   192      public function preferredLayoutSize(target:Container):Dimension{
   193  		var insets:Insets = target.getInsets();
   194  		var ncomponents:Number = target.getComponentCount();
   195  		var nrows:Number = rows;
   196  		var ncols:Number = cols;
   197  		if (nrows > 0){
   198  			ncols = Math.floor(((ncomponents + nrows) - 1) / nrows);
   199  		}else{
   200  			nrows = Math.floor(((ncomponents + ncols) - 1) / ncols);
   201  		}
   202  		var w:Number = 0;
   203  		var h:Number = 0;
   204  		for (var i:Number = 0; i < ncomponents; i++){
   205  			var comp:Component = target.getComponent(i);
   206  			var d:Dimension = comp.getPreferredSize();
   207  			if (w < d.width){
   208  				w = d.width;
   209  			}
   210  			if (h < d.height){
   211  				h = d.height;
   212  			}
   213  		}
   214  		return new Dimension((((insets.left + insets.right) + (ncols * w)) + ((ncols - 1) * hgap)), (((insets.top + insets.bottom) + (nrows * h)) + ((nrows - 1) * vgap))); 	
   215      }
   216  
   217      public function minimumLayoutSize(target:Container):Dimension{
   218  		var insets:Insets = target.getInsets();
   219  		var ncomponents:Number = target.getComponentCount();
   220  		var nrows:Number = rows;
   221  		var ncols:Number = cols;
   222  		if (nrows > 0){
   223  			ncols = Math.floor(((ncomponents + nrows) - 1) / nrows);
   224  		}else{
   225  			nrows = Math.floor(((ncomponents + ncols) - 1) / ncols);
   226  		}
   227  		var w:Number = 0;
   228  		var h:Number = 0;
   229  		for (var i:Number = 0; i < ncomponents; i++)
   230  		{
   231  			var comp:Component = target.getComponent(i);
   232  			var d:Dimension = comp.getMinimumSize();
   233  			if (w < d.width)
   234  			{
   235  				w = d.width;
   236  			}
   237  			if (h < d.height)
   238  			{
   239  				h = d.height;
   240  			}
   241  		}
   242  		return new Dimension((((insets.left + insets.right) + (ncols * w)) + ((ncols - 1) * hgap)), (((insets.top + insets.bottom) + (nrows * h)) + ((nrows - 1) * vgap)));
   243      }
   244  	
   245  	/**
   246  	 * return new Dimension(Number.MAX_VALUE, Number.MAX_VALUE);
   247  	 */
   248      public function maximumLayoutSize(target:Container):Dimension{
   249      	return new Dimension(Number.MAX_VALUE, Number.MAX_VALUE);
   250      }
   251      
   252      public function layoutContainer(target:Container):Void{
   253  		var insets:Insets = target.getInsets();
   254  		var ncomponents:Number = target.getComponentCount();
   255  		var nrows:Number = rows;
   256  		var ncols:Number = cols;
   257  		if (ncomponents == 0){
   258  			return ;
   259  		}
   260  		if (nrows > 0){
   261  			ncols = Math.floor(((ncomponents + nrows) - 1) / nrows);
   262  		}else{
   263  			nrows = Math.floor(((ncomponents + ncols) - 1) / ncols);
   264  		}
   265  		var w:Number = (target.getWidth() - (insets.left + insets.right));
   266  		var h:Number = (target.getHeight() - (insets.top + insets.bottom));
   267  		w = ((w - ((ncols - 1) * hgap)) / ncols);
   268  		h = ((h - ((nrows - 1) * vgap)) / nrows);
   269  		var x:Number = insets.left;
   270  		var y:Number = insets.top;
   271  		for (var c:Number = 0; c < ncols; c++){
   272  			y = insets.top;
   273  			for (var r:Number = 0; r < nrows; r++){
   274  				var i:Number = ((r * ncols) + c);
   275  				if (i < ncomponents){
   276  					target.getComponent(i).setBounds(x, y, w, h);
   277  				}
   278  				y += (h + vgap);
   279  			}
   280  			x += (w + hgap);
   281  		}
   282  	}
   283  	public function toString():String{
   284  		return ((((((((("GridLayout[hgap=") + hgap) + ",vgap=") + vgap) + ",rows=") + rows) + ",cols=") + cols) + "]");
   285  	}
   286      
   287  	/**
   288  	 * return 0.5
   289  	 */
   290      public function getLayoutAlignmentX(target:Container):Number{
   291      	return 0.5;
   292      }
   293  
   294  	/**
   295  	 * return 0.5
   296  	 */
   297      public function getLayoutAlignmentY(target:Container):Number{
   298      	return 0.5;
   299      }
   300  }
   301