/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.ui.hud.layout; import java.util.ArrayList; import org.xith3d.ui.hud.base.Widget; /** * The GridLayout arranges the contained Widgets in a Grid.<br> * You can define borders and gaps and even column- and row-weights.<br> * <br> * the widgets' original size is overwritten by the calculated size. * If the rows-count is 0, then the widget's original height is respected * and only the width is calculated. The same applies for columns-count.<br> * <br> * If columns-count is greater than 0, one row is filled after the other in the * order, the widgets are added. * If columns-count is 0, the fields are filled by column-first. * * @author Marvin Froehlich (aka Qudus) */ public class GridLayout extends BorderSettableLayoutManagerBase { private int rows; private int cols; private float hgap; private float vgap; private float[] colWeights = null; private float[] rowWeights = null; private float[] recColWeights = null; private float[] recRowWeights = null; public void setRows( int rows ) { this.rows = rows; } public final int getRows() { return ( rows ); } public void setCols( int cols ) { this.cols = cols; } public final int getCols() { return ( cols ); } public void setHGap( float hgap ) { this.hgap = hgap; } public final float getHGap() { return ( hgap ); } public void setVGap( float vgap ) { this.vgap = vgap; } public final float getVGap() { return ( vgap ); } public void setColWeights( float... weights ) { this.colWeights = weights; if ( colWeights != null ) { if ( ( recColWeights == null ) || ( recColWeights.length != colWeights.length ) ) recColWeights = new float[ colWeights.length ]; float sum = 0f; for ( int i = 0; i < colWeights.length; i++ ) sum += colWeights[ i ]; for ( int i = 0; i < colWeights.length; i++ ) recColWeights[ i ] = colWeights[ i ] / sum; } } public final float[] getColWeights() { return ( colWeights ); } public void setRowWeights( float... weights ) { this.rowWeights = weights; if ( rowWeights != null ) { if ( ( recRowWeights == null ) || ( recRowWeights.length != rowWeights.length ) ) recRowWeights = new float[ rowWeights.length ]; float sum = 0f; for ( int i = 0; i < rowWeights.length; i++ ) sum += rowWeights[ i ]; for ( int i = 0; i < rowWeights.length; i++ ) recRowWeights[ i ] = rowWeights[ i ] / sum; } } public final float[] getRowWeights() { return ( rowWeights ); } /** * {@inheritDoc} */ @Override protected void doLayout( final float left0, final float top0, final float containerResX, final float containerResY ) { final ArrayList< Widget > widgets = getWidgets(); if ( ( rows > 0 ) && ( cols > 0 ) ) { final float totalWidth = ( containerResX - ( ( getCols() - 1 ) * getHGap() ) ); final float totalHeight = ( containerResY - ( ( getRows() - 1 ) * getVGap() ) ); float width = 0f; float height = 0f; if ( getColWeights() == null ) width = totalWidth / getCols(); if ( getRowWeights() == null ) height = totalHeight / getRows(); float left = left0; float top = top0; int row = 0; int col = 0; for ( int i = 0; i < widgets.size(); i++ ) { final Widget widget = widgets.get( i ); if ( !widget.isVisible() && getInvisibleWidgetsHidden() ) continue; if ( getColWeights() != null ) width = totalWidth * recColWeights[ col ]; if ( getRowWeights() != null ) height = totalHeight * recRowWeights[ row ]; widget.setSize( width, height ); widget.setLocation( left, top ); col++; left += width + getHGap(); if ( col >= getCols() ) { col = 0; row++; left = left0; top += height + getVGap(); } } } else if ( ( rows == 0 ) && ( cols > 0 ) ) { final float totalWidth = ( containerResX - ( ( getCols() - 1 ) * getHGap() ) ); float width = 0f; float height = 0f; if ( getColWeights() == null ) width = totalWidth / getCols(); float left = left0; float top = top0; int row = 0; int col = 0; for ( int i = 0; i < widgets.size(); i++ ) { final Widget widget = widgets.get( i ); if ( !widget.isVisible() && getInvisibleWidgetsHidden() ) continue; if ( getColWeights() != null ) width = totalWidth * recColWeights[ col ]; if ( widget.getHeight() > height ) height = widget.getHeight(); widget.setSize( width, widget.getHeight() ); widget.setLocation( left, top ); col++; left += width + getHGap(); if ( col >= getCols() ) { col = 0; row++; left = left0; top += height + getVGap(); height = 0f; } } } else if ( ( rows > 0 ) && ( cols == 0 ) ) { final float totalHeight = ( containerResY - ( ( getRows() - 1 ) * getVGap() ) ); float width = 0f; float height = 0f; if ( getRowWeights() == null ) height = totalHeight / getRows(); float left = left0; float top = top0; int row = 0; int col = 0; for ( int i = 0; i < widgets.size(); i++ ) { final Widget widget = widgets.get( i ); if ( !widget.isVisible() && getInvisibleWidgetsHidden() ) continue; if ( widget.getWidth() > width ) width = widget.getWidth(); if ( getRowWeights() != null ) height = totalHeight * recRowWeights[ row ]; widget.setSize( widget.getWidth(), height ); widget.setLocation( left, top ); row++; top += height + getVGap(); if ( row >= getRows() ) { row = 0; col++; top = top0; left += width + getHGap(); width = 0f; } } } } public GridLayout( int rows, int cols, float hgap, float vgap, float borderBottom, float borderRight, float borderTop, float borderLeft ) { super( borderBottom, borderRight, borderTop, borderLeft ); if ( ( rows < 0 ) || ( cols < 0 ) ) throw new IllegalArgumentException( "rows and cols must be >= 0" ); if ( ( rows == 0 ) && ( cols == 0 ) ) throw new IllegalArgumentException( "rows and cols cannot be 0 at the same time" ); if ( ( hgap < 0f ) || ( vgap < 0f ) ) throw new IllegalArgumentException( "hgap and vgap must be >= 0" ); this.rows = rows; this.cols = cols; this.hgap = hgap; this.vgap = vgap; } public GridLayout( int rows, int cols, float hgap, float vgap ) { this( rows, cols, hgap, vgap, 0f, 0f, 0f, 0f ); } public GridLayout( int rows, int cols, float borderBottom, float borderRight, float borderTop, float borderLeft ) { this( rows, cols, 0f, 0f, borderBottom, borderRight, borderTop, borderLeft ); } public GridLayout( int rows, int cols ) { this( rows, cols, 0f, 0f ); } }