mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.ActionEvent;
|
||||
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.UIActionLink;
|
||||
import org.alfresco.web.ui.common.component.UIMenu;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author kevinr
|
||||
*/
|
||||
public class ActionLinkRenderer extends BaseRenderer
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ActionLinkRenderer.class);
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Renderer implementation
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void decode(FacesContext context, UIComponent component)
|
||||
{
|
||||
Map requestMap = context.getExternalContext().getRequestParameterMap();
|
||||
String fieldId = Utils.getActionHiddenFieldName(context, component);
|
||||
String value = (String)requestMap.get(fieldId);
|
||||
// we are clicked if the hidden field contained our client id
|
||||
if (value != null && value.equals(component.getClientId(context)))
|
||||
{
|
||||
// get all the params for this actionlink, see if any values have been set
|
||||
// on the request which match our params and set them into the component
|
||||
UIActionLink link = (UIActionLink)component;
|
||||
Map<String, String> destParams = link.getParameterMap();
|
||||
destParams.clear();
|
||||
Map<String, String> actionParams = getParameterMap(link);
|
||||
if (actionParams != null)
|
||||
{
|
||||
for (String name : actionParams.keySet())
|
||||
{
|
||||
String paramValue = (String)requestMap.get(name);
|
||||
destParams.put(name, paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
ActionEvent event = new ActionEvent(component);
|
||||
component.queueEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeEnd(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
// always check for this flag - as per the spec
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
Writer out = context.getResponseWriter();
|
||||
|
||||
UIActionLink link = (UIActionLink)component;
|
||||
|
||||
if (isInMenu(link) == true)
|
||||
{
|
||||
// render as menu item
|
||||
out.write( renderMenuAction(context, link) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// render as action link
|
||||
out.write( renderActionLink(context, link) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render ActionLink as plain link and image
|
||||
*
|
||||
* @param context
|
||||
* @param link
|
||||
*
|
||||
* @return action link HTML
|
||||
*/
|
||||
private String renderActionLink(FacesContext context, UIActionLink link)
|
||||
{
|
||||
Map attrs = link.getAttributes();
|
||||
StringBuilder linkBuf = new StringBuilder(256);
|
||||
|
||||
if (link.getHref() == null)
|
||||
{
|
||||
linkBuf.append("<a href='#' onclick=\"");
|
||||
|
||||
// if we have an overriden onclick add that
|
||||
if (link.getOnclick() != null)
|
||||
{
|
||||
linkBuf.append(link.getOnclick());
|
||||
}
|
||||
else
|
||||
{
|
||||
// generate JavaScript to set a hidden form field and submit
|
||||
// a form which request attributes that we can decode
|
||||
linkBuf.append(Utils.generateFormSubmit(context, link, Utils.getActionHiddenFieldName(context, link), link.getClientId(context), getParameterMap(link)));
|
||||
}
|
||||
|
||||
linkBuf.append('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
String href = link.getHref();
|
||||
if (href.startsWith("http") == false && href.startsWith("file") == false)
|
||||
{
|
||||
href = context.getExternalContext().getRequestContextPath() + href;
|
||||
}
|
||||
linkBuf.append("<a href=\"")
|
||||
.append(href)
|
||||
.append('"');
|
||||
|
||||
// output href 'target' attribute if supplied
|
||||
if (link.getTarget() != null)
|
||||
{
|
||||
linkBuf.append(" target=\"")
|
||||
.append(link.getTarget())
|
||||
.append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs.get("style") != null)
|
||||
{
|
||||
linkBuf.append(" style=\"")
|
||||
.append(attrs.get("style"))
|
||||
.append('"');
|
||||
}
|
||||
if (attrs.get("styleClass") != null)
|
||||
{
|
||||
linkBuf.append(" class=")
|
||||
.append(attrs.get("styleClass"));
|
||||
}
|
||||
if (attrs.get("tooltip") != null)
|
||||
{
|
||||
linkBuf.append(" title=\"")
|
||||
.append(Utils.encode((String)attrs.get("tooltip")))
|
||||
.append('"');
|
||||
}
|
||||
linkBuf.append('>');
|
||||
|
||||
StringBuilder buf = new StringBuilder(350);
|
||||
if (link.getImage() != null)
|
||||
{
|
||||
int padding = link.getPadding();
|
||||
if (padding != 0)
|
||||
{
|
||||
// TODO: make this width value a property!
|
||||
buf.append("<table cellspacing=0 cellpadding=0><tr><td width=16>");
|
||||
}
|
||||
|
||||
if (link.getShowLink() == false)
|
||||
{
|
||||
buf.append(linkBuf.toString());
|
||||
}
|
||||
|
||||
// TODO: allow configuring of alignment attribute
|
||||
buf.append(Utils.buildImageTag(context, link.getImage(), (String)link.getValue(), "absmiddle"));
|
||||
|
||||
if (link.getShowLink() == false)
|
||||
{
|
||||
buf.append("</a>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (padding != 0)
|
||||
{
|
||||
buf.append("</td><td style=\"padding:")
|
||||
.append(padding)
|
||||
.append("px\">");
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: add horizontal spacing as component property
|
||||
buf.append("<span style='padding-left:2px");
|
||||
|
||||
// text next to an image may need alignment
|
||||
if (attrs.get("verticalAlign") != null)
|
||||
{
|
||||
buf.append(";vertical-align:")
|
||||
.append(attrs.get("verticalAlign"));
|
||||
}
|
||||
|
||||
buf.append("'>");
|
||||
}
|
||||
|
||||
buf.append(linkBuf.toString());
|
||||
buf.append(Utils.encode(link.getValue().toString()));
|
||||
buf.append("</a>");
|
||||
|
||||
if (padding == 0)
|
||||
{
|
||||
buf.append("</span>");
|
||||
}
|
||||
}
|
||||
|
||||
if (padding != 0)
|
||||
{
|
||||
buf.append("</td></tr></table>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append(linkBuf.toString());
|
||||
buf.append(Utils.encode(link.getValue().toString()));
|
||||
buf.append("</a>");
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render ActionLink as menu image and item link
|
||||
*
|
||||
* @param context
|
||||
* @param link
|
||||
*
|
||||
* @return action link HTML
|
||||
*/
|
||||
private String renderMenuAction(FacesContext context, UIActionLink link)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
|
||||
buf.append("<tr><td>");
|
||||
|
||||
// render image cell first for a menu
|
||||
if (link.getImage() != null)
|
||||
{
|
||||
buf.append(Utils.buildImageTag(context, link.getImage(), (String)link.getValue()));
|
||||
}
|
||||
|
||||
buf.append("</td><td");
|
||||
int padding = link.getPadding();
|
||||
if (padding != 0)
|
||||
{
|
||||
buf.append(" style=\"padding:")
|
||||
.append(padding)
|
||||
.append("px\"");
|
||||
}
|
||||
buf.append(">");
|
||||
|
||||
Map attrs = link.getAttributes();
|
||||
|
||||
// render text link cell for the menu
|
||||
if (attrs.get("href") == null)
|
||||
{
|
||||
buf.append("<a href='#' onclick=\"");
|
||||
buf.append(Utils.generateFormSubmit(context, link, Utils.getActionHiddenFieldName(context, link), link.getClientId(context), getParameterMap(link)));
|
||||
buf.append('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
String href = (String)attrs.get("href");
|
||||
if (href.startsWith("http") == false)
|
||||
{
|
||||
href = context.getExternalContext().getRequestContextPath() + href;
|
||||
}
|
||||
buf.append("<a href=\"")
|
||||
.append(href)
|
||||
.append('"');
|
||||
|
||||
// output href 'target' attribute if supplied
|
||||
if (link.getTarget() != null)
|
||||
{
|
||||
buf.append(" target=\"")
|
||||
.append(link.getTarget())
|
||||
.append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs.get("style") != null)
|
||||
{
|
||||
buf.append(" style=\"")
|
||||
.append(attrs.get("style"))
|
||||
.append('"');
|
||||
}
|
||||
if (attrs.get("styleClass") != null)
|
||||
{
|
||||
buf.append(" class=")
|
||||
.append(attrs.get("styleClass"));
|
||||
}
|
||||
buf.append('>');
|
||||
buf.append(Utils.encode(link.getValue().toString()));
|
||||
buf.append("</a>");
|
||||
|
||||
buf.append("</td></tr>");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Private helpers
|
||||
|
||||
/**
|
||||
* Return true if the action link is present within a UIMenu component container
|
||||
*
|
||||
* @param link The ActionLink to test
|
||||
*
|
||||
* @return true if the action link is present within a UIMenu component
|
||||
*/
|
||||
private static boolean isInMenu(UIActionLink link)
|
||||
{
|
||||
UIComponent parent = link.getParent();
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent instanceof UIMenu)
|
||||
{
|
||||
break;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return (parent != null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIParameter;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.render.Renderer;
|
||||
|
||||
/**
|
||||
* Base renderer class. Contains helper methods to assist most renderers.
|
||||
*
|
||||
* @author kevinr
|
||||
*/
|
||||
public abstract class BaseRenderer extends Renderer
|
||||
{
|
||||
/**
|
||||
* Helper to output an attribute to the output stream
|
||||
*
|
||||
* @param out ResponseWriter
|
||||
* @param attr attribute value object (cannot be null)
|
||||
* @param mapping mapping to output as e.g. style="..."
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
protected static void outputAttribute(ResponseWriter out, Object attr, String mapping)
|
||||
throws IOException
|
||||
{
|
||||
if (attr != null)
|
||||
{
|
||||
out.write(' ');
|
||||
out.write(mapping);
|
||||
out.write("=\"");
|
||||
out.write(attr.toString());
|
||||
out.write('"');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the given context and component are not null. This method
|
||||
* should be called by all renderer methods that are given these parameters.
|
||||
*
|
||||
* @param ctx Faces context
|
||||
* @param component The component
|
||||
*/
|
||||
protected static void assertParmeters(FacesContext ctx, UIComponent component)
|
||||
{
|
||||
if (ctx == null)
|
||||
{
|
||||
throw new IllegalStateException("context can not be null");
|
||||
}
|
||||
|
||||
if (component == null)
|
||||
{
|
||||
throw new IllegalStateException("component can not be null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map of name/value pairs for any child UIParameter components.
|
||||
*
|
||||
* @param component to find UIParameter child values for
|
||||
*
|
||||
* @return a Map of name/value pairs or null if none found
|
||||
*/
|
||||
protected static Map<String, String> getParameterMap(UIComponent component)
|
||||
{
|
||||
Map<String, String> params = null;
|
||||
|
||||
if (component.getChildCount() != 0)
|
||||
{
|
||||
params = new HashMap<String, String>(3, 1.0f);
|
||||
for (Iterator i=component.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIParameter)
|
||||
{
|
||||
UIParameter param = (UIParameter)child;
|
||||
params.put(param.getName(), (String)param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
}
|
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
|
||||
import org.alfresco.web.ui.common.component.UIBreadcrumb;
|
||||
|
||||
/**
|
||||
* Renderer class for the UIBreadcrumb component
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class BreadcrumbRenderer extends BaseRenderer
|
||||
{
|
||||
// ------------------------------------------------------------------------------
|
||||
// Renderer implementation
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void decode(FacesContext context, UIComponent component)
|
||||
{
|
||||
Map requestMap = context.getExternalContext().getRequestParameterMap();
|
||||
String fieldId = getHiddenFieldName(context, component);
|
||||
String value = (String)requestMap.get(fieldId);
|
||||
if (value != null && value.length() != 0)
|
||||
{
|
||||
// create a breadcrumb specific action event if we were clicked
|
||||
int selectedIndex = Integer.parseInt(value);
|
||||
UIBreadcrumb.BreadcrumbEvent event = new UIBreadcrumb.BreadcrumbEvent(component, selectedIndex);
|
||||
component.queueEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
// always check for this flag - as per the spec
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
Writer out = context.getResponseWriter();
|
||||
|
||||
UIBreadcrumb breadcrumb = (UIBreadcrumb)component;
|
||||
// get the List of IBreadcrumbHandler elements from the component
|
||||
List<IBreadcrumbHandler> elements = (List)breadcrumb.getValue();
|
||||
|
||||
boolean first = true;
|
||||
for (int index=0; index<elements.size(); index++)
|
||||
{
|
||||
IBreadcrumbHandler element = elements.get(index);
|
||||
|
||||
// handle not optionally hiding the root part
|
||||
if (index != 0 || breadcrumb.getShowRoot() == true)
|
||||
{
|
||||
out.write( renderBreadcrumb(context, breadcrumb, element.toString(), index, first) );
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Private helpers
|
||||
|
||||
/**
|
||||
* Render a single breadcrumb element as a link on the page
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param bc The current UIBreadcrumb component
|
||||
* @param element Text for the breadcrumb element
|
||||
* @param index The index of the element into the original breadcrumb path
|
||||
* @param first True is this is the root element
|
||||
*
|
||||
* @return HTML for this breadcrumb element
|
||||
*/
|
||||
private String renderBreadcrumb(FacesContext context, UIBreadcrumb bc, String element, int index, boolean first)
|
||||
{
|
||||
// render breadcrumb link element
|
||||
StringBuilder buf = new StringBuilder(200);
|
||||
|
||||
// output separator
|
||||
if (first == false)
|
||||
{
|
||||
buf.append(' ')
|
||||
.append(bc.getSeparator())
|
||||
.append(' ');
|
||||
}
|
||||
|
||||
// generate JavaScript to set a hidden form field and submit
|
||||
// a form which request attributes that we can decode
|
||||
buf.append("<a href='#' onclick=\"");
|
||||
buf.append(Utils.generateFormSubmit(context, bc, getHiddenFieldName(context, bc), Integer.toString(index)));
|
||||
buf.append('"');
|
||||
|
||||
if (bc.getAttributes().get("style") != null)
|
||||
{
|
||||
buf.append(" style=\"")
|
||||
.append(bc.getAttributes().get("style"))
|
||||
.append('"');
|
||||
}
|
||||
if (bc.getAttributes().get("styleClass") != null)
|
||||
{
|
||||
buf.append(" class=")
|
||||
.append(bc.getAttributes().get("styleClass"));
|
||||
}
|
||||
if (bc.getAttributes().get("tooltip") != null)
|
||||
{
|
||||
buf.append(" title=\"")
|
||||
.append(bc.getAttributes().get("tooltip"))
|
||||
.append('"');
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
// output path element text
|
||||
// TODO: optionally crop text length with ellipses - use title attribute for all
|
||||
buf.append(Utils.encode(element));
|
||||
|
||||
// close tag
|
||||
buf.append("</a>");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hidden field name for this breadcrumb.
|
||||
* Assume there will not be many breadcrumbs on a page - therefore a hidden field
|
||||
* for each is not a significant issue.
|
||||
*
|
||||
* @return hidden field name
|
||||
*/
|
||||
private static String getHiddenFieldName(FacesContext context, UIComponent component)
|
||||
{
|
||||
return component.getClientId(context);
|
||||
}
|
||||
}
|
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.EditableValueHolder;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.ValueHolder;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.convert.ConverterException;
|
||||
import javax.faces.model.SelectItem;
|
||||
|
||||
import org.alfresco.web.app.Application;
|
||||
|
||||
/**
|
||||
* @author kevinr
|
||||
*
|
||||
* Example of a custom JSF renderer. This demonstrates how to encode/decode a set
|
||||
* of input field params that we use to generate a Date object. This object is held
|
||||
* in our component and the renderer will output it to the page.
|
||||
*/
|
||||
public class DatePickerRenderer extends BaseRenderer
|
||||
{
|
||||
private static final String FIELD_YEAR = "_year";
|
||||
private static final String FIELD_MONTH = "_month";
|
||||
private static final String FIELD_DAY = "_day";
|
||||
private static final String FIELD_HOUR = "_hour";
|
||||
private static final String FIELD_MINUTE = "_minute";
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*
|
||||
* The decode method takes the parameters from the external requests, finds the
|
||||
* ones revelant to this component and decodes the results into an object known
|
||||
* as the "submitted value".
|
||||
*/
|
||||
public void decode(FacesContext context, UIComponent component)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: should check for disabled/readonly here - no need to decode
|
||||
String clientId = component.getClientId(context);
|
||||
Map params = context.getExternalContext().getRequestParameterMap();
|
||||
String year = (String)params.get(clientId + FIELD_YEAR);
|
||||
if (year != null)
|
||||
{
|
||||
// found data for our component
|
||||
String month = (String)params.get(clientId + FIELD_MONTH);
|
||||
String day = (String)params.get(clientId + FIELD_DAY);
|
||||
String hour = (String)params.get(clientId + FIELD_HOUR);
|
||||
String minute = (String)params.get(clientId + FIELD_MINUTE);
|
||||
|
||||
// we encode the values needed for the component as we see fit
|
||||
int[] parts = new int[5];
|
||||
parts[0] = Integer.parseInt(year);
|
||||
parts[1] = Integer.parseInt(month);
|
||||
parts[2] = Integer.parseInt(day);
|
||||
parts[3] = Integer.parseInt(hour);
|
||||
parts[4] = Integer.parseInt(minute);
|
||||
|
||||
// save the data in an object for our component as the "EditableValueHolder"
|
||||
// all UI Input Components support this interface for the submitted value
|
||||
((EditableValueHolder)component).setSubmittedValue(parts);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
// just ignore the error and skip the update of the property
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#getConvertedValue(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
|
||||
*
|
||||
* In the Process Validations phase, this method is called to convert the values
|
||||
* to the datatype as required by the component.
|
||||
*
|
||||
* It is possible at this point that a custom Converter instance will be used - this
|
||||
* is why we have not yet converted the values to a data type.
|
||||
*/
|
||||
public Object getConvertedValue(FacesContext context, UIComponent component, Object val) throws ConverterException
|
||||
{
|
||||
int[] parts = (int[])val;
|
||||
Calendar date = new GregorianCalendar(parts[0], parts[1], parts[2], parts[3], parts[4]);
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*
|
||||
* All rendering logic for this component is implemented here. A renderer for an
|
||||
* input component must render the submitted value if it's set, and use the local
|
||||
* value only if there is no submitted value.
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component)
|
||||
throws IOException
|
||||
{
|
||||
// always check for this flag - as per the spec
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
Date date = null;
|
||||
|
||||
// this is part of the spec:
|
||||
// first you attempt to build the date from the submitted value
|
||||
int[] submittedValue = (int[])((EditableValueHolder)component).getSubmittedValue();
|
||||
if (submittedValue != null)
|
||||
{
|
||||
date = (Date)getConvertedValue(context, component, submittedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// second if no submitted value is found, default to the current value
|
||||
Object value = ((ValueHolder)component).getValue();
|
||||
// finally check for null value and create default if needed
|
||||
date = value instanceof Date ? (Date)value : new Date();
|
||||
}
|
||||
|
||||
// get the attributes from the component we need for rendering
|
||||
int nStartYear = 1990;
|
||||
Integer startYear = (Integer)component.getAttributes().get("startYear");
|
||||
if (startYear != null)
|
||||
{
|
||||
nStartYear = startYear.intValue();
|
||||
}
|
||||
|
||||
int nYearCount = 10;
|
||||
Integer yearCount = (Integer)component.getAttributes().get("yearCount");
|
||||
if (yearCount != null)
|
||||
{
|
||||
nYearCount = yearCount.intValue();
|
||||
}
|
||||
|
||||
// now we render the output for our component
|
||||
// we create 3 drop-down menus for day, month and year and
|
||||
// two text fields for the hour and minute
|
||||
String clientId = component.getClientId(context);
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// note that we build a client id for our form elements that we are then
|
||||
// able to decode() as above.
|
||||
Calendar calendar = new GregorianCalendar();
|
||||
calendar.setTime(date);
|
||||
renderMenu(out, component, getDays(), calendar.get(Calendar.DAY_OF_MONTH), clientId + FIELD_DAY);
|
||||
renderMenu(out, component, getMonths(), calendar.get(Calendar.MONTH), clientId + FIELD_MONTH);
|
||||
renderMenu(out, component, getYears(nStartYear, nYearCount), calendar.get(Calendar.YEAR), clientId + FIELD_YEAR);
|
||||
|
||||
// make sure we have a flag to determine whether to show the time
|
||||
Boolean showTime = (Boolean)component.getAttributes().get("showTime");
|
||||
if (showTime == null)
|
||||
{
|
||||
showTime = Boolean.FALSE;
|
||||
}
|
||||
|
||||
out.write(" ");
|
||||
renderTimeElement(out, component, calendar.get(Calendar.HOUR_OF_DAY), clientId + FIELD_HOUR, showTime.booleanValue());
|
||||
if (showTime.booleanValue())
|
||||
{
|
||||
out.write(" : ");
|
||||
}
|
||||
renderTimeElement(out, component, calendar.get(Calendar.MINUTE), clientId + FIELD_MINUTE, showTime.booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a drop-down menu to represent an element for the date picker.
|
||||
*
|
||||
* @param out Response Writer to output too
|
||||
* @param component The compatible component
|
||||
* @param items To display in the drop-down list
|
||||
* @param selected Which item index is selected
|
||||
* @param clientId Client Id to use
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void renderMenu(ResponseWriter out, UIComponent component, List items,
|
||||
int selected, String clientId)
|
||||
throws IOException
|
||||
{
|
||||
out.write("<select");
|
||||
outputAttribute(out, clientId, "name");
|
||||
|
||||
if (component.getAttributes().get("styleClass") != null)
|
||||
{
|
||||
outputAttribute(out, component.getAttributes().get("styleClass"), "class");
|
||||
}
|
||||
if (component.getAttributes().get("style") != null)
|
||||
{
|
||||
outputAttribute(out, component.getAttributes().get("style"), "style");
|
||||
}
|
||||
if (component.getAttributes().get("disabled") != null)
|
||||
{
|
||||
outputAttribute(out, component.getAttributes().get("disabled"), "disabled");
|
||||
}
|
||||
out.write(">");
|
||||
|
||||
for (Iterator i=items.iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
SelectItem item = (SelectItem)i.next();
|
||||
Integer value = (Integer)item.getValue();
|
||||
out.write("<option");
|
||||
outputAttribute(out, value, "value");
|
||||
|
||||
// show selected value
|
||||
if (value.intValue() == selected)
|
||||
{
|
||||
outputAttribute(out, "selected", "selected");
|
||||
}
|
||||
out.write(">");
|
||||
out.write(item.getLabel());
|
||||
out.write("</option>");
|
||||
}
|
||||
out.write("</select>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders either the hour or minute field
|
||||
*
|
||||
* @param out The ResponseWriter
|
||||
* @param currentValue The value of the hour or minute
|
||||
* @param clientId The id to use for the field
|
||||
*/
|
||||
private void renderTimeElement(ResponseWriter out, UIComponent component,
|
||||
int currentValue, String clientId, boolean showTime) throws IOException
|
||||
{
|
||||
out.write("<input");
|
||||
outputAttribute(out, clientId, "name");
|
||||
|
||||
if (showTime)
|
||||
{
|
||||
out.write(" type='text' size='1' maxlength='2'");
|
||||
|
||||
if (component.getAttributes().get("disabled") != null)
|
||||
{
|
||||
outputAttribute(out, component.getAttributes().get("disabled"), "disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write(" type='hidden'");
|
||||
}
|
||||
|
||||
// make sure there are always 2 digits
|
||||
String strValue = Integer.toString(currentValue);
|
||||
if (strValue.length() == 1)
|
||||
{
|
||||
strValue = "0" + strValue;
|
||||
}
|
||||
|
||||
outputAttribute(out, strValue, "value");
|
||||
out.write("/>");
|
||||
}
|
||||
|
||||
private List getYears(int startYear, int yearCount)
|
||||
{
|
||||
List<SelectItem> years = new ArrayList<SelectItem>();
|
||||
for (int i=startYear; i<startYear + yearCount; i++)
|
||||
{
|
||||
Integer year = Integer.valueOf(i);
|
||||
years.add(new SelectItem(year, year.toString()));
|
||||
}
|
||||
return years;
|
||||
}
|
||||
|
||||
private List getMonths()
|
||||
{
|
||||
// get names of the months for default locale
|
||||
Locale locale = Application.getLanguage(FacesContext.getCurrentInstance());
|
||||
if (locale == null)
|
||||
{
|
||||
locale = locale.getDefault();
|
||||
}
|
||||
DateFormatSymbols dfs = new DateFormatSymbols(locale);
|
||||
String[] names = dfs.getMonths();
|
||||
List<SelectItem> months = new ArrayList<SelectItem>(12);
|
||||
for (int i=0; i<12; i++)
|
||||
{
|
||||
Integer key = Integer.valueOf(i);
|
||||
months.add(new SelectItem(key, names[i]));
|
||||
}
|
||||
return months;
|
||||
}
|
||||
|
||||
private List getDays()
|
||||
{
|
||||
List<SelectItem> days = new ArrayList<SelectItem>(31);
|
||||
for (int i=1; i<32; i++)
|
||||
{
|
||||
Integer day = Integer.valueOf(i);
|
||||
days.add(new SelectItem(day, day.toString()));
|
||||
}
|
||||
return days;
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.el.ValueBinding;
|
||||
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.ui.common.PanelGenerator;
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
|
||||
/**
|
||||
* Renderer that displays any errors that occurred in the previous lifecylce
|
||||
* processing within a gradient panel
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class ErrorsRenderer extends BaseRenderer
|
||||
{
|
||||
private static final String DEFAULT_MESSAGE = "wizard_errors";
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Iterator messages = context.getMessages();
|
||||
if (messages.hasNext())
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
String contextPath = context.getExternalContext().getRequestContextPath();
|
||||
String styleClass = (String)component.getAttributes().get("styleClass");
|
||||
String message = (String)component.getAttributes().get("message");
|
||||
|
||||
if (message == null)
|
||||
{
|
||||
// because we are using the standard messages component value binding
|
||||
// would not be handled for the message attribute so do it here
|
||||
ValueBinding vb = component.getValueBinding("message");
|
||||
if (vb != null)
|
||||
{
|
||||
message = (String)vb.getValue(context);
|
||||
}
|
||||
|
||||
if (message == null)
|
||||
{
|
||||
message = Application.getMessage(context, DEFAULT_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
PanelGenerator.generatePanelStart(out, contextPath, "yellowInner", "#ffffcc");
|
||||
|
||||
out.write("\n<div");
|
||||
if (styleClass != null)
|
||||
{
|
||||
outputAttribute(out, styleClass, "class");
|
||||
}
|
||||
out.write(">");
|
||||
out.write("<img src='");
|
||||
out.write(contextPath);
|
||||
out.write("/images/icons/info_icon.gif' alt='Error' align='absmiddle'/> ");
|
||||
out.write(Utils.encode(message));
|
||||
out.write("\n<ul style='margin:2px;'>");
|
||||
|
||||
while (messages.hasNext())
|
||||
{
|
||||
FacesMessage fm = (FacesMessage)messages.next();
|
||||
out.write("<li>");
|
||||
out.write(Utils.encode(fm.getSummary()));
|
||||
out.write("</li>\n");
|
||||
}
|
||||
|
||||
out.write("</ul></div>\n");
|
||||
|
||||
PanelGenerator.generatePanelEnd(out, contextPath, "yellowInner");
|
||||
|
||||
// TODO: Expose this as a configurable attribute i.e. padding at bottom
|
||||
out.write("<div style='padding:2px;'></div>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#getRendersChildren()
|
||||
*/
|
||||
public boolean getRendersChildren()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.UIImagePicker;
|
||||
import org.alfresco.web.ui.common.component.UIListItem;
|
||||
import org.alfresco.web.ui.common.component.UIListItems;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Renderer for the image picker component that outputs the list of images
|
||||
* as radio buttons
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class ImagePickerRadioRenderer extends BaseRenderer
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ImagePickerRadioRenderer.class);
|
||||
|
||||
private int columns;
|
||||
private int position;
|
||||
private boolean open;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Renderer implemenation
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void decode(FacesContext context, UIComponent component)
|
||||
{
|
||||
if (Utils.isComponentDisabledOrReadOnly(component))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String clientId = component.getClientId(context);
|
||||
Map paramsMap = context.getExternalContext().getRequestParameterMap();
|
||||
|
||||
String submittedValue = (String)paramsMap.get(clientId);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Submitted value = " + submittedValue);
|
||||
|
||||
((UIInput)component).setSubmittedValue(submittedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// setup counters
|
||||
this.columns = 1;
|
||||
this.position = 0;
|
||||
this.open = false;
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
UIImagePicker imagePicker = (UIImagePicker)component;
|
||||
|
||||
Map attrs = imagePicker.getAttributes();
|
||||
out.write("<table cellpadding='0'");
|
||||
outputAttribute(out, attrs.get("spacing"), "cellspacing");
|
||||
outputAttribute(out, attrs.get("styleClass"), "class");
|
||||
outputAttribute(out, attrs.get("style"), "style");
|
||||
out.write(">\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeChildren(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UIImagePicker imagePicker = (UIImagePicker)component;
|
||||
Map attrs = imagePicker.getAttributes();
|
||||
|
||||
Integer cols = (Integer)attrs.get("columns");
|
||||
if (cols != null && cols instanceof Integer)
|
||||
{
|
||||
this.columns = cols.intValue();
|
||||
}
|
||||
|
||||
// retrieve the onclick handler, if there is one
|
||||
String onclick = (String)attrs.get("onclick");
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// get the child components
|
||||
for (Iterator i = imagePicker.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIListItems)
|
||||
{
|
||||
// get the value of the list items component and iterate
|
||||
// through it's collection
|
||||
Object listItems = ((UIListItems)child).getValue();
|
||||
if (listItems instanceof Collection)
|
||||
{
|
||||
Iterator iter = ((Collection)listItems).iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
UIListItem item = (UIListItem)iter.next();
|
||||
renderItem(context, out, imagePicker, item, onclick);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (child instanceof UIListItem && child.isRendered() == true)
|
||||
{
|
||||
// found a valid UIListItem child to render
|
||||
UIListItem item = (UIListItem)child;
|
||||
renderItem(context, out, imagePicker, item, onclick);
|
||||
}
|
||||
}
|
||||
|
||||
// if we are in the middle of a row, close it
|
||||
if (open)
|
||||
{
|
||||
out.write("</tr>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeEnd(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
out.write("</table>");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#getRendersChildren()
|
||||
*/
|
||||
public boolean getRendersChildren()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given item as a radio button selection choice
|
||||
*
|
||||
* @param context Faces context
|
||||
* @param out ReponseWriter to write output to
|
||||
* @param imagePicker The parent component
|
||||
* @param item The item to render
|
||||
* @param onclick The onClick JavaScript handler (may be null)
|
||||
*/
|
||||
private void renderItem(FacesContext context, ResponseWriter out,
|
||||
UIImagePicker imagePicker, UIListItem item, String onclick)
|
||||
throws IOException
|
||||
{
|
||||
String tooltip = (String)item.getAttributes().get("tooltip");
|
||||
|
||||
// if we are at the start of another row output "tr"
|
||||
if ((this.position % this.columns) == 0)
|
||||
{
|
||||
// if we are at the end of a row, close it
|
||||
if (this.open)
|
||||
{
|
||||
out.write("</tr>\n");
|
||||
this.open = false;
|
||||
}
|
||||
|
||||
out.write("<tr>");
|
||||
|
||||
// we have started the row
|
||||
this.open = true;
|
||||
}
|
||||
|
||||
// output the next "cell" i.e. a radio button, the image and optional label
|
||||
out.write("<td>");
|
||||
|
||||
out.write("<input type='radio' name='");
|
||||
out.write(imagePicker.getClientId(context));
|
||||
out.write("' id='");
|
||||
out.write(imagePicker.getClientId(context));
|
||||
out.write("' value='");
|
||||
// TODO: need to take into account values that may need to be converted,
|
||||
// for now presume a string is OK
|
||||
out.write(item.getValue().toString());
|
||||
out.write("'");
|
||||
|
||||
// determine whether this item should be selected
|
||||
Object currentValue = imagePicker.getSubmittedValue();
|
||||
if (currentValue == null)
|
||||
{
|
||||
currentValue = imagePicker.getValue();
|
||||
}
|
||||
|
||||
Object itemValue = item.getValue();
|
||||
if (itemValue != null && itemValue.equals(currentValue))
|
||||
{
|
||||
out.write(" checked='true'");
|
||||
}
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
out.write(" title='");
|
||||
out.write(Utils.encode(tooltip));
|
||||
out.write("'");
|
||||
}
|
||||
|
||||
if (onclick != null)
|
||||
{
|
||||
out.write(" onclick='");
|
||||
out.write(onclick);
|
||||
out.write("'");
|
||||
}
|
||||
|
||||
// if (item.isDisabled())
|
||||
// {
|
||||
// out.write(" disabled='true'");
|
||||
// }
|
||||
|
||||
out.write(">");
|
||||
out.write("</td><td align='center'>");
|
||||
|
||||
// get the image and make sure there is one!
|
||||
String image = (String)item.getAttributes().get("image");
|
||||
if (image == null)
|
||||
{
|
||||
throw new IllegalStateException("All child items must specify an image");
|
||||
}
|
||||
|
||||
out.write(Utils.buildImageTag(context, image, tooltip));
|
||||
|
||||
String label = (String)item.getAttributes().get("label");
|
||||
if (label != null && label.length() > 0)
|
||||
{
|
||||
out.write("<br/>");
|
||||
out.write(Utils.encode(label));
|
||||
}
|
||||
|
||||
out.write("</td>");
|
||||
|
||||
// we've finished the item so move the position on
|
||||
this.position++;
|
||||
}
|
||||
}
|
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.NamingContainer;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIForm;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.UIListItem;
|
||||
import org.alfresco.web.ui.common.component.UIModeList;
|
||||
|
||||
/**
|
||||
* @author kevinr
|
||||
*/
|
||||
public class ModeListRenderer extends BaseRenderer
|
||||
{
|
||||
// ------------------------------------------------------------------------------
|
||||
// Renderer implemenation
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void decode(FacesContext context, UIComponent component)
|
||||
{
|
||||
Map requestMap = context.getExternalContext().getRequestParameterMap();
|
||||
String fieldId = getHiddenFieldName(context, component);
|
||||
String value = (String)requestMap.get(fieldId);
|
||||
|
||||
// we encoded the value to start with our Id
|
||||
if (value != null && value.startsWith(component.getClientId(context) + NamingContainer.SEPARATOR_CHAR))
|
||||
{
|
||||
// found a new selected value for this ModeList
|
||||
// queue an event to represent the change
|
||||
// TODO: NOTE: The value object is passed in as a String here - is this a problem?
|
||||
// As the 'value' field for a ModeListItem can contain Object...
|
||||
Object selectedValue = value.substring(component.getClientId(context).length() + 1);
|
||||
UIModeList.ModeListItemSelectedEvent event = new UIModeList.ModeListItemSelectedEvent(component, selectedValue);
|
||||
component.queueEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UIModeList list = (UIModeList)component;
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// start outer table container the list items
|
||||
Map attrs = list.getAttributes();
|
||||
out.write("<table cellspacing=1 cellpadding=0");
|
||||
outputAttribute(out, attrs.get("styleClass"), "class");
|
||||
outputAttribute(out, attrs.get("style"), "style");
|
||||
outputAttribute(out, attrs.get("width"), "width");
|
||||
out.write('>');
|
||||
|
||||
// horizontal rendering outputs a single row with each item as a column cell
|
||||
if (list.isHorizontal() == true)
|
||||
{
|
||||
out.write("<tr>");
|
||||
}
|
||||
|
||||
// output title row if present
|
||||
if (list.getLabel() != null)
|
||||
{
|
||||
// each row is an inner table with a single row and 2 columns
|
||||
// first column contains an icon if present, second column contains text
|
||||
if (list.isHorizontal() == false)
|
||||
{
|
||||
out.write("<tr>");
|
||||
}
|
||||
|
||||
out.write("<td><table cellpadding=0 width=100%");
|
||||
outputAttribute(out, attrs.get("itemSpacing"), "cellspacing");
|
||||
out.write("><tr>");
|
||||
|
||||
// output icon column
|
||||
if (list.getIconColumnWidth() != 0)
|
||||
{
|
||||
out.write("<td");
|
||||
outputAttribute(out, list.getIconColumnWidth(), "width");
|
||||
out.write("></td>");
|
||||
}
|
||||
|
||||
// output title label
|
||||
out.write("<td><span");
|
||||
outputAttribute(out, attrs.get("labelStyle"), "style");
|
||||
outputAttribute(out, attrs.get("labelStyleClass"), "class");
|
||||
out.write('>');
|
||||
out.write(Utils.encode(list.getLabel()));
|
||||
out.write("</span></td></tr></table></td>");
|
||||
|
||||
if (list.isHorizontal() == false)
|
||||
{
|
||||
out.write("</tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeChildren(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UIModeList list = (UIModeList)component;
|
||||
Map attrs = list.getAttributes();
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
String selectedImage = (String)attrs.get("selectedImage");
|
||||
|
||||
// get the child components
|
||||
for (Iterator i=list.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIListItem && child.isRendered() == true)
|
||||
{
|
||||
// found a valid UIListItem child to render
|
||||
UIListItem item = (UIListItem)child;
|
||||
|
||||
// each row is an inner table with a single row and 2 columns
|
||||
// first column contains an icon if present, second column contains text
|
||||
if (list.isHorizontal() == false)
|
||||
{
|
||||
out.write("<tr>");
|
||||
}
|
||||
|
||||
out.write("<td><table cellpadding=0 width=100%");
|
||||
outputAttribute(out, attrs.get("itemSpacing"), "cellspacing");
|
||||
|
||||
// if selected value render different style for the item
|
||||
boolean selected = item.getValue().equals(list.getValue());
|
||||
if (selected == true)
|
||||
{
|
||||
outputAttribute(out, attrs.get("selectedStyleClass"), "class");
|
||||
outputAttribute(out, attrs.get("selectedStyle"), "style");
|
||||
}
|
||||
else
|
||||
{
|
||||
outputAttribute(out, attrs.get("itemStyleClass"), "class");
|
||||
outputAttribute(out, attrs.get("itemStyle"), "style");
|
||||
}
|
||||
out.write("><tr>");
|
||||
|
||||
// output icon column
|
||||
if (list.getIconColumnWidth() != 0)
|
||||
{
|
||||
out.write("<td");
|
||||
outputAttribute(out, list.getIconColumnWidth(), "width");
|
||||
out.write(">");
|
||||
|
||||
// if the "selectedImage" property is set and this item is selected then show it
|
||||
if (selected == true && selectedImage != null)
|
||||
{
|
||||
out.write( Utils.buildImageTag(context, selectedImage, item.getTooltip()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// else show the image set for the individual item
|
||||
String image = (String)child.getAttributes().get("image");
|
||||
if (image != null)
|
||||
{
|
||||
out.write( Utils.buildImageTag(context, image, item.getTooltip()) );
|
||||
}
|
||||
}
|
||||
|
||||
out.write("</td>");
|
||||
}
|
||||
|
||||
// output item link
|
||||
out.write("<td>");
|
||||
if (!list.isDisabled() && !item.isDisabled())
|
||||
{
|
||||
out.write("<a href='#' onclick=\"");
|
||||
// generate javascript to submit the value of the child component
|
||||
String value = list.getClientId(context) + NamingContainer.SEPARATOR_CHAR + (String)child.getAttributes().get("value");
|
||||
out.write(Utils.generateFormSubmit(context, list, getHiddenFieldName(context, list), value));
|
||||
out.write('"');
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write("<span");
|
||||
outputAttribute(out, attrs.get("disabledStyleClass"), "class");
|
||||
outputAttribute(out, attrs.get("disabledStyle"), "style");
|
||||
}
|
||||
|
||||
// render style for the item link
|
||||
if (item.getValue().equals(list.getValue()))
|
||||
{
|
||||
outputAttribute(out, attrs.get("selectedLinkStyleClass"), "class");
|
||||
outputAttribute(out, attrs.get("selectedLinkStyle"), "style");
|
||||
}
|
||||
else
|
||||
{
|
||||
outputAttribute(out, attrs.get("itemLinkStyleClass"), "class");
|
||||
outputAttribute(out, attrs.get("itemLinkStyle"), "style");
|
||||
}
|
||||
|
||||
outputAttribute(out, child.getAttributes().get("tooltip"), "title");
|
||||
out.write('>');
|
||||
out.write(Utils.encode(item.getLabel()));
|
||||
if (!list.isDisabled() && !item.isDisabled())
|
||||
{
|
||||
out.write("</a>");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write("</span>");
|
||||
}
|
||||
out.write("</td></tr></table></td>");
|
||||
|
||||
if (list.isHorizontal() == false)
|
||||
{
|
||||
out.write("</tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeEnd(FacesContext context, UIComponent component) throws IOException
|
||||
{
|
||||
if (component.isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// end outer table
|
||||
if (((UIModeList)component).isHorizontal() == true)
|
||||
{
|
||||
out.write("</tr>");
|
||||
}
|
||||
out.write("</table>");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#getRendersChildren()
|
||||
*/
|
||||
public boolean getRendersChildren()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use a hidden field name based on the parent form component Id and
|
||||
* the string "modelist" to give a hidden field name that can be shared by all
|
||||
* ModeList components within a single UIForm component.
|
||||
*
|
||||
* @return hidden field name
|
||||
*/
|
||||
private static String getHiddenFieldName(FacesContext context, UIComponent component)
|
||||
{
|
||||
UIForm form = Utils.getParentForm(context, component);
|
||||
return form.getClientId(context) + NamingContainer.SEPARATOR_CHAR + "modelist";
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer.data;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import org.alfresco.web.ui.common.component.data.UIColumn;
|
||||
import org.alfresco.web.ui.common.component.data.UIRichList;
|
||||
|
||||
/**
|
||||
* Contract for implementations capable of rendering the columns for a Rich List
|
||||
* component.
|
||||
*
|
||||
* @author kevinr
|
||||
*/
|
||||
public interface IRichListRenderer
|
||||
{
|
||||
/**
|
||||
* Callback executed by the RichList component to render any adornments before
|
||||
* the main list rows are rendered. This is generally used to output header items.
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param richList The parent RichList component
|
||||
* @param columns Array of columns to be shown
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void renderListBefore(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Callback executed by the RichList component once per row of data to be rendered.
|
||||
* The bean used as the current row data is provided, but generally rendering of the
|
||||
* column data will be performed by recursively encoding Column child components.
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param richList The parent RichList component
|
||||
* @param columns Array of columns to be shown
|
||||
* @param row The data bean for the current row
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void renderListRow(FacesContext context, UIRichList richList, UIColumn[] columns, Object row)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Callback executed by the RichList component to render any adornments after
|
||||
* the main list rows are rendered. This is generally used to output footer items.
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param richList The parent RichList component
|
||||
* @param columns Array of columns to be shown
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void renderListAfter(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Return the unique view mode identifier that this renderer is responsible for.
|
||||
*
|
||||
* @return Unique view mode identifier for this renderer e.g. "icons" or "details"
|
||||
*/
|
||||
public String getViewModeID();
|
||||
}
|
@@ -0,0 +1,735 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.common.renderer.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.data.UIColumn;
|
||||
import org.alfresco.web.ui.common.component.data.UIRichList;
|
||||
import org.alfresco.web.ui.common.renderer.BaseRenderer;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author kevinr
|
||||
*/
|
||||
public class RichListRenderer extends BaseRenderer
|
||||
{
|
||||
// ------------------------------------------------------------------------------
|
||||
// Renderer implemenation
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context, UIComponent component)
|
||||
throws IOException
|
||||
{
|
||||
// always check for this flag - as per the spec
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
Map attrs = component.getAttributes();
|
||||
out.write("<table cellspacing=0 cellpadding=0");
|
||||
outputAttribute(out, attrs.get("styleClass"), "class");
|
||||
outputAttribute(out, attrs.get("style"), "style");
|
||||
outputAttribute(out, attrs.get("width"), "width");
|
||||
out.write(">");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeChildren(FacesContext context, UIComponent component)
|
||||
throws IOException
|
||||
{
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
// the RichList component we are working with
|
||||
UIRichList richList = (UIRichList)component;
|
||||
|
||||
// prepare the component current row against the current page settings
|
||||
richList.bind();
|
||||
|
||||
// collect child column components so they can be passed to the renderer
|
||||
List<UIColumn> columnList = new ArrayList<UIColumn>(8);
|
||||
for (Iterator i=richList.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIColumn)
|
||||
{
|
||||
columnList.add((UIColumn)child);
|
||||
}
|
||||
}
|
||||
|
||||
UIColumn[] columns = new UIColumn[columnList.size()];
|
||||
columnList.toArray(columns);
|
||||
|
||||
// get the renderer instance
|
||||
IRichListRenderer renderer = (IRichListRenderer)richList.getViewRenderer();
|
||||
if (renderer == null)
|
||||
{
|
||||
throw new IllegalStateException("IRichListRenderer must be available in UIRichList!");
|
||||
}
|
||||
|
||||
// call render-before to output headers if required
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
out.write("<thead>");
|
||||
renderer.renderListBefore(context, richList, columns);
|
||||
out.write("</thead>");
|
||||
out.write("<tbody>");
|
||||
if (richList.isDataAvailable() == true)
|
||||
{
|
||||
while (richList.isDataAvailable() == true)
|
||||
{
|
||||
// render each row in turn
|
||||
renderer.renderListRow(context, richList, columns, richList.nextRow());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no items present, render the facet with the "no items found" message
|
||||
UIComponent emptyComponent = richList.getEmptyMessage();
|
||||
if (emptyComponent != null)
|
||||
{
|
||||
emptyComponent.encodeBegin(context);
|
||||
emptyComponent.encodeChildren(context);
|
||||
emptyComponent.encodeEnd(context);
|
||||
}
|
||||
}
|
||||
// call render-after to output footers if required
|
||||
renderer.renderListAfter(context, richList, columns);
|
||||
out.write("</tbody>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
|
||||
*/
|
||||
public void encodeEnd(FacesContext context, UIComponent component)
|
||||
throws IOException
|
||||
{
|
||||
// always check for this flag - as per the spec
|
||||
if (component.isRendered() == true)
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
out.write("</table>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.render.Renderer#getRendersChildren()
|
||||
*/
|
||||
public boolean getRendersChildren()
|
||||
{
|
||||
// we are responsible for rendering our child components
|
||||
// this renderer is a valid use of this mode - it can render the various
|
||||
// column descriptors as a number of different list view types e.g.
|
||||
// details, icons, list etc.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Inner classes
|
||||
|
||||
/**
|
||||
* Class to implement a Details view for the RichList component
|
||||
*
|
||||
* @author kevinr
|
||||
*/
|
||||
public static class DetailsViewRenderer implements IRichListRenderer
|
||||
{
|
||||
public static final String VIEWMODEID = "details";
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#getViewModeID()
|
||||
*/
|
||||
public String getViewModeID()
|
||||
{
|
||||
return VIEWMODEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListBefore(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListBefore(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// render column headers as labels
|
||||
out.write("<tr");
|
||||
outputAttribute(out, richList.getAttributes().get("headerStyleClass"), "class");
|
||||
out.write('>');
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
UIColumn column = columns[i];
|
||||
|
||||
if (column.isRendered() == true)
|
||||
{
|
||||
// render column header tag
|
||||
out.write("<th");
|
||||
outputAttribute(out, column.getAttributes().get("width"), "width");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
|
||||
// output the header facet if any
|
||||
UIComponent header = column.getHeader();
|
||||
if (header != null)
|
||||
{
|
||||
header.encodeBegin(context);
|
||||
header.encodeChildren(context);
|
||||
header.encodeEnd(context);
|
||||
}
|
||||
|
||||
// we don't render child controls for the header row
|
||||
out.write("</th>");
|
||||
}
|
||||
}
|
||||
out.write("</tr>");
|
||||
|
||||
this.rowIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListRow(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[], java.lang.Object)
|
||||
*/
|
||||
public void renderListRow(FacesContext context, UIRichList richList, UIColumn[] columns, Object row)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// output row or alt style row if set
|
||||
out.write("<tr");
|
||||
String rowStyle = (String)richList.getAttributes().get("rowStyleClass");
|
||||
String altStyle = (String)richList.getAttributes().get("altRowStyleClass");
|
||||
if (altStyle != null && (this.rowIndex++ & 1) == 1)
|
||||
{
|
||||
rowStyle = altStyle;
|
||||
}
|
||||
outputAttribute(out, rowStyle, "class");
|
||||
out.write('>');
|
||||
|
||||
// find the actions column if it exists
|
||||
UIColumn actionsColumn = null;
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
if (columns[i].isRendered() == true && columns[i].getActions() == true)
|
||||
{
|
||||
actionsColumn = columns[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// output each column in turn and render all children
|
||||
boolean renderedFirst = false;
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
UIColumn column = columns[i];
|
||||
|
||||
if (column.isRendered() == true)
|
||||
{
|
||||
out.write("<td");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
|
||||
// for details view, we show the small column icon for the first column
|
||||
if (renderedFirst == false)
|
||||
{
|
||||
UIComponent smallIcon = column.getSmallIcon();
|
||||
if (smallIcon != null)
|
||||
{
|
||||
smallIcon.encodeBegin(context);
|
||||
smallIcon.encodeChildren(context);
|
||||
smallIcon.encodeEnd(context);
|
||||
out.write(" ");
|
||||
}
|
||||
renderedFirst = true;
|
||||
}
|
||||
|
||||
if (column.getChildCount() != 0)
|
||||
{
|
||||
if (column == actionsColumn)
|
||||
{
|
||||
out.write("<nobr>");
|
||||
}
|
||||
|
||||
// allow child controls inside the columns to render themselves
|
||||
Utils.encodeRecursive(context, column);
|
||||
|
||||
if (column == actionsColumn)
|
||||
{
|
||||
out.write("</nobr>");
|
||||
}
|
||||
}
|
||||
|
||||
out.write("</td>");
|
||||
}
|
||||
}
|
||||
out.write("</tr>");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListAfter(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListAfter(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
out.write("<tr><td colspan=99 align=right>");
|
||||
for (Iterator i=richList.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
// output all remaining child components that are not UIColumn
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIColumn == false)
|
||||
{
|
||||
Utils.encodeRecursive(context, child);
|
||||
}
|
||||
}
|
||||
out.write("</td></tr>");
|
||||
}
|
||||
|
||||
private int rowIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class to implement a List view for the RichList component
|
||||
*
|
||||
* @author kevinr
|
||||
*/
|
||||
public static class ListViewRenderer implements IRichListRenderer
|
||||
{
|
||||
// maximum displayable textual lines within a single item cell
|
||||
private final static int MAX_DISPLAYABLE_LINES = 3;
|
||||
|
||||
private final static String END_ROW_SEPARATOR = "</tr><tr><td colspan=10><div style='padding:3px'></div></td></tr>";
|
||||
private final static String COLUMN_SPACER = "<td><div style='padding-left:8px'></div></td>";
|
||||
|
||||
public static final String VIEWMODEID = "list";
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#getViewModeID()
|
||||
*/
|
||||
public String getViewModeID()
|
||||
{
|
||||
return VIEWMODEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListBefore(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListBefore(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// render column headers as labels
|
||||
// TODO: add "showHeaders" to RichList to allow hiding of header facets for some view modes
|
||||
/*
|
||||
out.write("<tr");
|
||||
outputAttribute(out, richList.getAttributes().get("headerStyleClass"), "class");
|
||||
out.write('>');
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
UIColumn column = columns[i];
|
||||
|
||||
if (column.isRendered() == true)
|
||||
{
|
||||
out.write("<th");
|
||||
outputAttribute(out, column.getAttributes().get("width"), "width");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
|
||||
// output the header facet if any
|
||||
UIComponent header = column.getHeader();
|
||||
if (header != null)
|
||||
{
|
||||
header.encodeBegin(context);
|
||||
header.encodeChildren(context);
|
||||
header.encodeEnd(context);
|
||||
}
|
||||
}
|
||||
|
||||
// we don't render child controls for the header row
|
||||
out.write("</th>");
|
||||
}
|
||||
out.write("</tr>");
|
||||
*/
|
||||
|
||||
this.rowIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListRow(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[], java.lang.Object)
|
||||
*/
|
||||
public void renderListRow(FacesContext context, UIRichList richList, UIColumn[] columns, Object row) throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// start new row if we are on an even column in this view
|
||||
// we show 2 columns, left to right
|
||||
String rowStyle = (String)richList.getAttributes().get("rowStyleClass");
|
||||
if ((this.rowIndex & 1) == 0)
|
||||
{
|
||||
out.write("<tr");
|
||||
outputAttribute(out, rowStyle, "class");
|
||||
out.write('>');
|
||||
}
|
||||
|
||||
// find the actions column if it exists
|
||||
// and the primary column (which must exist)
|
||||
UIColumn primaryColumn = null;
|
||||
UIColumn actionsColumn = null;
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
if (columns[i].isRendered() == true)
|
||||
{
|
||||
if (columns[i].getPrimary() == true)
|
||||
{
|
||||
primaryColumn = columns[i];
|
||||
}
|
||||
else if (columns[i].getActions() == true)
|
||||
{
|
||||
actionsColumn = columns[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (primaryColumn == null)
|
||||
{
|
||||
logger.warn("No primary column found for RichList definition: " + richList.getId());
|
||||
}
|
||||
|
||||
// get the icon from the primary column
|
||||
out.write("<td width=50%><table cellspacing=0 cellpadding=2 border=0>");
|
||||
if (primaryColumn != null)
|
||||
{
|
||||
UIColumn column = primaryColumn;
|
||||
|
||||
if (column.isRendered() == true)
|
||||
{
|
||||
out.write("<tr><td rowspan=10");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
|
||||
// output the large icon for this column
|
||||
UIComponent icon = column.getLargeIcon();
|
||||
if (icon != null)
|
||||
{
|
||||
icon.encodeBegin(context);
|
||||
icon.encodeChildren(context);
|
||||
icon.encodeEnd(context);
|
||||
}
|
||||
out.write("</td>");
|
||||
|
||||
// start the next cell which contains the first column component
|
||||
out.write("<td width=100%");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
if (column.getChildCount() != 0)
|
||||
{
|
||||
// allow child controls inside the column to render themselves
|
||||
Utils.encodeRecursive(context, column);
|
||||
}
|
||||
out.write("</td>");
|
||||
|
||||
// output actions column if any
|
||||
if (actionsColumn != null)
|
||||
{
|
||||
out.write("<td");
|
||||
outputAttribute(out, actionsColumn.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, actionsColumn.getAttributes().get("styleClass"), "class");
|
||||
out.write("><nobr>");
|
||||
|
||||
if (actionsColumn.getChildCount() != 0)
|
||||
{
|
||||
// allow child controls inside the columns to render themselves
|
||||
Utils.encodeRecursive(context, actionsColumn);
|
||||
}
|
||||
out.write("</nobr></td>");
|
||||
}
|
||||
|
||||
out.write("</tr>");
|
||||
}
|
||||
}
|
||||
|
||||
// render remaining columns as lines of data up to a max display limit
|
||||
for (int i = 0; i < columns.length; i++)
|
||||
{
|
||||
UIColumn column = columns[i];
|
||||
|
||||
int count = 1;
|
||||
if (column.isRendered() == true && count < MAX_DISPLAYABLE_LINES &&
|
||||
column.getActions() == false && column.getPrimary() == false)
|
||||
{
|
||||
// output row or alt style row if set
|
||||
out.write("<tr valign=top");
|
||||
outputAttribute(out, rowStyle, "class");
|
||||
out.write("><td colspan=2"); // render into above actions column
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
if (column.getChildCount() != 0)
|
||||
{
|
||||
// allow child controls inside the columns to render themselves
|
||||
Utils.encodeRecursive(context, column);
|
||||
}
|
||||
// end this cell and end row
|
||||
out.write("</td></tr>");
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
out.write("</table></td>");
|
||||
|
||||
if ((this.rowIndex & 1) == 1)
|
||||
{
|
||||
// end row and output a blank padding row/div
|
||||
out.write(END_ROW_SEPARATOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write(COLUMN_SPACER);
|
||||
}
|
||||
|
||||
this.rowIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListAfter(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListAfter(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// finish last row if required (we used an open-ended column rendering algorithm)
|
||||
if ( ((this.rowIndex-1) & 1) != 1)
|
||||
{
|
||||
out.write(END_ROW_SEPARATOR);
|
||||
}
|
||||
|
||||
out.write("<tr><td colspan=99 align=right>");
|
||||
for (Iterator i=richList.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
// output all remaining child components that are not UIColumn
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIColumn == false)
|
||||
{
|
||||
Utils.encodeRecursive(context, child);
|
||||
}
|
||||
}
|
||||
out.write("</td></tr>");
|
||||
}
|
||||
|
||||
private int rowIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class to implement an Icon view for the RichList component
|
||||
*
|
||||
* @author kevinr
|
||||
*/
|
||||
public static class IconViewRenderer implements IRichListRenderer
|
||||
{
|
||||
// number of vertical columns to render before starting new row
|
||||
private final static int COLUMNS = 3;
|
||||
|
||||
// calculation for percentage of table row per column
|
||||
private final static String COLUMN_PERCENT = Integer.toString(100/COLUMNS) + "%";
|
||||
|
||||
// maximum displayable textual lines within a single item cell
|
||||
private final static int MAX_DISPLAYABLE_LINES = 3;
|
||||
|
||||
private final static String END_ROW_SEPARATOR = "</tr><tr><td colspan=10><div style='padding:3px'></div></td></tr>";
|
||||
|
||||
public static final String VIEWMODEID = "icons";
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#getViewModeID()
|
||||
*/
|
||||
public String getViewModeID()
|
||||
{
|
||||
return VIEWMODEID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListBefore(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListBefore(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
// no headers for this renderer
|
||||
this.rowIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListRow(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[], java.lang.Object)
|
||||
*/
|
||||
public void renderListRow(FacesContext context, UIRichList richList, UIColumn[] columns, Object row)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// start new row as per number of columns in this icon view
|
||||
if (this.rowIndex % COLUMNS == 0)
|
||||
{
|
||||
out.write("<tr");
|
||||
outputAttribute(out, richList.getAttributes().get("rowStyleClass"), "class");
|
||||
out.write('>');
|
||||
}
|
||||
|
||||
// find primary column (which must exist)
|
||||
UIColumn primaryColumn = null;
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
if (columns[i].isRendered() == true && columns[i].getPrimary() == true)
|
||||
{
|
||||
primaryColumn = columns[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (primaryColumn == null)
|
||||
{
|
||||
logger.warn("No primary column found for RichList definition: " + richList.getId());
|
||||
}
|
||||
|
||||
// output primary column as the icon label
|
||||
out.write("<td width=");
|
||||
out.write(COLUMN_PERCENT);
|
||||
out.write("><table cellspacing=0 cellpadding=2 border=0>");
|
||||
if (primaryColumn != null)
|
||||
{
|
||||
UIColumn column = primaryColumn;
|
||||
|
||||
if (column.isRendered() == true)
|
||||
{
|
||||
out.write("<tr><td rowspan=10");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
|
||||
// output the large icon for this column
|
||||
UIComponent largeIcon = column.getLargeIcon();
|
||||
if (largeIcon != null)
|
||||
{
|
||||
largeIcon.encodeBegin(context);
|
||||
largeIcon.encodeChildren(context);
|
||||
largeIcon.encodeEnd(context);
|
||||
}
|
||||
out.write("</td>");
|
||||
|
||||
// start the next cell which contains the first column component
|
||||
out.write("<td");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
if (column.getChildCount() != 0)
|
||||
{
|
||||
// allow child controls inside the columns to render themselves
|
||||
Utils.encodeRecursive(context, column);
|
||||
}
|
||||
out.write("</td></tr>");
|
||||
}
|
||||
}
|
||||
|
||||
// render remaining columns as lines of data up to a max display limit
|
||||
for (int i=0; i<columns.length; i++)
|
||||
{
|
||||
UIColumn column = columns[i];
|
||||
|
||||
int count = 1;
|
||||
if (column.isRendered() == true && column.getPrimary() == false &&
|
||||
(count < MAX_DISPLAYABLE_LINES || column.getActions() == true) )
|
||||
{
|
||||
out.write("<tr><td");
|
||||
outputAttribute(out, column.getAttributes().get("style"), "style");
|
||||
outputAttribute(out, column.getAttributes().get("styleClass"), "class");
|
||||
out.write('>');
|
||||
if (column.getChildCount() != 0)
|
||||
{
|
||||
// allow child controls inside the columns to render themselves
|
||||
Utils.encodeRecursive(context, column);
|
||||
}
|
||||
out.write("</td></tr>");
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
out.write("</table></td>");
|
||||
|
||||
if (this.rowIndex % COLUMNS == COLUMNS-1)
|
||||
{
|
||||
// end row and output a blank padding row/div
|
||||
out.write(END_ROW_SEPARATOR);
|
||||
}
|
||||
|
||||
this.rowIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.web.ui.common.renderer.data.IRichListRenderer#renderListAfter(javax.faces.context.FacesContext, org.alfresco.web.ui.common.component.data.UIColumn[])
|
||||
*/
|
||||
public void renderListAfter(FacesContext context, UIRichList richList, UIColumn[] columns)
|
||||
throws IOException
|
||||
{
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// finish last row if required (we used an open-ended column rendering algorithm)
|
||||
if ((this.rowIndex-1) % COLUMNS != COLUMNS-1)
|
||||
{
|
||||
out.write(END_ROW_SEPARATOR);
|
||||
}
|
||||
|
||||
out.write("<tr><td colspan=99 align=right>");
|
||||
for (Iterator i=richList.getChildren().iterator(); i.hasNext(); /**/)
|
||||
{
|
||||
// output all remaining child components that are not UIColumn
|
||||
UIComponent child = (UIComponent)i.next();
|
||||
if (child instanceof UIColumn == false)
|
||||
{
|
||||
Utils.encodeRecursive(context, child);
|
||||
}
|
||||
}
|
||||
out.write("</td></tr>");
|
||||
}
|
||||
|
||||
private int rowIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
private static Log logger = LogFactory.getLog(RichListRenderer.class);
|
||||
}
|
Reference in New Issue
Block a user