001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.uif.layout;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.commons.lang.StringUtils;
022import org.kuali.rice.krad.datadictionary.parse.BeanTag;
023import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
024import org.kuali.rice.krad.datadictionary.parse.BeanTags;
025import org.kuali.rice.krad.uif.CssConstants;
026import org.kuali.rice.krad.uif.component.Component;
027import org.kuali.rice.krad.uif.container.Container;
028import org.kuali.rice.krad.uif.container.Group;
029import org.kuali.rice.krad.uif.util.LifecycleElement;
030
031/**
032 * Layout manager that organizes its components in a table based grid
033 *
034 * <p>
035 * Items are laid out from left to right (with each item taking up one column)
036 * until the configured number of columns is reached. If the item count is
037 * greater than the number of columns, a new row will be created to render the
038 * remaining items (and so on until all items are placed). Labels for the fields
039 * can be pulled out (default) and rendered as a separate column. The manager
040 * also supports the column span and row span options for the field items. If
041 * not specified the default is 1.
042 * </p>
043 *
044 * @author Kuali Rice Team (rice.collab@kuali.org)
045 */
046@BeanTags({@BeanTag(name = "gridLayout", parent = "Uif-GridLayoutBase"),
047        @BeanTag(name = "twoColumnGridLayout", parent = "Uif-TwoColumnGridLayout"),
048        @BeanTag(name = "fourColumnGridLayout", parent = "Uif-FourColumnGridLayout"),
049        @BeanTag(name = "sixColumnGridLayout", parent = "Uif-SixColumnGridLayout")})
050public class GridLayoutManagerBase extends LayoutManagerBase implements GridLayoutManager {
051    private static final long serialVersionUID = 1890011900375071128L;
052
053    private int numberOfColumns;
054
055    private boolean suppressLineWrapping;
056    private boolean applyAlternatingRowStyles;
057    private boolean applyDefaultCellWidths;
058    private boolean renderFirstRowHeader;
059    private boolean renderAlternatingHeaderColumns;
060    private boolean renderRowFirstCellHeader;
061
062    private List<String> rowCssClasses;
063
064    private List<String> rowDataAttributes;
065
066    public GridLayoutManagerBase() {
067        super();
068
069        rowCssClasses = new ArrayList<String>();
070        rowDataAttributes = new ArrayList<String>();
071    }
072
073    /**
074     * The following finalization is performed:
075     *
076     * <ul>
077     * <li>If suppressLineWrapping is true, sets the number of columns to the
078     * container's items list size</li>
079     * <li>Adjust the cell attributes for the container items</li>
080     * </ul>
081     *
082     * {@inheritDoc}
083     */
084    @Override
085    public void performFinalize(Object model, LifecycleElement parent) {
086        super.performFinalize(model, parent);
087        
088        Container container = (Container) parent;
089
090        // Default equal cell widths class
091        if (this.isApplyDefaultCellWidths()){
092            this.addStyleClass("uif-table-fixed");
093        }
094
095        if (suppressLineWrapping) {
096            numberOfColumns = container.getItems().size();
097        }
098
099        for (Component item : container.getItems()) {
100            if (!(this instanceof TableLayoutManager)) {
101                item.addWrapperCssClass("uif-gridLayoutCell");
102            }
103            setCellAttributes(item);
104        }
105    }
106
107    /**
108     * Moves the width, align, and valign settings of the component to the corresponding cell properties (if not
109     * already configured)
110     *
111     * @param component instance to adjust settings for
112     */
113    protected void setCellAttributes(Component component) {
114        if (StringUtils.isNotBlank(component.getWidth()) && StringUtils.isBlank(component.getCellWidth())) {
115            component.setCellWidth(component.getWidth());
116            component.setWidth("");
117        }
118
119        if (StringUtils.isNotBlank(component.getAlign()) && !StringUtils.contains(component.getWrapperStyle(),
120                CssConstants.TEXT_ALIGN)) {
121            if (component.getWrapperStyle() == null) {
122                component.setWrapperStyle("");
123            }
124
125            component.setWrapperStyle(
126                    component.getWrapperStyle() + CssConstants.TEXT_ALIGN + component.getAlign() + ";");
127            component.setAlign("");
128        }
129
130        if (StringUtils.isNotBlank(component.getValign()) && !StringUtils.contains(component.getWrapperStyle(),
131                CssConstants.VERTICAL_ALIGN)) {
132            if (component.getWrapperStyle() == null) {
133                component.setWrapperStyle("");
134            }
135
136            component.setWrapperStyle(
137                    component.getWrapperStyle() + CssConstants.VERTICAL_ALIGN + component.getValign() + ";");
138            component.setValign("");
139        }
140    }
141
142    /**
143     * @see LayoutManagerBase#getSupportedContainer()
144     */
145    @Override
146    public Class<? extends Container> getSupportedContainer() {
147        return Group.class;
148    }
149
150    /**
151     * {@inheritDoc}
152     */
153    @Override
154    @BeanTagAttribute
155    public int getNumberOfColumns() {
156        return this.numberOfColumns;
157    }
158
159    /**
160     * {@inheritDoc}
161     */
162    @Override
163    public void setNumberOfColumns(int numberOfColumns) {
164        this.numberOfColumns = numberOfColumns;
165    }
166
167    /**
168     * {@inheritDoc}
169     */
170    @Override
171    @BeanTagAttribute
172    public boolean isSuppressLineWrapping() {
173        return this.suppressLineWrapping;
174    }
175
176    /**
177     * {@inheritDoc}
178     */
179    @Override
180    public void setSuppressLineWrapping(boolean suppressLineWrapping) {
181        this.suppressLineWrapping = suppressLineWrapping;
182    }
183
184    /**
185     * {@inheritDoc}
186     */
187    @Override
188    @BeanTagAttribute
189    public boolean isApplyAlternatingRowStyles() {
190        return this.applyAlternatingRowStyles;
191    }
192
193    /**
194     * {@inheritDoc}
195     */
196    @Override
197    public void setApplyAlternatingRowStyles(boolean applyAlternatingRowStyles) {
198        this.applyAlternatingRowStyles = applyAlternatingRowStyles;
199    }
200
201    /**
202     * {@inheritDoc}
203     */
204    @Override
205    @BeanTagAttribute
206    public boolean isApplyDefaultCellWidths() {
207        return this.applyDefaultCellWidths;
208    }
209
210    /**
211     * {@inheritDoc}
212     */
213    @Override
214    public void setApplyDefaultCellWidths(boolean applyDefaultCellWidths) {
215        this.applyDefaultCellWidths = applyDefaultCellWidths;
216    }
217
218    /**
219     * {@inheritDoc}
220     */
221    @Override
222    @BeanTagAttribute
223    public boolean isRenderRowFirstCellHeader() {
224        return renderRowFirstCellHeader;
225    }
226
227    /**
228     * {@inheritDoc}
229     */
230    @Override
231    public void setRenderRowFirstCellHeader(boolean renderRowFirstCellHeader) {
232        this.renderRowFirstCellHeader = renderRowFirstCellHeader;
233    }
234
235    /**
236     * {@inheritDoc}
237     */
238    @Override
239    @BeanTagAttribute
240    public boolean isRenderFirstRowHeader() {
241        return renderFirstRowHeader;
242    }
243
244    /**
245     * {@inheritDoc}
246     */
247    @Override
248    public void setRenderFirstRowHeader(boolean renderFirstRowHeader) {
249        this.renderFirstRowHeader = renderFirstRowHeader;
250    }
251
252    /**
253     * {@inheritDoc}
254     */
255    @Override
256    @BeanTagAttribute
257    public boolean isRenderAlternatingHeaderColumns() {
258        return this.renderAlternatingHeaderColumns;
259    }
260
261    /**
262     * {@inheritDoc}
263     */
264    @Override
265    public void setRenderAlternatingHeaderColumns(boolean renderAlternatingHeaderColumns) {
266        this.renderAlternatingHeaderColumns = renderAlternatingHeaderColumns;
267    }
268
269    /**
270     * {@inheritDoc}
271     */
272    @Override
273    @BeanTagAttribute
274    public List<String> getRowCssClasses() {
275        return rowCssClasses;
276    }
277
278    /**
279     * {@inheritDoc}
280     */
281    @Override
282    public void setRowCssClasses(List<String> rowCssClasses) {
283        this.rowCssClasses = rowCssClasses;
284    }
285
286    /**
287     * {@inheritDoc}
288     */
289    @Override
290    @BeanTagAttribute(name = "rowDataAttributes", type = BeanTagAttribute.AttributeType.LISTVALUE)
291    public List<String> getRowDataAttributes() {
292        return rowDataAttributes;
293    }
294
295    /**
296     * {@inheritDoc}
297     */
298    @Override
299    public void setRowDataAttributes(List<String> rowDataAttributes) {
300        this.rowDataAttributes = rowDataAttributes;
301    }
302}