Completion of dialog and wizard frameworks also converted advanced space wizard and create space dialog to the new frameworks.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2615 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2006-04-04 12:12:58 +00:00
parent 4f3e44c1d3
commit 48e2691f6a
34 changed files with 2448 additions and 759 deletions

View File

@@ -26,7 +26,6 @@ import javax.faces.context.FacesContext;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.dialog.DialogManager;
import org.alfresco.web.bean.repository.Node;
@@ -35,6 +34,7 @@ import org.alfresco.web.config.DialogsConfigElement;
import org.alfresco.web.config.NavigationConfigElement;
import org.alfresco.web.config.NavigationElementReader;
import org.alfresco.web.config.NavigationResult;
import org.alfresco.web.config.WizardsConfigElement;
import org.alfresco.web.config.DialogsConfigElement.DialogConfig;
import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
import org.apache.commons.logging.Log;
@@ -96,7 +96,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
if (dialogWizardClosing)
{
handleDialogOrWizardClose(context, fromAction, outcome);
handleDialogOrWizardClose(context, fromAction, outcome, isDialog);
}
else
{
@@ -108,15 +108,22 @@ public class AlfrescoNavigationHandler extends NavigationHandler
{
handleWizardOpen(context, fromAction, outcome);
}
if (logger.isDebugEnabled())
logger.debug("view stack: " + getViewStack(context));
}
}
else
{
handleDispatch(context, fromAction, outcome);
if (isWizardStep(fromAction))
{
goToView(context, getWizardContainer(context));
}
else
{
handleDispatch(context, fromAction, outcome);
}
}
if (logger.isDebugEnabled())
logger.debug("view stack: " + getViewStack(context));
}
/**
@@ -176,6 +183,26 @@ public class AlfrescoNavigationHandler extends NavigationHandler
return closing;
}
/**
* Determines whether the given fromAction represents a step in the wizard
* i.e. next or back
*
* @param fromAction The fromAction
* @return true if the from action represents a wizard step
*/
protected boolean isWizardStep(String fromAction)
{
boolean wizardStep = false;
if (fromAction != null &&
(fromAction.equals("#{WizardManager.next}") || fromAction.equals("#{WizardManager.back}")))
{
wizardStep = true;
}
return wizardStep;
}
/**
* Removes the dialog or wizard prefix from the given outcome
*
@@ -281,7 +308,39 @@ public class AlfrescoNavigationHandler extends NavigationHandler
*/
protected WizardConfig getWizardConfig(FacesContext context, String name, Node dispatchContext)
{
return null;
WizardConfig wizardConfig = null;
ConfigService configSvc = Application.getConfigService(context);
if (dispatchContext != null)
{
Config config = configSvc.getConfig(dispatchContext);
if (config != null)
{
WizardsConfigElement wizardsCfg = (WizardsConfigElement)config.getConfigElement(
WizardsConfigElement.CONFIG_ELEMENT_ID);
if (wizardsCfg != null)
{
wizardConfig = wizardsCfg.getWizard(name);
}
}
}
// if we didn't find a dialog via the dispatch look it up in the 'global' wizards config
if (wizardConfig == null)
{
Config config = configSvc.getConfig(CONFIG_WIZARDS);
if (config != null)
{
WizardsConfigElement wizardsCfg = (WizardsConfigElement)config.getConfigElement(
WizardsConfigElement.CONFIG_ELEMENT_ID);
if (wizardsCfg != null)
{
wizardConfig = wizardsCfg.getWizard(name);
}
}
}
return wizardConfig;
}
/**
@@ -511,10 +570,17 @@ public class AlfrescoNavigationHandler extends NavigationHandler
/**
* Closes the current dialog or wizard
*
* @param context FacesContext
* @param fromAction The fromAction
* @param outcome The outcome
* @param dialog true if a dialog is being closed, false if a wizard is being closed
*/
protected void handleDialogOrWizardClose(FacesContext context, String fromAction, String outcome)
protected void handleDialogOrWizardClose(FacesContext context, String fromAction, String outcome, boolean dialog)
{
// if we are closing the dialog take the view off the
String closingItem = dialog ? "dialog" : "wizard";
// if we are closing a wizard or dialog take the view off the
// top of the stack then decide whether to use the view
// or any overridden outcome that may be present
if (getViewStack(context).empty() == false)
@@ -527,7 +593,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
{
// there isn't an overidden outcome so go back to the previous view
if (logger.isDebugEnabled())
logger.debug("Closing dialog, going back to view id: " + newViewId);
logger.debug("Closing " + closingItem + ", going back to view id: " + newViewId);
goToView(context, newViewId);
}
@@ -538,7 +604,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
getViewStack(context).clear();
if (logger.isDebugEnabled())
logger.debug("Closing dialog with an overridden outcome of '" + overriddenOutcome + "'");
logger.debug("Closing " + closingItem + " with an overridden outcome of '" + overriddenOutcome + "'");
navigate(context, fromAction, overriddenOutcome);
}
@@ -549,7 +615,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler
// log a warning and return a null outcome to stay on the same page
if (logger.isWarnEnabled())
{
logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome");
logger.warn("Attempting to close a " + closingItem + " with an empty view stack, returning null outcome");
}
navigate(context, fromAction, null);
@@ -565,8 +631,8 @@ public class AlfrescoNavigationHandler extends NavigationHandler
*/
protected void addCurrentViewToStack(FacesContext context)
{
// if we are opening a dialog push the current view id
// on to the stack, but only if it is different than the
// if we are opening a wizard or dialog push the current view
// id on to the stack, but only if it is different than the
// current view at the top (you can't launch a dialog from
// the same page 2 times in a row!)

View File

@@ -48,7 +48,12 @@ public class DebugPhaseListener implements PhaseListener
{
if (logger.isDebugEnabled())
{
printComponentTree(FacesContext.getCurrentInstance().getViewRoot());
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE)
{
printComponentTree(FacesContext.getCurrentInstance().getViewRoot());
}
logger.debug("********** Exiting phase: " + event.getPhaseId().toString());
}
}
@@ -57,6 +62,8 @@ public class DebugPhaseListener implements PhaseListener
*/
public void beforePhase(PhaseEvent event)
{
if (logger.isDebugEnabled())
logger.debug("********** Entering phase: " + event.getPhaseId().toString());
}
/**
@@ -64,29 +71,33 @@ public class DebugPhaseListener implements PhaseListener
*/
public PhaseId getPhaseId()
{
return PhaseId.RENDER_RESPONSE;
return PhaseId.ANY_PHASE;
}
public void printComponentTree(UIComponent comp){
public void printComponentTree(UIComponent comp)
{
printComponentInfo(comp);
List complist = comp.getChildren();
if (complist.size()>0)
indent++;
for (int i = 0; i < complist.size(); i++) {
for (int i = 0; i < complist.size(); i++)
{
UIComponent uicom = (UIComponent) complist.get(i);
printComponentTree(uicom);
if (i+1 == complist.size())
indent--;
}
}
public void printComponentInfo(UIComponent comp){
if (comp.getId() == null){
public void printComponentInfo(UIComponent comp)
{
if (comp.getId() == null)
{
logger.debug("UIViewRoot" + " " + "(" + comp.getClass().getName() + ")");
} else {
}
else
{
logger.debug(getIndent() + "|");
logger.debug(getIndent() + comp.getId() + " " + "(" + comp.getClass().getName() + ")");
}
@@ -99,6 +110,7 @@ public class DebugPhaseListener implements PhaseListener
{
indent += INDENT;
}
return indent;
}
}

View File

@@ -1,9 +1,18 @@
package org.alfresco.web.bean.dialog;
import javax.faces.context.FacesContext;
import java.text.MessageFormat;
import javax.faces.context.FacesContext;
import javax.transaction.UserTransaction;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
/**
* Base class for all dialog beans providing common functionality
@@ -12,9 +21,12 @@ import org.alfresco.web.app.context.UIContextService;
*/
public abstract class BaseDialogBean implements IDialogBean
{
protected static final String DIALOG_CLOSE = "dialog:close";
public abstract String finish();
protected static final String ERROR_ID = "error_generic";
// services common to most dialogs
protected BrowseBean browseBean;
protected NavigationBean navigator;
protected NodeService nodeService;
public void init()
{
@@ -24,16 +36,118 @@ public abstract class BaseDialogBean implements IDialogBean
public String cancel()
{
return DIALOG_CLOSE;
return getDefaultCancelOutcome();
}
public String finish()
{
String outcome = getDefaultFinishOutcome();
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
// call the actual implementation
outcome = finishImpl(context, outcome);
tx.commit();
}
catch (Throwable e)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(formatErrorMessage(e));
outcome = null;
}
return outcome;
}
public boolean getFinishButtonDisabled()
public String getCancelButtonLabel()
{
return true;
return Application.getMessage(FacesContext.getCurrentInstance(), "cancel");
}
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "ok");
}
public boolean getFinishButtonDisabled()
{
return true;
}
/**
* @param browseBean The BrowseBean to set.
*/
public void setBrowseBean(BrowseBean browseBean)
{
this.browseBean = browseBean;
}
/**
* @param navigator The NavigationBean to set.
*/
public void setNavigator(NavigationBean navigator)
{
this.navigator = navigator;
}
/**
* @param nodeService The nodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Returns the default cancel outcome
*
* @return Default close outcome, dialog:close by default
*/
protected String getDefaultCancelOutcome()
{
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
/**
* Returns the default finish outcome
*
* @return Default finish outcome, dialog:close by default
*/
protected String getDefaultFinishOutcome()
{
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
/**
* Performs the actual processing for the wizard.
* NOTE: This method is called within the context of a transaction
* so no transaction handling is required
*
* @param context FacesContext
* @param outcome The default outcome
* @return The outcome
*/
protected abstract String finishImpl(FacesContext context, String outcome)
throws Exception;
/**
* Returns a formatted exception string for the given exception
*
* @param exception The exception that got thrown
* @return The formatted message
*/
protected String formatErrorMessage(Throwable exception)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), ERROR_ID),
exception.getMessage());
}
}

