/** * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.webui.core; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import org.exoplatform.commons.serialization.api.annotations.Serialized; import org.exoplatform.commons.utils.HTMLEntityEncoder; import org.exoplatform.util.ReflectionUtil; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.config.annotation.EventConfig; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.event.EventListener; import org.exoplatform.webui.form.UIForm; /** * Author : Nhu Dinh Thuan nhudinhthuan@exoplatform.com Jul 7, 2006 * * A component that represents a tree. Can contain a UIRightClickPopupMenu * * @see UIRightClickPopupMenu */ @ComponentConfig(template = "system:/groovy/webui/core/UITree.gtmpl", events = @EventConfig(listeners = UITree.ChangeNodeActionListener.class)) @Serialized public class UITree extends UIComponent { /** * The css class name to show the expand icon */ private String expandIcon = "ExpandIcon"; /** * The css class name to show the collapse icon */ private String colapseIcon = "CollapseIcon"; /** * The css class name to show the null icon (item has no child) */ private String nullItemIcon = "NullItemIcon"; /** * The css class name to show the selected icon */ private String selectedIcon = ""; private String icon = ""; /** * The bean field that holds the id of the bean */ private String beanIdField_; /** * The bean field that holds the count number of the children This help to express the node have childs or not */ private String beanChildCountField_; /** * The bean field that holds the label of the bean */ private String beanLabelField_; /** * The bean field that holds the icon of the bean */ private String beanIconField_ = ""; /** * The field that holds max character's title of node */ private Integer maxTitleCharacter_ = 0; /** * A list of sibling nodes */ private Collection<?> sibbling; /** * A list of children nodes */ private Collection<?> children; /** * The selected node */ private Object selected; /** * The parent node of the selected node */ private Object parentSelected; /** * A right click popup menu */ private UIRightClickPopupMenu uiPopupMenu_; /** * Encode the value before rendering or not */ private boolean escapeHTML_ = false; public Object getFieldValue(Object bean, String field) throws Exception { Method method = ReflectionUtil.getGetBindingMethod(bean, field); return method.invoke(bean, ReflectionUtil.EMPTY_ARGS); } public void setBeanIdField(String beanIdField_) { this.beanIdField_ = beanIdField_; } public void setBeanIconField(String beanIconField_) { this.beanIconField_ = beanIconField_; } public void setBeanLabelField(String beanLabelField_) { this.beanLabelField_ = beanLabelField_; } public void setBeanChildCountField(String beanChildCountField) { this.beanChildCountField_ = beanChildCountField; } public Object getId(Object object) throws Exception { return getFieldValue(object, beanIdField_); } public String getActionLink() throws Exception { if (selected == null) return "#"; if (parentSelected == null) return event("ChangeNode"); return event("ChangeNode", (String) getId(parentSelected)); } // TODO review equals object with id public boolean isSelected(Object obj) throws Exception { if (selected == null) return false; return getId(obj).equals(getId(selected)); } public String getColapseIcon() { return colapseIcon; } public void setCollapseIcon(String colapseIcon) { this.colapseIcon = colapseIcon; } public String getExpandIcon() { return expandIcon; } public void setExpandIcon(String expandIcon) { this.expandIcon = expandIcon; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getSelectedIcon() { return selectedIcon; } public void setSelectedIcon(String selectedIcon) { this.selectedIcon = selectedIcon; } public Collection<?> getChildren() { return children; } public void setChildren(Collection<?> children) { this.children = children; } @SuppressWarnings("unchecked") public <T> T getSelected() { return (T) selected; } public void setSelected(Object selectedObject) { this.selected = selectedObject; } @SuppressWarnings("unchecked") public <T> T getParentSelected() { return (T) parentSelected; } public void setParentSelected(Object parentSelected) { this.parentSelected = parentSelected; } public Collection<?> getSibbling() { return sibbling; } public void setSibbling(Collection<?> sibbling) { this.sibbling = sibbling; } public UIRightClickPopupMenu getUIRightClickPopupMenu() { return uiPopupMenu_; } public void setUIRightClickPopupMenu(UIRightClickPopupMenu uiPopupMenu) { uiPopupMenu_ = uiPopupMenu; if (uiPopupMenu_ != null) uiPopupMenu_.setParent(this); } public void setEscapeHTML(boolean escape) { escapeHTML_ = escape; } public boolean getEscapeHTML() { return escapeHTML_; } public String event(String name, String beanId) throws Exception { UIForm uiForm = getAncestorOfType(UIForm.class); if (uiForm != null) return uiForm.event(name, getId(), beanId); return super.event(name, beanId); } public String renderNode(Object obj) throws Exception { String nodeIcon = expandIcon; String iconGroup = icon; String note = ""; if (isSelected(obj)) { nodeIcon = colapseIcon; iconGroup = selectedIcon; note = " NodeSelected"; } if (getBeanChildCountField() != null) { Object childCount = getFieldValue(obj, getBeanChildCountField()); if (childCount != null && childCount.getClass().isAssignableFrom(Integer.class) && (Integer) childCount == 0) { nodeIcon = nullItemIcon; } } if (beanIconField_ != null && beanIconField_.length() > 0) { if (getFieldValue(obj, beanIconField_) != null) iconGroup = (String) getFieldValue(obj, beanIconField_); } String objId = String.valueOf(getId(obj)); String actionLink = event("ChangeNode", objId); String fieldValue = (String) getFieldValue(obj, beanLabelField_); StringBuilder builder = new StringBuilder(); // if field's length > max field's length then cut field value if ((fieldValue.length() > getMaxTitleCharacter()) && (getMaxTitleCharacter() != 0)) { fieldValue = fieldValue.substring(0, getMaxTitleCharacter() - 3) + "..."; } if (escapeHTML_) { fieldValue = fieldValue != null ? HTMLEntityEncoder.getInstance().encode(fieldValue) : fieldValue; } if (nodeIcon.equals(expandIcon)) { builder.append(" <div class=\"").append(nodeIcon).append("\" onclick=\"").append(actionLink).append("\">"); } else if (nodeIcon.equals(colapseIcon)) { builder.append(" <div class=\"").append(nodeIcon).append("\">"); } else {// Null item builder.append(" <div class=\"").append(nodeIcon).append("\" onclick=\"").append(actionLink).append("\">"); } if (uiPopupMenu_ == null) { builder.append(" <a href=\"javascript:void(0);\" class=\"NodeIcon ").append(iconGroup).append(note).append("\"") .append(" title=\"").append(fieldValue).append("\"").append(">") .append(fieldValue).append("</a>"); } else { builder.append("<a href=\"javascript:void(0);\" class=\"NodeIcon ").append(iconGroup).append(note).append("\" ") .append(uiPopupMenu_.getJSOnclickShowPopup(objId, null)).append(" title=\"") .append(fieldValue).append("\"").append(">").append(fieldValue).append("</a>"); } builder.append(" </div>"); return builder.toString(); } public void renderUIComponent(UIComponent uicomponent) throws Exception { uicomponent.processRender((WebuiRequestContext) WebuiRequestContext.getCurrentInstance()); } @SuppressWarnings("unchecked") public <T extends UIComponent> T findComponentById(String id) { if (getId().equals(id)) return (T) this; if (uiPopupMenu_ == null) return null; return (T) uiPopupMenu_.findComponentById(id); } public <T extends UIComponent> T findFirstComponentOfType(Class<T> type) { if (type.isInstance(this)) return type.cast(this); if (uiPopupMenu_ == null) return null; return uiPopupMenu_.findFirstComponentOfType(type); } public <T> void findComponentOfType(List<T> list, Class<T> type) { if (type.isInstance(this)) list.add(type.cast(this)); if (uiPopupMenu_ == null) return; uiPopupMenu_.findComponentOfType(list, type); } public static class ChangeNodeActionListener extends EventListener<UITree> { public void execute(Event<UITree> event) throws Exception { event.getSource().<UIComponent> getParent().broadcast(event, event.getExecutionPhase()); } } public String getBeanIdField() { return beanIdField_; } public String getBeanChildCountField() { return beanChildCountField_; } public String getBeanLabelField() { return beanLabelField_; } public String getBeanIconField() { return beanIconField_; } public void setMaxTitleCharacter(Integer maxTitleCharacter_) { this.maxTitleCharacter_ = maxTitleCharacter_; } public Integer getMaxTitleCharacter() { return maxTitleCharacter_; } public UIRightClickPopupMenu getUiPopupMenu() { return uiPopupMenu_; } public void setUiPopupMenu(UIRightClickPopupMenu uiPopupMenu) { this.uiPopupMenu_ = uiPopupMenu; } public void setColapseIcon(String colapseIcon) { this.colapseIcon = colapseIcon; } }