package pt.ist.fenixWebFramework.rendererExtensions; import java.util.Collection; import java.util.Iterator; import pt.ist.fenixWebFramework.renderers.OutputRenderer; import pt.ist.fenixWebFramework.renderers.components.HtmlComponent; import pt.ist.fenixWebFramework.renderers.components.HtmlText; import pt.ist.fenixWebFramework.renderers.layouts.FlowLayout; import pt.ist.fenixWebFramework.renderers.layouts.Layout; import pt.ist.fenixWebFramework.renderers.utils.RenderKit; import pt.ist.fenixWebFramework.renderers.utils.RenderUtils; /** * This renderer allows you to present a collection of objects using * a flow layout, that is, every object is presented just after the previous * without any special interface organization. * *

* Example: * <object A presentation> <object B presentation> * <object C presentation> * * @author naat */ public class FlowCollectionRenderer extends OutputRenderer { private String eachLayout; private String eachSchema; private String eachClasses; private String eachStyle; private String htmlSeparator; private String emptyMessageKey; private String emptyMessageClasses; private String emptyMessageBundle; private String eachInline; private boolean indented = true; public boolean isIndented() { return this.indented; } /** * Allows to prevent identation of the generated markup. This is specially * usefull when you need to prevent extra spaces between elements and the * separator. * * @property */ public void setIndented(boolean indented) { this.indented = indented; } public String getEachLayout() { return eachLayout; } /** * The layout to be used when presenting each sub object. * * @property */ public void setEachLayout(String eachLayout) { this.eachLayout = eachLayout; } public String getEachSchema() { return eachSchema; } public String getEachClasses() { return this.eachClasses; } /** * The css classes to be set in each sub object's presentation. * * @property */ public void setEachClasses(String eachClasses) { this.eachClasses = eachClasses; } public String getEachStyle() { return this.eachStyle; } /** * The css style to be used for each sub object's presentation. * * @property */ public void setEachStyle(String eachStyle) { this.eachStyle = eachStyle; } /** * The schema to be used when presenting each sub object. * * @property */ public void setEachSchema(String eachSchema) { this.eachSchema = eachSchema; } public String getHtmlSeparator() { return htmlSeparator; } /** * If you specify this property then value given will be inserted between * any two object's presentations. This, depending on the individual * presentation of each object, can be used to force line breaks or just * provide a visual separator. * * @property */ public void setHtmlSeparator(String htmlSeparator) { this.htmlSeparator = htmlSeparator; } public String getEmptyMessageKey() { return emptyMessageKey; } /** * When the given collection is empty this key will be used * to fecth an according message for the situation. The bundle * used is the module's default bundle. * * @property */ public void setEmptyMessageKey(String emptyMessageKey) { this.emptyMessageKey = emptyMessageKey; } public String getEmptyMessageClasses() { return emptyMessageClasses; } /** * This property can be used to costumize the css classes of the * message shown when the given collection is empty. * * @property */ public void setEmptyMessageClasses(String emptyMessageClasses) { this.emptyMessageClasses = emptyMessageClasses; } public String getEmptyMessageBundle() { return emptyMessageBundle; } /** * When emptyMessageKey is used to specify wich resource key will be used * when the collection is empty, this property allows to specify wich bundle * will be used to fetch the key. * * @property */ public void setEmptyMessageBundle(String emptyMessageBundle) { this.emptyMessageBundle = emptyMessageBundle; } public String getEachInline() { return this.eachInline; } /** * Indicates if the each object's presentation should be placed * inside a <div> or a <span>. * * @property */ public void setEachInline(String eachInline) { this.eachInline = eachInline; } @Override protected Layout getLayout(final Object object, Class type) { return new FlowCollectionLayout(object,type); } public class FlowCollectionLayout extends FlowLayout { protected boolean insertSeparator; protected Iterator iterator; private boolean empty; public FlowCollectionLayout(final Object object, Class type) { iterator = ((Collection) object).iterator(); } @Override public HtmlComponent createComponent(Object object, Class type) { HtmlComponent component = null; if ((getEmptyMessageKey() != null) && (hasMoreComponents() == false)) { component = new HtmlText(RenderUtils.getResourceString(getEmptyMessageBundle(), getEmptyMessageKey()), false); this.empty = true; } else { component = super.createComponent(object, type); component.setIndented(isIndented()); this.empty = false; } return component; } @Override public void applyStyle(HtmlComponent component) { if (this.empty) { component.setClasses(getEmptyMessageClasses()); } else { super.applyStyle(component); } } @Override protected boolean hasMoreComponents() { return iterator.hasNext(); } @Override protected HtmlComponent getNextComponent() { if (this.insertSeparator) { this.insertSeparator = false; return new HtmlText(getHtmlSeparator(),false); } else if (hasMoreComponents() && getHtmlSeparator() != null) { this.insertSeparator = true; } return renderValue(iterator.next(), RenderKit.getInstance().findSchema(getEachSchema()), getEachLayout()); } }; }