org.richfaces.renderkit.html.PopupPanelBaseRenderer Maven / Gradle / Ivy
The newest version!
package org.richfaces.renderkit.html;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.faces.FacesException;
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.richfaces.component.AbstractPopupPanel;
import org.richfaces.json.JSONException;
import org.richfaces.json.JSONMap;
import org.richfaces.renderkit.RendererBase;
//TODO nick - JSF have concept of library, it should be used instead of '/' in resource names
@ResourceDependencies({ @ResourceDependency(library = "javax.faces", name = "jsf.js"),
@ResourceDependency(name = "jquery.js"),
@ResourceDependency(name = "richfaces.js"),
@ResourceDependency(name = "richfaces-base-component.js"),
@ResourceDependency(name = "richfaces-event.js"),
@ResourceDependency(library = "org.richfaces", name = "popupPanel.js"),
@ResourceDependency(library = "org.richfaces", name = "popupPanelBorders.js"),
@ResourceDependency(library = "org.richfaces", name = "popupPanelSizer.js"),
@ResourceDependency(library = "org.richfaces", name = "popupPanel.ecss") })
public class PopupPanelBaseRenderer extends RendererBase {
private static final String CONTROLS_FACET = "controls";
private static final String HEADER_FACET = "header";
private static final int SIZE = 10;
private static final String STATE_OPTION_SUFFIX = "StateOption_";
private static final String DEFAULT_LEFT = "auto";
private static final String DEFAULT_TOP = "auto";
// TODO nick - use enums
private static final Set ALLOWED_ATTACHMENT_OPTIONS = new HashSet();
static {
ALLOWED_ATTACHMENT_OPTIONS.add("body");
ALLOWED_ATTACHMENT_OPTIONS.add("parent");
ALLOWED_ATTACHMENT_OPTIONS.add("form");
}
public void renderHeaderFacet(FacesContext context, UIComponent component) throws IOException {
renderFacet(context, component, HEADER_FACET);
}
public void renderControlsFacet(FacesContext context, UIComponent component) throws IOException {
renderFacet(context, component, CONTROLS_FACET);
}
private void renderFacet(FacesContext context, UIComponent component, String facet) throws IOException {
UIComponent headerFacet = component.getFacet(facet);
headerFacet.encodeAll(context);
}
@SuppressWarnings("unchecked")
protected void doDecode(FacesContext context, UIComponent component) {
super.doDecode(context, component);
AbstractPopupPanel panel = (AbstractPopupPanel) component;
ExternalContext exCtx = context.getExternalContext();
Map rqMap = exCtx.getRequestParameterMap();
Object panelOpenState = rqMap.get(panel.getClientId(context) + "OpenedState");
if (panel.isKeepVisualState()) {
if (null != panelOpenState) {
// Bug https://jira.jboss.org/jira/browse/RF-2466
// Incorrect old:
// panel.setShowWhenRendered(Boolean.parseBoolean((String) clnId));
// ShowWhenRendered can be settled separately with modal panel "showWhenRendered" attribute
// so we should combine ShowWhenRendered || KeepVisualState && (OpenedState==TRUE) against rewriting
boolean show = panel.isShow() || Boolean.parseBoolean((String) panelOpenState);
panel.setShow(show);
Map visualOptions = (Map) getHandledVisualOptions(panel);
Iterator> it = rqMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
int suffixPos = entry.getKey().toString().indexOf(STATE_OPTION_SUFFIX);
if (-1 != suffixPos) {
String key = entry.getKey().toString().substring(suffixPos + STATE_OPTION_SUFFIX.length());
visualOptions.put(key, entry.getValue());
}
}
}
}
}
protected Class getComponentClass() {
return AbstractPopupPanel.class;
}
public void checkOptions(FacesContext context, UIComponent component) {
AbstractPopupPanel panel = (AbstractPopupPanel) component;
if (panel.isAutosized() && panel.isResizeable()) {
throw new IllegalArgumentException("Autosized modal panel can't be resizeable.");
}
String domElementAttachment = panel.getDomElementAttachment();
if (domElementAttachment != null && domElementAttachment.trim().length() != 0) {
if (!ALLOWED_ATTACHMENT_OPTIONS.contains(domElementAttachment)) {
throw new IllegalArgumentException("Value '" + domElementAttachment
+ "' of domElementAttachment attribute is illegal. " + "Allowed values are: " + ALLOWED_ATTACHMENT_OPTIONS);
}
}
if (panel.getMinHeight() != -1) {
if (panel.getMinHeight() < SIZE) {
throw new FacesException("Attribbute minWidth should be greater then 10px");
}
}
if (panel.getMinWidth() != -1) {
if (panel.getMinWidth() < SIZE) {
throw new FacesException("Attribbute minHeight should be greater then 10px");
}
}
}
public boolean getRendersChildren() {
return true;
}
@SuppressWarnings("unchecked")
public String buildShowScript(FacesContext context, UIComponent component) {
AbstractPopupPanel panel = (AbstractPopupPanel) component;
StringBuilder result = new StringBuilder();
// Bug https://jira.jboss.org/jira/browse/RF-2466
// We are already processed KeepVisualState and current open state in
// doDecode, so no need to check panel.isKeepVisualState() here.
if (panel.isShow()) {
result.append("RichFaces.ui.PopupPanel.showPopupPanel('" + panel.getClientId(context) + "', {");
// TODO nick - use ScriptUtils.toScript
Iterator> it = ((Map) getHandledVisualOptions(panel)).entrySet()
.iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
result.append(entry.getKey() + ": '" + entry.getValue() + "'");
if (it.hasNext()) {
result.append(", ");
}
}
result.append("});");
}
if (result.length() > 0) {
return result.toString();
}
return null;
}
public String getStyleIfTrimmed(UIComponent panel) {
if (panel.getAttributes().get("trimOverlayedElements").equals(Boolean.TRUE)) {
return "position: relative; z-index : 0";
}
return "";
}
public String getContainerStyle(UIComponent panel) {
StringBuilder res = new StringBuilder();
Map attrs = panel.getAttributes();
res.append("position: ").append(((Boolean) attrs.get("followByScroll")) ? "fixed" : "absolute").append("; ");
Integer zindex = (Integer) attrs.get("zindex");
if (zindex != null) {
res.append("z-index:").append(zindex).append("; ");
}
String style = (String) attrs.get("style");
if (style != null && style.length() > 0) {
res.append(style);
}
return res.toString();
}
private Object buildEventFunction(Object eventFunction) {
if (eventFunction != null && eventFunction.toString().length() > 0) {
return "new Function(\"" + eventFunction.toString() + "\");";
}
return null;
}
public Map getHandledVisualOptions(UIComponent component) {
AbstractPopupPanel panel = (AbstractPopupPanel) component;
String options = panel.getVisualOptions();
Map result;
result = prepareVisualOptions(options, panel);
if (null == result) {
result = new HashMap();
}
return result;
}
private Map prepareVisualOptions(Object value, AbstractPopupPanel panel) {
if (null == value) {
return new HashMap();
} else if (value instanceof Map) {
return (Map) value;
} else if (value instanceof String) {
String s = (String) value;
if (!s.startsWith("{")) {
s = "{" + s + "}";
}
try {
return new HashMap(new JSONMap(s));
} catch (JSONException e) {
throw new FacesException(e);
}
} else {
throw new FacesException("Attribute visualOptions of component ["
+ panel.getClientId(FacesContext.getCurrentInstance())
+ "] must be instance of Map or String, but its type is " + value.getClass().getSimpleName());
}
}
protected String getLeftOrDefault(UIComponent component) {
String leftProperty = ((AbstractPopupPanel) component).getLeft();
if (leftProperty == null || leftProperty.length() == 0) {
leftProperty = DEFAULT_LEFT;
}
return leftProperty;
}
protected String getTopOrDefault(UIComponent component) {
String topProperty = ((AbstractPopupPanel) component).getTop();
if (topProperty == null || topProperty.length() == 0) {
topProperty = DEFAULT_TOP;
}
return topProperty;
}
}