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 org.apache.commons.lang.StringUtils; 019import org.kuali.rice.krad.datadictionary.parse.BeanTag; 020import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 021import org.kuali.rice.krad.datadictionary.parse.BeanTags; 022import org.kuali.rice.krad.uif.CssConstants; 023import org.kuali.rice.krad.uif.CssConstants.Padding; 024import org.kuali.rice.krad.uif.UifConstants.Orientation; 025import org.kuali.rice.krad.uif.component.Component; 026import org.kuali.rice.krad.uif.container.Container; 027import org.kuali.rice.krad.uif.element.Header; 028import org.kuali.rice.krad.uif.element.Message; 029import org.kuali.rice.krad.uif.element.MultiFileUploadCollection; 030import org.kuali.rice.krad.uif.element.ProgressBar; 031import org.kuali.rice.krad.uif.field.ProgressBarField; 032import org.kuali.rice.krad.uif.util.LifecycleElement; 033 034import java.util.ArrayList; 035import java.util.List; 036 037/** 038 * Layout manager that organizes components in a single row (horizontal) or 039 * column (vertical) 040 * 041 * <p> 042 * Although a table based template could be used, setup is done to also support 043 * a CSS based template. The items in the <code>Container</code> instance are 044 * rendered sequentially wrapping each one with a span element. The padding 045 * property can be configured to space the elements as needed. To achieve a 046 * vertical orientation, the span style is set to block. Additional styling can 047 * be set for the items by using the itemSpanStyle property. 048 * </p> 049 * 050 * @author Kuali Rice Team (rice.collab@kuali.org) 051 */ 052@BeanTags({@BeanTag(name = "boxLayout", parent = "Uif-BoxLayoutBase"), 053 @BeanTag(name = "horizontalBoxLayout", parent = "Uif-HorizontalBoxLayout"), 054 @BeanTag(name = "verticalBoxLayout", parent = "Uif-VerticalBoxLayout")}) 055public class BoxLayoutManager extends LayoutManagerBase { 056 private static final long serialVersionUID = 4467342272983290044L; 057 058 private Orientation orientation; 059 private String padding; 060 061 private String itemStyle; 062 private List<String> itemStyleClasses; 063 064 private boolean renderLayoutWrapper; 065 066 public BoxLayoutManager() { 067 super(); 068 069 itemStyle = ""; 070 orientation = Orientation.HORIZONTAL; 071 itemStyleClasses = new ArrayList<String>(); 072 } 073 074 /** 075 * Sets the item span style 076 * 077 * {@inheritDoc} 078 */ 079 @Override 080 public void performFinalize(Object model, LifecycleElement container) { 081 super.performFinalize(model, container); 082 083 if (StringUtils.isBlank(itemStyle)) { 084 itemStyle = ""; 085 } 086 087 if (StringUtils.isNotEmpty(padding)) { 088 if (orientation.equals(Orientation.VERTICAL)) { 089 // set item to block which will cause a line break and margin 090 // bottom for padding 091 itemStyle += CssConstants.getCssStyle(Padding.PADDING_BOTTOM, padding); 092 } else { 093 // set margin right for padding 094 itemStyle += CssConstants.getCssStyle(Padding.PADDING_RIGHT, padding); 095 } 096 } 097 098 for (Component c : ((Container) container).getItems()) { 099 if (c != null) { 100 if (orientation.equals(Orientation.HORIZONTAL)) { 101 c.addStyleClass("uif-boxLayoutHorizontalItem"); 102 103 ((Component) container).addStyleClass("clearfix"); 104 105 for (String styleClass : this.getItemStyleClasses()) { 106 c.addStyleClass(styleClass); 107 } 108 109 } else { 110 c.addStyleClass("uif-boxLayoutVerticalItem"); 111 112 if (!(c instanceof Header 113 || c instanceof Container 114 || c instanceof Message 115 || c instanceof ProgressBar 116 || c instanceof ProgressBarField 117 || c instanceof MultiFileUploadCollection)) { 118 c.addStyleClass("pull-left"); 119 } 120 121 for (String styleClass : this.getItemStyleClasses()) { 122 c.addStyleClass(styleClass); 123 } 124 125 c.addStyleClass("clearfix"); 126 } 127 128 if (c.getStyle() != null && !c.getStyle().endsWith(";")) { 129 c.appendToStyle(";" + this.getItemStyle()); 130 } else { 131 c.appendToStyle(this.getItemStyle()); 132 } 133 } 134 } 135 } 136 137 /** 138 * Indicates whether the components should be rendered in a horizontal or 139 * vertical column 140 * 141 * @return orientation configured for layout 142 */ 143 @BeanTagAttribute 144 public Orientation getOrientation() { 145 return this.orientation; 146 } 147 148 /** 149 * Setter for the orientation for layout 150 * 151 * @param orientation 152 */ 153 public void setOrientation(Orientation orientation) { 154 this.orientation = orientation; 155 } 156 157 /** 158 * Amount of separation between each item 159 * 160 * <p> 161 * For horizontal orientation, this will be the right padding for each item. 162 * For vertical, it will be the bottom padding for each item. The value can 163 * be a fixed length (like px) or percentage 164 * </p> 165 * 166 * @return String 167 */ 168 @BeanTagAttribute 169 public String getPadding() { 170 return this.padding; 171 } 172 173 /** 174 * Setter for the item padding 175 * 176 * @param padding 177 */ 178 public void setPadding(String padding) { 179 this.padding = padding; 180 } 181 182 /** 183 * Used by the render to set the style on the span element that wraps the 184 * item. By using a wrapping span the items can be aligned based on the 185 * orientation and given the correct padding 186 * 187 * @return css style string 188 */ 189 @BeanTagAttribute 190 public String getItemStyle() { 191 return this.itemStyle; 192 } 193 194 /** 195 * Setter for the span style 196 * 197 * @param itemStyle 198 */ 199 public void setItemStyle(String itemStyle) { 200 this.itemStyle = itemStyle; 201 } 202 203 /** 204 * List of style classes that should be applied to each span that wraps the item in the layout 205 * 206 * @return List<String> 207 */ 208 @BeanTagAttribute 209 public List<String> getItemStyleClasses() { 210 return itemStyleClasses; 211 } 212 213 /** 214 * Setter for the list of style classes that should apply to each item span 215 * 216 * @param itemStyleClasses 217 */ 218 public void setItemStyleClasses(List<String> itemStyleClasses) { 219 this.itemStyleClasses = itemStyleClasses; 220 } 221 222 /** 223 * Builds the HTML class attribute string by combining the item styleClasses list 224 * with a space delimiter 225 * 226 * @return class attribute string 227 */ 228 public String getItemStyleClassesAsString() { 229 if (itemStyleClasses != null) { 230 return StringUtils.join(itemStyleClasses, " "); 231 } 232 233 return ""; 234 } 235 236 public boolean isRenderLayoutWrapper() { 237 return renderLayoutWrapper; 238 } 239 240 public void setRenderLayoutWrapper(boolean renderLayoutWrapper) { 241 this.renderLayoutWrapper = renderLayoutWrapper; 242 } 243}