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:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit d051d1153c
920 changed files with 98871 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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("&nbsp;");
renderTimeElement(out, component, calendar.get(Calendar.HOUR_OF_DAY), clientId + FIELD_HOUR, showTime.booleanValue());
if (showTime.booleanValue())
{
out.write("&nbsp;:&nbsp;");
}
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;
}
}

View File

@@ -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'/>&nbsp;&nbsp;");
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;
}
}

View File

@@ -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++;
}
}

View File

@@ -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";
}
}

View File

@@ -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();
}

View File

@@ -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("&nbsp;");
}
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);
}