View File

@@ -39,6 +39,16 @@ public class DialogManager
this.currentDialog.init();
}
/**
* Returns the config for the current dialog
*
* @return The current dialog config
*/
public DialogConfig getCurrentDialog()
{
return this.currentDialogConfig;
}
/**
* Returns the current dialog bean being managed
*
@@ -111,6 +121,16 @@ public class DialogManager
return this.currentDialogConfig.getPage();
}
/**
* Returns the label to use for the cancel button
*
* @return The cancel button label
*/
public String getCancelButtonLabel()
{
return this.currentDialog.getCancelButtonLabel();
}
/**
* Returns the label to use for the finish button
*

View File

@@ -12,19 +12,26 @@ public interface IDialogBean
*/
public void init();
/**
* Method handler called when the cancel button of the dialog is pressed
*
* @return The outcome to return
*/
public String cancel();
/**
* Method handler called when the finish button of the dialog is pressed
*
* @return The outcome to return (normally dialog:close)
* @return The outcome to return
*/
public String finish();
/**
* Method handler called when the cancel button of the dialog is pressed
* Returns the label to use for the cancel button
*
* @return The outcome to return (normally dialog:close)
* @return The cancel button label
*/
public String cancel();
public String getCancelButtonLabel();
/**
* Returns the label to use for the finish button

View File

@@ -1,328 +0,0 @@
package org.alfresco.web.bean.dialog;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.transaction.UserTransaction;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIListItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Dialog bean to create a space
*
* @author gavinc
*/
public class SpaceDialog extends BaseDialogBean
{
protected static final String ERROR = "error_space";
private static final String SPACE_ICON_DEFAULT = "space-icon-default";
// private static final String DEFAULT_SPACE_TYPE_ICON = "/images/icons/space.gif";
private static final String ICONS_LOOKUP_KEY = " icons";
protected NodeService nodeService;
protected FileFolderService fileFolderService;
protected NamespaceService namespaceService;
protected SearchService searchService;
protected NavigationBean navigator;
protected BrowseBean browseBean;
protected String spaceType;
protected String icon;
protected String name;
protected String description;
private static Log logger = LogFactory.getLog(SpaceDialog.class);
/**
* @param nodeService The nodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param fileFolderService used to manipulate folder/folder model nodes
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* @param searchService the service used to find nodes
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* @param namespaceService The NamespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param navigator The NavigationBean to set.
*/
public void setNavigator(NavigationBean navigator)
{
this.navigator = navigator;
}
/**
* @param browseBean The BrowseBean to set.
*/
public void setBrowseBean(BrowseBean browseBean)
{
this.browseBean = browseBean;
}
/**
* @return Returns the description.
*/
public String getDescription()
{
return description;
}
/**
* @param description The description to set.
*/
public void setDescription(String description)
{
this.description = description;
}
/**
* @return Returns the icon.
*/
public String getIcon()
{
return icon;
}
/**
* @param icon The icon to set.
*/
public void setIcon(String icon)
{
this.icon = icon;
}
/**
* @return Returns the name.
*/
public String getName()
{
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return Returns the spaceType.
*/
public String getSpaceType()
{
return spaceType;
}
/**
* @param spaceType The spaceType to set.
*/
public void setSpaceType(String spaceType)
{
this.spaceType = spaceType;
}
/**
* Returns a list of icons to allow the user to select from.
* The list can change according to the type of space being created.
*
* @return A list of icons
*/
@SuppressWarnings("unchecked")
public List<UIListItem> getIcons()
{
// NOTE: we can't cache this list as it depends on the space type
// which the user can change during the advanced space wizard
List<UIListItem> icons = null;
QName type = QName.createQName(this.spaceType);
String typePrefixForm = type.toPrefixString(this.namespaceService);
Config config = Application.getConfigService(FacesContext.getCurrentInstance()).
getConfig(typePrefixForm + ICONS_LOOKUP_KEY);
if (config != null)
{
ConfigElement iconsCfg = config.getConfigElement("icons");
if (iconsCfg != null)
{
boolean first = true;
for (ConfigElement icon : iconsCfg.getChildren())
{
String iconName = icon.getAttribute("name");
String iconPath = icon.getAttribute("path");
if (iconName != null && iconPath != null)
{
if (first)
{
// if this is the first icon create the list and make
// the first icon in the list the default
icons = new ArrayList<UIListItem>(iconsCfg.getChildCount());
if (this.icon == null)
{
// set the default if it is not already
this.icon = iconName;
}
first = false;
}
UIListItem item = new UIListItem();
item.setValue(iconName);
item.getAttributes().put("image", iconPath);
icons.add(item);
}
}
}
}
// if we didn't find any icons display one default choice
if (icons == null)
{
icons = new ArrayList<UIListItem>(1);
this.icon = SPACE_ICON_DEFAULT;
UIListItem item = new UIListItem();
item.setValue("space-icon-default");
item.getAttributes().put("image", "/images/icons/space-icon-default.gif");
icons.add(item);
}
return icons;
}
/**
* Initialises the wizard
*/
public void init()
{
super.init();
// reset all variables
this.spaceType = ContentModel.TYPE_FOLDER.toString();
this.icon = null;
this.name = null;
this.description = "";
}
@Override
public String finish()
{
String outcome = DIALOG_CLOSE;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
// create the space (just create a folder for now)
NodeRef parentNodeRef;
String nodeId = this.navigator.getCurrentNodeId();
if (nodeId == null)
{
parentNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());
}
else
{
parentNodeRef = new NodeRef(Repository.getStoreRef(), nodeId);
}
FileInfo fileInfo = fileFolderService.create(
parentNodeRef,
this.name,
Repository.resolveToQName(this.spaceType));
NodeRef nodeRef = fileInfo.getNodeRef();
if (logger.isDebugEnabled())
logger.debug("Created folder node with name: " + this.name);
// apply the uifacets aspect - icon, title and description props
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(5);
uiFacetsProps.put(ContentModel.PROP_ICON, this.icon);
uiFacetsProps.put(ContentModel.PROP_TITLE, this.name);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, this.description);
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps);
if (logger.isDebugEnabled())
logger.debug("Added uifacets aspect with properties: " + uiFacetsProps);
// commit the transaction
tx.commit();
}
catch (FileExistsException e)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
// print status message
String statusMsg = MessageFormat.format(
Application.getMessage(
FacesContext.getCurrentInstance(), "error_exists"),
e.getExisting().getName());
Utils.addErrorMessage(statusMsg);
// no outcome
outcome = null;
}
catch (Throwable e)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), ERROR), e.getMessage()), e);
outcome = null;
}
return outcome;
}
}

