///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition 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 General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.plugins.skillmatrix; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; import org.apache.wicket.extensions.markup.html.repeater.data.table.HeadersToolbar; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar; import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree; import org.apache.wicket.extensions.markup.html.repeater.tree.TableTree; import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder; import org.apache.wicket.extensions.markup.html.repeater.tree.table.NodeBorder; import org.apache.wicket.extensions.markup.html.repeater.tree.table.NodeModel; import org.apache.wicket.extensions.markup.html.repeater.tree.table.TreeColumn; import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.OddEvenItem; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.projectforge.registry.Registry; import org.projectforge.web.fibu.ISelectCallerPage; import org.projectforge.web.wicket.AbstractListPage; import org.projectforge.web.wicket.AbstractSecuredPage; import org.projectforge.web.wicket.CellItemListener; import org.projectforge.web.wicket.CellItemListenerPropertyColumn; import org.projectforge.web.wicket.ListSelectActionPanel; /** * @author Billy Duong (b.duong@micromata.de) * */ public class SkillTreeBuilder implements Serializable { private static final long serialVersionUID = -5283360078497855756L; private final Behavior theme = new WindowsTheme(); private TableTree<SkillNode, String> tree; private AbstractSecuredPage parentPage; private Integer highlightedSkillNodeId; private boolean selectMode, showRootNode; private ISelectCallerPage caller; private String selectProperty; @SuppressWarnings("serial") public AbstractTree<SkillNode> createTree(final String id, final AbstractSecuredPage parentPage, final SkillFilter skillFilter) { this.parentPage = parentPage; final List<IColumn<SkillNode, String>> columns = createColumns(); tree = new TableTree<SkillNode, String>(id, columns, new SkillTreeProvider(skillFilter).setShowRootNode(showRootNode), Integer.MAX_VALUE, SkillTreeExpansion.getExpansionModel()) { private static final long serialVersionUID = 1L; @Override protected Component newContentComponent(final String id, final IModel<SkillNode> model) { return SkillTreeBuilder.this.newContentComponent(id, this, model); } @Override protected Item<SkillNode> newRowItem(final String id, final int index, final IModel<SkillNode> model) { return new OddEvenItem<SkillNode>(id, index, model); } }; tree.getTable().addTopToolbar(new HeadersToolbar<String>(tree.getTable(), null)); tree.getTable().addBottomToolbar(new NoRecordsToolbar(tree.getTable())); tree.add(new Behavior() { @Override public void onComponentTag(final Component component, final ComponentTag tag) { theme.onComponentTag(component, tag); } @Override public void renderHead(final Component component, final IHeaderResponse response) { theme.renderHead(component, response); } }); tree.getTable().add(AttributeModifier.append("class", "tableTree")); return tree; } /** * @return */ @SuppressWarnings("serial") private List<IColumn<SkillNode, String>> createColumns() { final CellItemListener<SkillNode> cellItemListener = new CellItemListener<SkillNode>() { public void populateItem(final Item<ICellPopulator<SkillNode>> item, final String componentId, final IModel<SkillNode> rowModel) { final SkillNode skillNode = rowModel.getObject(); SkillListPage.appendCssClasses(item, skillNode.getSkill(), highlightedSkillNodeId); } }; final List<IColumn<SkillNode, String>> columns = new ArrayList<IColumn<SkillNode, String>>(); final TreeColumn<SkillNode, String> title = new TreeColumn<SkillNode, String>(new ResourceModel("plugins.skillmatrix.skill.title")) { @Override public void populateItem(final Item<ICellPopulator<SkillNode>> cellItem, final String componentId, final IModel<SkillNode> rowModel) { final RepeatingView view = new RepeatingView(componentId); cellItem.add(view); final SkillNode skillNode = rowModel.getObject(); if (selectMode == false) { view.add(new ListSelectActionPanel(view.newChildId(), rowModel, SkillEditPage.class, skillNode.getId(), parentPage, "")); } else { view.add(new ListSelectActionPanel(view.newChildId(), rowModel, caller, selectProperty, skillNode.getId(), "")); } AbstractListPage.addRowClick(cellItem); final NodeModel<SkillNode> nodeModel = (NodeModel<SkillNode>) rowModel; final Component nodeComponent = getTree().newNodeComponent(view.newChildId(), nodeModel.getWrappedModel()); nodeComponent.add(new NodeBorder(nodeModel.getBranches())); view.add(nodeComponent); cellItemListener.populateItem(cellItem, componentId, rowModel); } }; final CellItemListenerPropertyColumn<SkillNode> created = new CellItemListenerPropertyColumn<SkillNode>(new ResourceModel( "created"), null, "skill.created", cellItemListener); final CellItemListenerPropertyColumn<SkillNode> lastUpdate = new CellItemListenerPropertyColumn<SkillNode>(new ResourceModel( "lastUpdate"), null, "skill.lastUpdate", cellItemListener); final CellItemListenerPropertyColumn<SkillNode> description = new CellItemListenerPropertyColumn<SkillNode>(new ResourceModel( "plugins.skillmatrix.skill.description"), null, "skill.description", cellItemListener); final CellItemListenerPropertyColumn<SkillNode> comment = new CellItemListenerPropertyColumn<SkillNode>(new ResourceModel( "plugins.skillmatrix.skill.comment"), null, "skill.comment", cellItemListener); final CellItemListenerPropertyColumn<SkillNode> rateable = new CellItemListenerPropertyColumn<SkillNode>(new ResourceModel( "plugins.skillmatrix.skill.rateable"), null, "skill.rateable", cellItemListener); columns.add(title); columns.add(description); columns.add(comment); columns.add(rateable); columns.add(created); columns.add(lastUpdate); return columns; } protected void addColumn(final WebMarkupContainer parent, final Component component, final String cssStyle) { if (cssStyle != null) { component.add(AttributeModifier.append("style", new Model<String>(cssStyle))); } parent.add(component); } /** * @param id * @param model * @return */ @SuppressWarnings("serial") protected Component newContentComponent(final String id, final TableTree<SkillNode, String> tree, final IModel<SkillNode> model) { return new Folder<SkillNode>(id, tree, model) { @Override protected IModel< ? > newLabelModel(final IModel<SkillNode> model) { return new PropertyModel<String>(model, "skill.title"); } }; } /** * @param selectMode the selectMode to set * @return this for chaining. */ public SkillTreeBuilder setSelectMode(final boolean selectMode) { this.selectMode = selectMode; return this; } /** * @param showRootNode the showRootNode to set * @return this for chaining. */ public SkillTreeBuilder setShowRootNode(final boolean showRootNode) { this.showRootNode = showRootNode; return this; } /** * @param caller the caller to set * @return this for chaining. */ public SkillTreeBuilder setCaller(final ISelectCallerPage caller) { this.caller = caller; return this; } /** * @param selectProperty the selectProperty to set * @return this for chaining. */ public SkillTreeBuilder setSelectProperty(final String selectProperty) { this.selectProperty = selectProperty; return this; } /** * @param highlightedSkillNodeId the highlightedSkillNodeId to set * @return this for chaining. */ public SkillTreeBuilder setHighlightedSkillNodeId(final Integer highlightedSkillNodeId) { this.highlightedSkillNodeId = highlightedSkillNodeId; final SkillNode node = getSkillTree().getSkillNodeById(highlightedSkillNodeId); if (node == null) { // Shouldn't occur. return this; } // Open all ancestor nodes of the highlighted node: final Set<SkillNode> set = SkillTreeExpansion.getExpansionModel().getObject(); SkillNode parent = node.getParent(); while (parent != null) { set.add(parent); parent = parent.getParent(); } return this; } private SkillTree getSkillTree() { return Registry.instance().getDao(SkillDao.class).getSkillTree(); } }