package org.richfaces.component; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.faces.FacesException; import javax.faces.component.UIComponent; public class LayoutStructure implements Serializable { // ------------------------------ FIELDS ------------------------------ private AbstractLayoutPanel bottom = null; private AbstractLayoutPanel center = null; private List<Column> columns; private int deep = 0; private AbstractLayoutPanel left = null; private AbstractLayoutPanel right = null; private AbstractLayoutPanel top = null; // --------------------------- CONSTRUCTORS --------------------------- public LayoutStructure(AbstractLayout layout) { sortPanels(layout); } public LayoutStructure(AbstractLayoutPanel panel) { UIComponent parent = panel.getParent(); if (parent instanceof AbstractLayout) { AbstractLayout layout = (AbstractLayout) parent; sortPanels(layout); } else { throw new FacesException("Layout panel should be children of UILayout pomponent"); } } // --------------------- GETTER / SETTER METHODS --------------------- /** * @return the bottom */ public AbstractLayoutPanel getBottom() { return bottom; } /** * @return the center */ public AbstractLayoutPanel getCenter() { return center; } /** * @return the deep */ public int getDeep() { return deep; } /** * @return the left */ public AbstractLayoutPanel getLeft() { return left; } /** * @return the right */ public AbstractLayoutPanel getRight() { return right; } /** * @return the top */ public AbstractLayoutPanel getTop() { return top; } // -------------------------- OTHER METHODS -------------------------- /** * @throws NumberFormatException */ public void calculateWidth() throws NumberFormatException { // calculate widths. if (getColumns() > 0) { float totalPercent = 0.0f; int numOfPercentColumns = 0; float totalPart = 0.0f; int numOfPartColumns = 0; // Collect width information. for (Column column : columns) { String width = column.panel.getWidth(); if (null == width || 0 == width.length()) { column.partWidth = 1.0f; totalPart += column.partWidth; numOfPartColumns++; } else if (width.startsWith("*")) { column.partWidth = Float.parseFloat(width.substring(1)); totalPart += column.partWidth; numOfPartColumns++; } else if (width.endsWith("%")) { column.percentWidth = Float.parseFloat(width.substring(0, width.length() - 1)); totalPercent += column.percentWidth; numOfPercentColumns++; } } float partToPercent = 0.0f; float percentCoefficient = 1.0f; if (numOfPartColumns > 0 && numOfPercentColumns > 0) { float rest = 100.00f - totalPercent; partToPercent = rest / totalPart; } else if (numOfPartColumns > 0) { partToPercent = 100.00f / totalPart; } else if (numOfPercentColumns == columns.size()) { percentCoefficient = 100.00f / totalPercent; } // TODO - calculate precisious coefficient. percentCoefficient *= 0.98f; // Recalculate width. for (Column column : columns) { if (column.partWidth > 0.0f) { column.percentWidth = column.partWidth * partToPercent; } column.percentWidth = column.percentWidth * percentCoefficient; } } } /** * @return the columns */ public int getColumns() { return columns.size(); } /** */ public String getWidth(AbstractLayoutPanel panel) { return getWidth(panel, 1.0f); } /** * @param panel * @param coeeficient * @return */ public String getWidth(AbstractLayoutPanel panel, float coeeficient) { if (this.top == panel || this.bottom == panel) { return panel.getWidth(); } else { for (Column column : columns) { if (column.panel == panel) { if (column.percentWidth > 0) { return String.format((Locale) null, "%2.2f%%", column.percentWidth * coeeficient); } else { return panel.getWidth(); } } } } return null; } /** * @param layout * @throws FacesException */ public void sortPanels(AbstractLayout layout) throws FacesException { this.deep = layoutDeep(layout); for (UIComponent child : layout.getChildren()) { if (child instanceof AbstractLayoutPanel && child.isRendered()) { AbstractLayoutPanel layoutPanel = (AbstractLayoutPanel) child; LayoutPosition position = layoutPanel.getPosition(); if (LayoutPosition.top.equals(position)) { if (null != top) { throw new FacesException( "Duplicate layoutPanel's with same position" + position); } top = layoutPanel; } else if (LayoutPosition.bottom.equals(position)) { if (null != bottom) { throw new FacesException( "Duplicate layoutPanel's with same position" + position); } bottom = layoutPanel; } else if (LayoutPosition.left.equals(position)) { if (null != left) { throw new FacesException( "Duplicate layoutPanel's with same position" + position); } left = layoutPanel; } else if (LayoutPosition.right.equals(position)) { if (null != right) { throw new FacesException( "Duplicate layoutPanel's with same position" + position); } right = layoutPanel; } else if (null == position || LayoutPosition.center.equals(position)) { if (null != center) { throw new FacesException( "Duplicate layoutPanel's with same position" + position); } center = layoutPanel; } else { } } } // Reorganise central row. if (null == left && null != center) { left = center; center = null; } if (null == left && null != right) { left = right; right = null; } if (null == center && null != right) { center = right; right = null; } this.columns = new ArrayList<Column>(3); if (null != left) { columns.add(new Column(left)); } if (null != center) { columns.add(new Column(center)); } if (null != right) { columns.add(new Column(right)); } } /** * Calculate deep of layout components. * * @param component * @return */ protected int layoutDeep(UIComponent component) { int deep = 0; if (null != component) { deep = layoutDeep(component.getParent()); if (component instanceof AbstractLayout) { deep++; } } return deep; } // -------------------------- INNER CLASSES -------------------------- static class Column { // ------------------------------ FIELDS ------------------------------ private final AbstractLayoutPanel panel; private float partWidth = 0.0f; private float percentWidth = 0.0f; // --------------------------- CONSTRUCTORS --------------------------- public Column(AbstractLayoutPanel panel) { this.panel = panel; } // --------------------- GETTER / SETTER METHODS --------------------- /** * @return the percentWidth */ public float getPercentWidth() { return percentWidth; } // -------------------------- OTHER METHODS -------------------------- public String getWidth() { if (percentWidth > 0.0f) { return String.format((Locale) null, "%2.2f%%", percentWidth); } else { return panel.getWidth(); } } } }