View File

@@ -0,0 +1,34 @@
package org.alfresco.web.bean.spaces;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
/**
* Dialog bean to create a space.
* Uses the CreateSpaceWizard and just overrides the finish button label
* and the default outcomes.
*
* @author gavinc
*/
public class CreateSpaceDialog extends CreateSpaceWizard
{
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "new_space");
}
@Override
protected String getDefaultCancelOutcome()
{
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
@Override
protected String getDefaultFinishOutcome()
{
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
}
}

View File

@@ -0,0 +1,696 @@
package org.alfresco.web.bean.spaces;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.wizard.BaseWizardBean;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.ui.common.component.UIListItem;
import org.alfresco.web.ui.common.component.description.UIDescription;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean responsible for the create space wizard
*
* @author gavinc
*/
public class CreateSpaceWizard extends BaseWizardBean
{
public static final String DEFAULT_SPACE_ICON_NAME = "space-icon-default";
public static final String DEFAULT_SPACE_ICON_PATH = "";
public static final String DEFAULT_SPACE_TYPE_ICON_PATH = "/images/icons/space.gif";
private static Log logger = LogFactory.getLog(CreateSpaceWizard.class);
protected NamespaceService namespaceService;
protected DictionaryService dictionaryService;
protected String spaceType;
protected String icon;
protected String createFrom;
protected NodeRef existingSpaceId;
protected String templateSpaceId;
protected String copyPolicy;
protected String name;
protected String description;
protected String templateName;
protected boolean saveAsTemplate;
protected List<SelectItem> templates;
protected List<UIListItem> folderTypes;
protected List<UIDescription> folderTypeDescriptions;
// the NodeRef of the node created during finish
protected NodeRef createdNode;
/**
* Initialises the wizard
*/
public void init()
{
super.init();
// clear the cached query results
if (this.templates != null)
{
this.templates.clear();
this.templates = null;
}
// reset all variables
this.createFrom = "scratch";
this.spaceType = ContentModel.TYPE_FOLDER.toString();
this.icon = null;
this.copyPolicy = "contents";
this.existingSpaceId = null;
this.templateSpaceId = null;
this.name = null;
this.description = "";
this.templateName = null;
this.saveAsTemplate = false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
String newSpaceId = null;
if (this.createFrom.equals("scratch"))
{
// create the space (just create a folder for now)
NodeRef parentNodeRef;
String nodeId = this.navigator.getCurrentNodeId();
if (nodeId == null)
{
parentNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());
}
else
{
parentNodeRef = new NodeRef(Repository.getStoreRef(), nodeId);
}
FileInfo fileInfo = fileFolderService.create(
parentNodeRef,
this.name,
Repository.resolveToQName(this.spaceType));
NodeRef nodeRef = fileInfo.getNodeRef();
newSpaceId = nodeRef.getId();
if (logger.isDebugEnabled())
logger.debug("Created folder node with name: " + this.name);
// apply the uifacets aspect - icon, title and description props
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(5);
uiFacetsProps.put(ContentModel.PROP_ICON, this.icon);
uiFacetsProps.put(ContentModel.PROP_TITLE, this.name);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, this.description);
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps);
if (logger.isDebugEnabled())
logger.debug("Added uifacets aspect with properties: " + uiFacetsProps);
// remember the created node
this.createdNode = nodeRef;
}
else if (this.createFrom.equals("existing"))
{
// copy the selected space and update the name, description and icon
NodeRef sourceNode = this.existingSpaceId;
NodeRef parentSpace = new NodeRef(Repository.getStoreRef(), this.navigator.getCurrentNodeId());
// copy from existing
NodeRef copiedNode = this.fileFolderService.copy(sourceNode, parentSpace, this.name).getNodeRef();
// also need to set the new description and icon properties
this.nodeService.setProperty(copiedNode, ContentModel.PROP_DESCRIPTION, this.description);
this.nodeService.setProperty(copiedNode, ContentModel.PROP_ICON, this.icon);
newSpaceId = copiedNode.getId();
if (logger.isDebugEnabled())
logger.debug("Copied space with id of " + sourceNode.getId() + " to " + this.name);
// remember the created node
this.createdNode = copiedNode;
}
else if (this.createFrom.equals("template"))
{
// copy the selected space and update the name, description and icon
NodeRef sourceNode = new NodeRef(Repository.getStoreRef(), this.templateSpaceId);
NodeRef parentSpace = new NodeRef(Repository.getStoreRef(), this.navigator.getCurrentNodeId());
// copy from the template
NodeRef copiedNode = this.fileFolderService.copy(sourceNode, parentSpace, this.name).getNodeRef();
// also need to set the new description and icon properties
this.nodeService.setProperty(copiedNode, ContentModel.PROP_DESCRIPTION, this.description);
this.nodeService.setProperty(copiedNode, ContentModel.PROP_ICON, this.icon);
newSpaceId = copiedNode.getId();
if (logger.isDebugEnabled())
logger.debug("Copied template space with id of " + sourceNode.getId() + " to " + this.name);
// remember the created node
this.createdNode = copiedNode;
}
// if the user selected to save the space as a template space copy the new
// space to the templates folder
if (this.saveAsTemplate)
{
// get hold of the Templates node
DynamicNamespacePrefixResolver namespacePrefixResolver = new DynamicNamespacePrefixResolver(null);
namespacePrefixResolver.registerNamespace(NamespaceService.APP_MODEL_PREFIX, NamespaceService.APP_MODEL_1_0_URI);
String xpath = Application.getRootPath(FacesContext.getCurrentInstance()) + "/" +
Application.getGlossaryFolderName(FacesContext.getCurrentInstance()) + "/" +
Application.getSpaceTemplatesFolderName(FacesContext.getCurrentInstance());
NodeRef rootNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());
List<NodeRef> templateNodeList = this.searchService.selectNodes(
rootNodeRef,
xpath, null, namespacePrefixResolver, false);
if (templateNodeList.size() == 1)
{
// get the first item in the list as we from test above there is only one!
NodeRef templateNode = templateNodeList.get(0);
NodeRef sourceNode = new NodeRef(Repository.getStoreRef(), newSpaceId);
// copy this to the template location
fileFolderService.copy(sourceNode, templateNode, this.templateName);
}
}
return outcome;
}
/**
* @return Returns the copyPolicy.
*/
public String getCopyPolicy()
{
return copyPolicy;
}
/**
* @param copyPolicy The copyPolicy to set.
*/
public void setCopyPolicy(String copyPolicy)
{
this.copyPolicy = copyPolicy;
}
/**
* @return Returns the createFrom.
*/
public String getCreateFrom()
{
return createFrom;
}
/**
* @param createFrom The createFrom to set.
*/
public void setCreateFrom(String createFrom)
{
this.createFrom = createFrom;
}
/**
* @return Returns the description.
*/
public String getDescription()
{
return description;
}
/**
* @param description The description to set.
*/
public void setDescription(String description)
{
this.description = description;
}
/**
* @return Returns the existingSpaceId.
*/
public NodeRef getExistingSpaceId()
{
return existingSpaceId;
}
/**
* @param existingSpaceId The existingSpaceId to set.
*/
public void setExistingSpaceId(NodeRef existingSpaceId)
{
this.existingSpaceId = existingSpaceId;
}
/**
* @return Returns the icon.
*/
public String getIcon()
{
return icon;
}
/**
* @param icon The icon to set.
*/
public void setIcon(String icon)
{
this.icon = icon;
}
/**
* @return Returns the name.
*/
public String getName()
{
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return Returns the saveAsTemplate.
*/
public boolean isSaveAsTemplate()
{
return saveAsTemplate;
}
/**
* @param saveAsTemplate The saveAsTemplate to set.
*/
public void setSaveAsTemplate(boolean saveAsTemplate)
{
this.saveAsTemplate = saveAsTemplate;
}
/**
* @return Returns the spaceType.
*/
public String getSpaceType()
{
return spaceType;
}
/**
* @param spaceType The spaceType to set.
*/
public void setSpaceType(String spaceType)
{
this.spaceType = spaceType;
}
/**
* @return Returns the templateName.
*/
public String getTemplateName()
{
return templateName;
}
/**
* @param templateName The templateName to set.
*/
public void setTemplateName(String templateName)
{
this.templateName = templateName;
}
/**
* @return Returns the templateSpaceId.
*/
public String getTemplateSpaceId()
{
return templateSpaceId;
}
/**
* @param templateSpaceId The templateSpaceId to set.
*/
public void setTemplateSpaceId(String templateSpaceId)
{
this.templateSpaceId = templateSpaceId;
}
/**
* @return Returns the summary data for the wizard.
*/
public String getSummary()
{
String summaryCreateType = null;
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
if (this.createFrom.equals("scratch"))
{
summaryCreateType = bundle.getString("scratch");
}
else if (this.createFrom.equals("existing"))
{
summaryCreateType = bundle.getString("an_existing_space");
}
else if (this.createFrom.equals("template"))
{
summaryCreateType = bundle.getString("a_template");
}
// String summarySaveAsTemplate = this.saveAsTemplate ? bundle.getString("yes") : bundle.getString("no");
// bundle.getString("save_as_template"), bundle.getString("template_name")},
// summarySaveAsTemplate, this.templateName
String spaceTypeLabel = null;
for (UIListItem item : this.getFolderTypes())
{
if (item.getValue().equals(this.spaceType))
{
spaceTypeLabel = item.getLabel();
break;
}
}
return buildSummary(
new String[] {bundle.getString("space_type"), bundle.getString("name"),
bundle.getString("description"), bundle.getString("creating_from")},
new String[] {spaceTypeLabel, this.name, this.description, summaryCreateType});
}
/**
* @return Returns a list of template spaces currently in the system
*/
public List<SelectItem> getTemplateSpaces()
{
if (this.templates == null)
{
this.templates = new ArrayList<SelectItem>();
FacesContext context = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(context) + "/" + Application.getGlossaryFolderName(context) +
"/" + Application.getSpaceTemplatesFolderName(context) + "/*";
NodeRef rootNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());
NamespaceService resolver = Repository.getServiceRegistry(context).getNamespaceService();
List<NodeRef> results = this.searchService.selectNodes(rootNodeRef, xpath, null, resolver, false);
if (results.size() > 0)
{
for (NodeRef assocRef : results)
{
Node childNode = new Node(assocRef);
this.templates.add(new SelectItem(childNode.getId(), childNode.getName()));
}
// make sure the list is sorted by the label
QuickSort sorter = new QuickSort(this.templates, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
// add an entry (at the start) to instruct the user to select a template
this.templates.add(0, new SelectItem("none", Application.getMessage(FacesContext.getCurrentInstance(), "select_a_template")));
}
return this.templates;
}
/**
* Returns a list of UIListItem objects representing the folder types
* and also constructs the list of descriptions for each type
*
* @return List of UIListItem components
*/
@SuppressWarnings("unchecked")
public List<UIListItem> getFolderTypes()
{
if (this.folderTypes == null)
{
FacesContext context = FacesContext.getCurrentInstance();
this.folderTypes = new ArrayList<UIListItem>(2);
this.folderTypeDescriptions = new ArrayList<UIDescription>(2);
// add the well known 'container space' type to start with
UIListItem defaultItem = new UIListItem();
String defaultLabel = Application.getMessage(context, "container");
defaultItem.setValue(ContentModel.TYPE_FOLDER.toString());
defaultItem.setLabel(defaultLabel);
defaultItem.setTooltip(defaultLabel);
defaultItem.getAttributes().put("image", DEFAULT_SPACE_TYPE_ICON_PATH);
this.folderTypes.add(defaultItem);
UIDescription defaultDesc = new UIDescription();
defaultDesc.setControlValue(ContentModel.TYPE_FOLDER.toString());
defaultDesc.setText(Application.getMessage(context, "container_desc"));
this.folderTypeDescriptions.add(defaultDesc);
// add any configured content sub-types to the list
Config wizardCfg = Application.getConfigService(FacesContext.getCurrentInstance()).
getConfig("Custom Folder Types");
if (wizardCfg != null)
{
ConfigElement typesCfg = wizardCfg.getConfigElement("folder-types");
if (typesCfg != null)
{
for (ConfigElement child : typesCfg.getChildren())
{
QName idQName = Repository.resolveToQName(child.getAttribute("name"));
TypeDefinition typeDef = this.dictionaryService.getType(idQName);
if (typeDef != null &&
this.dictionaryService.isSubClass(typeDef.getName(), ContentModel.TYPE_FOLDER))
{
// look for a client localized string
String label = null;
String msgId = child.getAttribute("displayLabelId");
if (msgId != null)
{
label = Application.getMessage(context, msgId);
}
// if there wasn't an externalized string look for one in the config
if (label == null)
{
label = child.getAttribute("displayLabel");
}
// if there wasn't a client based label try and get it from the dictionary
if (label == null)
{
label = typeDef.getTitle();
}
// finally use the localname if we still haven't found a label
if (label == null)
{
label = idQName.getLocalName();
}
// resolve a description string for the type
String description = null;
msgId = child.getAttribute("descriptionMsgId");
if (msgId != null)
{
description = Application.getMessage(context, msgId);
}
if (description == null)
{
description = child.getAttribute("description");
}
// if we don't have a local description just use the label
if (description == null)
{
description = label;
}
// extract the icon to use from the config
String icon = child.getAttribute("icon");
if (icon == null || icon.length() == 0)
{
icon = DEFAULT_SPACE_TYPE_ICON_PATH;
}
UIListItem item = new UIListItem();
item.getAttributes().put("value", idQName.toString());
item.getAttributes().put("label", label);
item.getAttributes().put("tooltip", label);
item.getAttributes().put("image", icon);
this.folderTypes.add(item);
UIDescription desc = new UIDescription();
desc.setControlValue(idQName.toString());
desc.setText(description);
this.folderTypeDescriptions.add(desc);
}
}
}
else
{
logger.warn("Could not find 'folder-types' configuration element");
}
}
else
{
logger.warn("Could not find 'Custom Folder Types' configuration section");
}
}
return this.folderTypes;
}
/**
* Returns a list of UIDescription objects for the folder types
*
* @return A list of UIDescription objects
*/
public List<UIDescription> getFolderTypeDescriptions()
{
if (this.folderTypeDescriptions == null)
{
// call the getFolderType method to construct the list
getFolderTypes();
}
return this.folderTypeDescriptions;
}
/**
* Returns a list of icons to allow the user to select from.
* The list can change according to the type of space being created.
*
* @return A list of icons
*/
@SuppressWarnings("unchecked")
public List<UIListItem> getIcons()
{
// NOTE: we can't cache this list as it depends on the space type
// which the user can change during the advanced space wizard
List<UIListItem> icons = null;
QName type = QName.createQName(this.spaceType);
String typePrefixForm = type.toPrefixString(this.namespaceService);
Config config = Application.getConfigService(FacesContext.getCurrentInstance()).
getConfig(typePrefixForm + " icons");
if (config != null)
{
ConfigElement iconsCfg = config.getConfigElement("icons");
if (iconsCfg != null)
{
boolean first = true;
for (ConfigElement icon : iconsCfg.getChildren())
{
String iconName = icon.getAttribute("name");
String iconPath = icon.getAttribute("path");
if (iconName != null && iconPath != null)
{
if (first)
{
// if this is the first icon create the list and make
// the first icon in the list the default
icons = new ArrayList<UIListItem>(iconsCfg.getChildCount());
if (this.icon == null)
{
// set the default if it is not already
this.icon = iconName;
}
first = false;
}
UIListItem item = new UIListItem();
item.setValue(iconName);
item.getAttributes().put("image", iconPath);
icons.add(item);
}
}
}
}
// if we didn't find any icons display one default choice
if (icons == null)
{
icons = new ArrayList<UIListItem>(1);
this.icon = DEFAULT_SPACE_ICON_NAME;
UIListItem item = new UIListItem();
item.setValue("space-icon-default");
item.getAttributes().put("image", "/images/icons/space-icon-default.gif");
icons.add(item);
}
return icons;
}
/**
* @param namespaceService The NamespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* Sets the dictionary service
*
* @param dictionaryService the dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Formats the error message to display if an error occurs during finish processing
*
* @param The exception
* @return The formatted message
*/
@Override
protected String formatErrorMessage(Throwable exception)
{
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_exists"),
((FileExistsException)exception).getExisting().getName());
}
else
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_space"),
((FileExistsException)exception).getExisting().getName());
}
}
}

View File

@@ -2,47 +2,35 @@ package org.alfresco.web.bean.wizard;
import javax.faces.context.FacesContext;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.dialog.BaseDialogBean;
/**
* Base class for all wizard beans providing common functionality
*
* @author gavinc
*/
public abstract class BaseWizardBean implements IWizardBean
public abstract class BaseWizardBean extends BaseDialogBean implements IWizardBean
{
protected static final String WIZARD_CLOSE = "wizard:close";
private static final String MSG_NOT_SET = "value_not_set";
public abstract String finish();
// services common to most wizards
protected FileFolderService fileFolderService;
protected SearchService searchService;
public void init()
{
// tell any beans to update themselves so the UI gets refreshed
UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
}
public boolean getNextButtonDisabled()
{
return true;
}
public boolean getBackButtonDisabled()
{
return true;
}
public boolean getFinishButtonDisabled()
{
return true;
return false;
}
public String getNextButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "next_button");
}
public String getBackButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "back_button");
@@ -52,9 +40,67 @@ public abstract class BaseWizardBean implements IWizardBean
{
return Application.getMessage(FacesContext.getCurrentInstance(), "finish_button");
}
public String cancel()
/**
* @param fileFolderService used to manipulate folder/folder model nodes
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
return WIZARD_CLOSE;
this.fileFolderService = fileFolderService;
}
/**
* @param searchService the service used to find nodes
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* Build summary table from the specified list of Labels and Values
*
* @param labels Array of labels to display
* @param values Array of values to display
*
* @return summary table HTML
*/
protected String buildSummary(String[] labels, String[] values)
{
if (labels == null || values == null || labels.length != values.length)
{
throw new IllegalArgumentException("Labels and Values passed to summary must be valid and of equal length.");
}
String msg = Application.getMessage(FacesContext.getCurrentInstance(), MSG_NOT_SET);
String notSetMsg = "&lt;" + msg + "&gt;";
StringBuilder buf = new StringBuilder(256);
buf.append("<table cellspacing='4' cellpadding='2' border='0' class='summary'>");
for (int i=0; i<labels.length; i++)
{
String value = values[i];
buf.append("<tr><td valign='top'><b>");
buf.append(labels[i]);
buf.append(":</b></td><td>");
buf.append(value != null ? value : notSetMsg);
buf.append("</td></tr>");
}
buf.append("</table>");
return buf.toString();
}
@Override
protected String getDefaultCancelOutcome()
{
return AlfrescoNavigationHandler.CLOSE_WIZARD_OUTCOME;
}
@Override
protected String getDefaultFinishOutcome()
{
return AlfrescoNavigationHandler.CLOSE_WIZARD_OUTCOME;
}
}

View File

@@ -9,34 +9,6 @@ import org.alfresco.web.bean.dialog.IDialogBean;
*/
public interface IWizardBean extends IDialogBean
{
/**
* Method handler called when the next button of the wizard is pressed
*
* @return The outcome to return
*/
// public String next();
/**
* Method handler called when the back button of the wizard is pressed
*
* @return The outcome to return
*/
// public String back();
/**
* Determines whether the next button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getNextButtonDisabled();
/**
* Determines whether the back button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getBackButtonDisabled();
/**
* Returns the label to use for the next button
*
@@ -50,4 +22,11 @@ public interface IWizardBean extends IDialogBean
* @return The back button label
*/
public String getBackButtonLabel();
/**
* Determines whether the next button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getNextButtonDisabled();
}

View File

@@ -1,10 +1,21 @@
package org.alfresco.web.bean.wizard;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.config.WizardsConfigElement.ConditionalPageConfig;
import org.alfresco.web.config.WizardsConfigElement.PageConfig;
import org.alfresco.web.config.WizardsConfigElement.StepConfig;
import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
import org.alfresco.web.ui.common.component.UIListItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean that manages the wizard framework
@@ -13,8 +24,13 @@ import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
*/
public class WizardManager
{
private static Log logger = LogFactory.getLog(WizardManager.class);
protected int currentStep = 1;
protected PageConfig currentPageCfg;
protected WizardConfig currentWizardConfig;
protected IWizardBean currentWizard;
protected List<StepConfig> steps;
/**
* Sets the current wizard
@@ -23,6 +39,7 @@ public class WizardManager
*/
public void setCurrentWizard(WizardConfig config)
{
this.currentStep = 1;
this.currentWizardConfig = config;
String beanName = this.currentWizardConfig.getManagedBean();
@@ -36,6 +53,22 @@ public class WizardManager
// initialise the managed bean
this.currentWizard.init();
// get the steps for the wizard
this.steps = this.currentWizardConfig.getStepsAsList();
// setup the first step
determineCurrentPage();
}
/**
* Returns the config for the current wizard
*
* @return The current wizard config
*/
public WizardConfig getCurrentWizard()
{
return this.currentWizardConfig;
}
/**
@@ -47,4 +80,395 @@ public class WizardManager
{
return this.currentWizard;
}
/**
* Returns the icon to use for the current wizard
*
* @return The icon
*/
public String getIcon()
{
return this.currentWizardConfig.getIcon();
}
/**
* Returns the resolved title to use for the wizard
*
* @return The title
*/
public String getTitle()
{
String title = this.currentWizardConfig.getTitleId();
if (title != null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
title = this.currentWizardConfig.getTitle();
}
return title;
}
/**
* Returns the resolved description to use for the wizard
*
* @return The description
*/
public String getDescription()
{
String desc = this.currentWizardConfig.getDescriptionId();
if (desc != null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
desc = this.currentWizardConfig.getDescription();
}
return desc;
}
/**
* Returns the current step position
*
* @return Current step position
*/
public int getCurrentStep()
{
return this.currentStep;
}
/**
* Returns the current step position as a string for use in the UI
*
* @return Current step position as a string
*/
public String getCurrentStepAsString()
{
return Integer.toString(this.currentStep);
}
/**
* Returns a list of UIListItems representing the steps of the wizard
*
* @return List of steps to display in UI
*/
public List<UIListItem> getStepItems()
{
List<UIListItem> items = new ArrayList<UIListItem>(this.steps.size());
for (int x = 0; x < this.steps.size(); x++)
{
String uiStepNumber = Integer.toString(x + 1);
StepConfig stepCfg = this.steps.get(x);
UIListItem item = new UIListItem();
item.setValue(uiStepNumber);
// get the title for the step
String stepTitle = stepCfg.getTitleId();
if (stepTitle != null)
{
stepTitle = Application.getMessage(FacesContext.getCurrentInstance(), stepTitle);
}
else
{
stepTitle = stepCfg.getTitle();
}
// get the tooltip for the step
String stepTooltip = stepCfg.getDescriptionId();
if (stepTooltip != null)
{
stepTooltip = Application.getMessage(FacesContext.getCurrentInstance(), stepTooltip);
}
else
{
stepTooltip = stepCfg.getDescription();
}
// set the label and tooltip
item.setLabel(uiStepNumber + ". " + stepTitle);
item.setTooltip(stepTooltip);
items.add(item);
}
return items;
}
/**
* Returns the current page of the wizard (depends on the current step position)
*
* @return The page
*/
public String getPage()
{
return this.currentPageCfg.getPath();
}
/**
* Returns the title of the current step
*
* @return The step title
*/
public String getStepTitle()
{
String title = this.currentPageCfg.getTitleId();
if (title != null)
{
title = Application.getMessage(FacesContext.getCurrentInstance(), title);
}
else
{
title = this.currentPageCfg.getTitle();
}
return title;
}
/**
* Returns the description of the current step
*
* @return The step description
*/
public String getStepDescription()
{
String desc = this.currentPageCfg.getDescriptionId();
if (desc != null)
{
desc = Application.getMessage(FacesContext.getCurrentInstance(), desc);
}
else
{
desc = this.currentPageCfg.getDescription();
}
return desc;
}
/**
* Returns the instructions for the current step
*
* @return The step instructions
*/
public String getStepInstructions()
{
String instruction = this.currentPageCfg.getInstructionId();
if (instruction != null)
{
instruction = Application.getMessage(FacesContext.getCurrentInstance(), instruction);
}
else
{
instruction = this.currentPageCfg.getInstruction();
}
return instruction;
}
/**
* Returns the label to use for the next button
*
* @return The next button label
*/
public String getNextButtonLabel()
{
return this.currentWizard.getNextButtonLabel();
}
/**
* Determines whether the next button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getNextButtonDisabled()
{
if (this.currentStep == this.steps.size())
{
return true;
}
else
{
return this.currentWizard.getNextButtonDisabled();
}
}
/**
* Returns the label to use for the back button
*
* @return The back button label
*/
public String getBackButtonLabel()
{
return this.currentWizard.getBackButtonLabel();
}
/**
* Determines whether the back button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getBackButtonDisabled()
{
if (this.currentStep == 1)
{
return true;
}
else
{
return false;
}
}
/**
* Returns the label to use for the cancel button
*
* @return The cancel button label
*/
public String getCancelButtonLabel()
{
return this.currentWizard.getCancelButtonLabel();
}
/**
* Returns the label to use for the finish button
*
* @return The finish button label
*/
public String getFinishButtonLabel()
{
return this.currentWizard.getFinishButtonLabel();
}
/**
* Determines whether the finish button on the wizard should be disabled
*
* @return true if the button should be disabled
*/
public boolean getFinishButtonDisabled()
{
if (this.currentStep == this.steps.size())
{
return false;
}
else
{
return this.currentWizard.getFinishButtonDisabled();
}
}
/**
* Method handler called when the next button of the wizard is pressed
*
* @return The outcome
*/
public void next()
{
this.currentStep++;
if (logger.isDebugEnabled())
logger.debug("next called, current step is now: " + this.currentStep);
// TODO: place a hook in here to call the wizard bean so it can override
// what step comes next thus overrriding the wizard manager
determineCurrentPage();
}
/**
* Method handler called when the back button of the wizard is pressed
*
* @return The outcome
*/
public void back()
{
this.currentStep--;
if (logger.isDebugEnabled())
logger.debug("back called, current step is now: " + this.currentStep);
// TODO: place a hook in here to call the wizard bean so it can override
// what step comes next thus overrriding the wizard manager
determineCurrentPage();
}
/**
* Method handler called when the finish button of the wizard is pressed
*
* @return The outcome
*/
public String finish()
{
return this.currentWizard.finish();
}
/**
* Method handler called when the cancel button of the wizard is pressed
*
* @return The outcome
*/
public String cancel()
{
return this.currentWizard.cancel();
}
/**
* Sets up the current page to show in the wizard
*/
protected void determineCurrentPage()
{
this.currentPageCfg = null;
// get the config for the current step position
StepConfig stepCfg = this.steps.get(this.currentStep-1);
// is the step conditional?
if (stepCfg.hasConditionalPages())
{
FacesContext context = FacesContext.getCurrentInstance();
// test each conditional page in turn
List<ConditionalPageConfig> pages = stepCfg.getConditionalPages();
for (ConditionalPageConfig pageCfg : pages)
{
String condition = pageCfg.getCondition();
if (logger.isDebugEnabled())
logger.debug("Evaluating condition: " + condition);
ValueBinding vb = context.getApplication().createValueBinding(condition);
Object obj = vb.getValue(context);
if (obj instanceof Boolean && ((Boolean)obj).booleanValue())
{
this.currentPageCfg = pageCfg;
break;
}
}
}
// if none of the conditions passed use the default page
if (this.currentPageCfg == null)
{
this.currentPageCfg = stepCfg.getDefaultPage();
}
if (this.currentPageCfg == null)
{
throw new AlfrescoRuntimeException("Failed to determine page for step '" + stepCfg.getName() +
"'. Make sure a default page is configured.");
}
if (logger.isDebugEnabled())
logger.debug("Config for current page: " + this.currentPageCfg);
}
}

View File

@@ -84,16 +84,6 @@ public class DialogsConfigElement extends ConfigElementAdapter
return combined;
}
/**
* Adds a dialog
*
* @param dialogConfig A pre-configured dialog config object
*/
/*package*/ void addDialog(DialogConfig dialogConfig)
{
this.dialogs.put(dialogConfig.getName(), dialogConfig);
}
/**
* Returns the named dialog
*
@@ -114,6 +104,16 @@ public class DialogsConfigElement extends ConfigElementAdapter
return this.dialogs;
}
/**
* Adds a dialog
*
* @param dialogConfig A pre-configured dialog config object
*/
/*package*/ void addDialog(DialogConfig dialogConfig)
{
this.dialogs.put(dialogConfig.getName(), dialogConfig);
}
/**
* Inner class representing the configuration of a single dialog
*
@@ -124,14 +124,16 @@ public class DialogsConfigElement extends ConfigElementAdapter
protected String name;
protected String page;
protected String managedBean;
protected String actionsConfigId;
protected String icon;
protected String title;
protected String titleId;
protected String description;
protected String descriptionId;
public DialogConfig(String name, String page, String bean,
String icon, String title, String titleId,
public DialogConfig(String name, String page, String bean,
String actionsConfigId, String icon,
String title, String titleId,
String description, String descriptionId)
{
// check the mandatory parameters are present
@@ -142,6 +144,7 @@ public class DialogsConfigElement extends ConfigElementAdapter
this.name = name;
this.page = page;
this.managedBean = bean;
this.actionsConfigId = actionsConfigId;
this.icon = icon;
this.title = title;
this.titleId = titleId;
@@ -164,6 +167,11 @@ public class DialogsConfigElement extends ConfigElementAdapter
return this.managedBean;
}
public String getActionsConfigId()
{
return this.actionsConfigId;
}
public String getName()
{
return this.name;
@@ -199,6 +207,7 @@ public class DialogsConfigElement extends ConfigElementAdapter
buffer.append(" (name=").append(this.name);
buffer.append(" page=").append(this.page);
buffer.append(" managed-bean=").append(this.managedBean);
buffer.append(" actions-config-id=").append(this.actionsConfigId);
buffer.append(" icon=").append(this.icon);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);

View File

@@ -35,6 +35,7 @@ public class DialogsElementReader implements ConfigElementReader
public static final String ATTR_NAME = "name";
public static final String ATTR_PAGE = "page";
public static final String ATTR_MANAGED_BEAN = "managed-bean";
public static final String ATTR_ACTIONS_CONFIG_ID = "actions-config-id";
public static final String ATTR_ICON = "icon";
public static final String ATTR_TITLE = "title";
public static final String ATTR_TITLE_ID = "title-id";
@@ -69,6 +70,7 @@ public class DialogsElementReader implements ConfigElementReader
String name = item.attributeValue(ATTR_NAME);
String page = item.attributeValue(ATTR_PAGE);
String bean = item.attributeValue(ATTR_MANAGED_BEAN);
String actions = item.attributeValue(ATTR_ACTIONS_CONFIG_ID);
String icon = item.attributeValue(ATTR_ICON);
String title = item.attributeValue(ATTR_TITLE);
String titleId = item.attributeValue(ATTR_TITLE_ID);
@@ -76,7 +78,8 @@ public class DialogsElementReader implements ConfigElementReader
String descriptionId = item.attributeValue(ATTR_DESCRIPTION_ID);
DialogsConfigElement.DialogConfig cfg = new DialogsConfigElement.DialogConfig(
name, page, bean, icon, title, titleId, description, descriptionId);
name, page, bean, actions, icon, title, titleId, description,
descriptionId);
configElement.addDialog(cfg);
}

View File

@@ -618,6 +618,8 @@ public class WebClientConfigTest extends BaseTest
assertEquals("name", "createSpace", dialog.getName());
assertEquals("page", "/jsp/dialog/create-space.jsp", dialog.getPage());
assertEquals("managed-bean", "NewSpaceDialog", dialog.getManagedBean());
assertEquals("actions-config-id", "space-actions", dialog.getActionsConfigId());
assertEquals("icon", "/images/icons/create_space_large.gif", dialog.getIcon());
assertEquals("title-id", "create_space_title", dialog.getTitleId());
assertEquals("description-id", "create_space_description", dialog.getDescriptionId());
assertNull("title should be null", dialog.getTitle());
@@ -631,6 +633,8 @@ public class WebClientConfigTest extends BaseTest
assertEquals("name", "spaceDetails", dialog.getName());
assertEquals("page", "/jsp/dialog/space-details.jsp", dialog.getPage());
assertEquals("managed-bean", "SpaceDetailsDialog", dialog.getManagedBean());
assertEquals("actions-config-id", "space-actions", dialog.getActionsConfigId());
assertEquals("icon", "/images/icons/create_space_large.gif", dialog.getIcon());
assertEquals("title", "Space Details Dialog", dialog.getTitle());
assertEquals("description", "Space Details Dialog Decsription", dialog.getDescription());
assertNull("title-id should be null", dialog.getTitleId());
@@ -699,16 +703,27 @@ public class WebClientConfigTest extends BaseTest
assertEquals("name", "exampleWizard", wizard.getName());
assertEquals("exampleWizard steps", 2, wizard.getNumberSteps());
assertEquals("managed-bean", "ExampleWizard", wizard.getManagedBean());
assertEquals("actions-config-id", "example-wizard-actions", wizard.getActionsConfigId());
assertEquals("icon", "/images/icons/example-logo.gif", wizard.getIcon());
assertEquals("title", "Example Wizard Title", wizard.getTitle());
assertEquals("description", "Example Wizard Description", wizard.getDescription());
assertNull("title-id should be null", wizard.getTitleId());
assertNull("description-id should be null", wizard.getDescriptionId());
// retrive step 1 config and check it is correct
Map<String, StepConfig> stepsMap = wizard.getSteps();
StepConfig step1 = stepsMap.get("details");
assertNotNull("step 1 of example wizard should not be null", step1);
assertEquals("step title", "Details", step1.getTitle());
assertNull("step 1 title-id should be null", step1.getTitleId());
// get the 'createSpace' wizard and ensure all the data is correct
wizard = wizardsElement.getWizard("createSpace");
assertEquals("name", "createSpace", wizard.getName());
assertEquals("createSpace steps", 3, wizard.getNumberSteps());
assertEquals("managed-bean", "AdvancedSpaceWizard", wizard.getManagedBean());
assertEquals("actions-config-id", "create-space-actions", wizard.getActionsConfigId());
assertEquals("icon", "/images/icons/create_space_large.gif", wizard.getIcon());
assertEquals("title-id", "advanced_space_details_title", wizard.getTitleId());
assertEquals("description-id", "advanced_space_details_description", wizard.getDescriptionId());
assertNull("title should be null", wizard.getTitle());
@@ -717,8 +732,9 @@ public class WebClientConfigTest extends BaseTest
assertNotNull("steps should not be null", steps);
// retrieve step1 information and check it is correct
StepConfig step1 = steps.get(0);
step1 = steps.get(0);
assertEquals("step 1 name", "details", step1.getName());
assertEquals("step 1 title-id", "starting_space", step1.getTitleId());
assertFalse("step 1 should not have conditional pages", step1.hasConditionalPages());
PageConfig step1Page = step1.getDefaultPage();
assertNotNull("step1Page should not be null", step1Page);
@@ -732,6 +748,7 @@ public class WebClientConfigTest extends BaseTest
// check the conditional step2 data
StepConfig step2 = steps.get(1);
assertEquals("step 2 name", "properties", step2.getName());
assertEquals("step 2 title-id", "space_options", step2.getTitleId());
assertTrue("step 2 should have conditional pages", step2.hasConditionalPages());
PageConfig step2DefaultPage = step2.getDefaultPage();
assertNotNull("step 2 default page should not be null", step2DefaultPage);
@@ -756,6 +773,7 @@ public class WebClientConfigTest extends BaseTest
// check step 3 data
StepConfig step3 = steps.get(2);
assertEquals("step 3 name", "summary", step3.getName());
assertEquals("step 3 title-id", "summary", step3.getTitleId());
assertFalse("step 3 should not have conditional pages", step3.hasConditionalPages());
PageConfig step3Page = step3.getDefaultPage();
assertNotNull("step3Page should not be null", step3Page);

View File

@@ -85,16 +85,6 @@ public class WizardsConfigElement extends ConfigElementAdapter
return combined;
}
/**
* Adds a wizard
*
* @param wizardConfig A pre-configured wizard config object
*/
/*package*/ void addWizard(WizardConfig wizardConfig)
{
this.wizards.put(wizardConfig.getName(), wizardConfig);
}
/**
* Returns the named wizard
*
@@ -114,6 +104,16 @@ public class WizardsConfigElement extends ConfigElementAdapter
return this.wizards;
}
/**
* Adds a wizard
*
* @param wizardConfig A pre-configured wizard config object
*/
/*package*/ void addWizard(WizardConfig wizardConfig)
{
this.wizards.put(wizardConfig.getName(), wizardConfig);
}
public abstract static class AbstractConfig
{
protected String title;
@@ -159,9 +159,11 @@ public class WizardsConfigElement extends ConfigElementAdapter
protected String name;
protected String managedBean;
protected String icon;
protected String actionsConfigId;
protected Map<String, StepConfig> steps = new LinkedHashMap<String, StepConfig>(4);
public WizardConfig(String name, String bean, String icon,
public WizardConfig(String name, String bean,
String actionsConfigId, String icon,
String title, String titleId,
String description, String descriptionId)
{
@@ -173,6 +175,7 @@ public class WizardsConfigElement extends ConfigElementAdapter
this.name = name;
this.managedBean = bean;
this.icon = icon;
this.actionsConfigId = actionsConfigId;
}
public String getName()
@@ -190,9 +193,9 @@ public class WizardsConfigElement extends ConfigElementAdapter
return this.icon;
}
public void addStep(StepConfig step)
public String getActionsConfigId()
{
this.steps.put(step.getName(), step);
return this.actionsConfigId;
}
public int getNumberSteps()
@@ -222,6 +225,11 @@ public class WizardsConfigElement extends ConfigElementAdapter
return this.steps.get(name);
}
/*package*/ void addStep(StepConfig step)
{
this.steps.put(step.getName(), step);
}
/**
* @see java.lang.Object#toString()
*/
@@ -231,6 +239,7 @@ public class WizardsConfigElement extends ConfigElementAdapter
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (name=").append(this.name);
buffer.append(" managed-bean=").append(this.managedBean);
buffer.append(" actions-config-id=").append(this.actionsConfigId);
buffer.append(" icon=").append(this.icon);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
@@ -347,18 +356,28 @@ public class WizardsConfigElement extends ConfigElementAdapter
* Represents the configuration of a step in a wizard
* i.e. the &lt;step&gt; element.
*/
public static class StepConfig
public static class StepConfig extends AbstractConfig
{
protected String name;
protected PageConfig defaultPage;
protected List<ConditionalPageConfig> conditionalPages =
new ArrayList<ConditionalPageConfig>(3);
public StepConfig(String name)
public StepConfig(String name,
String title, String titleId,
String description, String descriptionId)
{
super(title, titleId, description, descriptionId);
// check we have a name
ParameterCheck.mandatoryString("name", name);
// check we have a title
if (this.title == null && this.titleId == null)
{
throw new IllegalArgumentException("A title or title-id attribute must be supplied for a step");
}
this.name = name;
}
@@ -367,11 +386,6 @@ public class WizardsConfigElement extends ConfigElementAdapter
return this.name;
}
public void setDefaultPage(PageConfig page)
{
this.defaultPage = page;
}
public PageConfig getDefaultPage()
{
return this.defaultPage;
@@ -382,14 +396,19 @@ public class WizardsConfigElement extends ConfigElementAdapter
return (this.conditionalPages.size() > 0);
}
public void addConditionalPage(ConditionalPageConfig conditionalPage)
public List<ConditionalPageConfig> getConditionalPages()
{
return this.conditionalPages;
}
/*package*/ void addConditionalPage(ConditionalPageConfig conditionalPage)
{
this.conditionalPages.add(conditionalPage);
}
public List<ConditionalPageConfig> getConditionalPages()
/*package*/ void setDefaultPage(PageConfig page)
{
return this.conditionalPages;
this.defaultPage = page;
}
/**
@@ -400,6 +419,10 @@ public class WizardsConfigElement extends ConfigElementAdapter
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (name=").append(this.name);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
buffer.append(" description=").append(this.description);
buffer.append(" descriptionId=").append(this.descriptionId);
buffer.append(" defaultPage=").append(this.defaultPage);
buffer.append(" conditionalPages=").append(this.conditionalPages).append(")");
return buffer.toString();

View File

@@ -41,6 +41,7 @@ public class WizardsElementReader implements ConfigElementReader
public static final String ATTR_NAME = "name";
public static final String ATTR_MANAGED_BEAN = "managed-bean";
public static final String ATTR_ACTIONS_CONFIG_ID = "actions-config-id";
public static final String ATTR_ICON = "icon";
public static final String ATTR_TITLE = "title";
public static final String ATTR_TITLE_ID = "title-id";
@@ -78,6 +79,7 @@ public class WizardsElementReader implements ConfigElementReader
String name = wizard.attributeValue(ATTR_NAME);
String bean = wizard.attributeValue(ATTR_MANAGED_BEAN);
String actions = wizard.attributeValue(ATTR_ACTIONS_CONFIG_ID);
String icon = wizard.attributeValue(ATTR_ICON);
String title = wizard.attributeValue(ATTR_TITLE);
String titleId = wizard.attributeValue(ATTR_TITLE_ID);
@@ -86,7 +88,7 @@ public class WizardsElementReader implements ConfigElementReader
// create the wizard config object
WizardsConfigElement.WizardConfig wizardCfg = new WizardsConfigElement.WizardConfig(
name, bean, icon, title, titleId, description, descriptionId);
name, bean, actions, icon, title, titleId, description, descriptionId);
Iterator<Element> steps = wizard.elementIterator(ELEMENT_STEP);
while (steps.hasNext())
@@ -111,7 +113,13 @@ public class WizardsElementReader implements ConfigElementReader
protected StepConfig parseStep(Element step)
{
// get the name of the step and create the config object
StepConfig stepCfg = new StepConfig(step.attributeValue(ATTR_NAME));
String stepName = step.attributeValue(ATTR_NAME);
String stepTitle = step.attributeValue(ATTR_TITLE);
String stepTitleId = step.attributeValue(ATTR_TITLE_ID);
String stepDescription = step.attributeValue(ATTR_DESCRIPTION);
String stepDescriptionId = step.attributeValue(ATTR_DESCRIPTION_ID);
StepConfig stepCfg = new StepConfig(stepName, stepTitle, stepTitleId,
stepDescription, stepDescriptionId);
// find and parse the default page
Element defaultPageElem = step.element(ELEMENT_PAGE);

View File

@@ -175,7 +175,10 @@ public class ImagePickerRadioRenderer extends BaseRenderer
while (iter.hasNext())
{
UIListItem item = (UIListItem)iter.next();
renderItem(context, out, imagePicker, item, onclick);
if (item.isRendered())
{
renderItem(context, out, imagePicker, item, onclick);
}
}
}
}

View File

@@ -17,6 +17,7 @@
package org.alfresco.web.ui.common.renderer;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -28,6 +29,7 @@ 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.UIListItems;
import org.alfresco.web.ui.common.component.UIMenu;
import org.alfresco.web.ui.common.component.UIModeList;
@@ -213,116 +215,35 @@ public class ModeListRenderer extends BaseRenderer
}
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)
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();
if (item.isRendered())
{
renderItem(context, out, list, item);
}
}
}
}
else 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>");
}
renderItem(context, out, list, item);
}
}
}
@@ -361,6 +282,118 @@ public class ModeListRenderer extends BaseRenderer
return true;
}
/**
* Renders the given item for the given list
*
* @param context FacesContext
* @param out ResponseWriter to write to
* @param list The parent list
* @param item The item to render
* @throws IOException
*/
protected void renderItem(FacesContext context, ResponseWriter out,
UIModeList list, UIListItem item) throws IOException
{
Map attrs = list.getAttributes();
String selectedImage = (String)attrs.get("selectedImage");
// 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)item.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)item.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, item.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>");
}
}
/**
* 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