/* Copyright (C) 2009 Steffen Dienst This program 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; either version 2 of the License, or (at your option) any later version. This program 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package de.elatexam.editor.components.panels.tree; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import wicketdnd.Operation; import wickettree.AbstractTree; import wickettree.AbstractTree.State; import wickettree.ITreeProvider; import wickettree.content.StyledLinkLabel; import com.google.common.collect.ImmutableMap; import de.elatexam.editor.user.BasicUser; import de.elatexam.model.Category; import de.elatexam.model.ClozeSubTaskDef; import de.elatexam.model.ClozeTaskBlock; import de.elatexam.model.ComplexTaskDef; import de.elatexam.model.MappingSubTaskDef; import de.elatexam.model.MappingTaskBlock; import de.elatexam.model.McSubTaskDef; import de.elatexam.model.McTaskBlock; import de.elatexam.model.PaintSubTaskDef; import de.elatexam.model.PaintTaskBlock; import de.elatexam.model.SubTaskDef; import de.elatexam.model.TaskBlock; import de.elatexam.model.TextSubTaskDef; import de.elatexam.model.TextTaskBlock; /** * @author Steffen Dienst * */ public class TaskTreeElement<T> extends StyledLinkLabel<T> { final static ImmutableMap<Class<?>, String> expressions = new ImmutableMap.Builder<Class<?>, String>() .put(ComplexTaskDef.class, "title") .put(Category.class, "title") .put(BasicUser.class, "username") .put(McTaskBlock.class, "class.simpleName") .put(MappingTaskBlock.class, "class.simpleName") .put(ClozeTaskBlock.class, "class.simpleName") .put(TextTaskBlock.class, "class.simpleName") .put(PaintTaskBlock.class, "class.simpleName") .put(McSubTaskDef.class, "xmlid") .put(MappingSubTaskDef.class, "xmlid") .put(ClozeSubTaskDef.class, "xmlid") .put(TextSubTaskDef.class, "xmlid") .put(PaintSubTaskDef.class, "xmlid") .build(); final static ImmutableMap<Class<?>, String> styleClasses = new ImmutableMap.Builder<Class<?>, String>() .put(BasicUser.class, "tree-user") .put(ComplexTaskDef.class, "tree-exam") .put(McTaskBlock.class, "tree-mc taskblock") .put(MappingTaskBlock.class, "tree-mapping taskblock") .put(ClozeTaskBlock.class, "tree-cloze taskblock") .put(TextTaskBlock.class, "tree-text taskblock") .put(PaintTaskBlock.class, "tree-paint taskblock") .put(McSubTaskDef.class, "tree-mc subtaskdef") .put(MappingSubTaskDef.class, "tree-mapping subtaskdef") .put(ClozeSubTaskDef.class, "tree-cloze subtaskdef") .put(TextSubTaskDef.class, "tree-text subtaskdef") .put(PaintSubTaskDef.class, "tree-paint subtaskdef") .build(); private final ComplexTaskDefTree tree; public TaskTreeElement(final String id, final ComplexTaskDefTree tree, final IModel<T> model) { super(id, model); this.tree = tree; add(new TypedDragSource(model.getObject().getClass(), Operation.MOVE, Operation.COPY)); add(new TypedDropTarget(model.getObject().getClass(), tree, Operation.MOVE, Operation.COPY)); } protected String getClosedStyleClass() { return "tree-folder-closed category"; } protected String getOpenStyleClass() { return "tree-folder-open category"; } /** * Get a style class for anything other than closed or open folders. */ protected String getOtherStyleClass(final T t) { return "tree-folder-other"; } /** * Get a style class to render for a selected folder. * * @see #isSelected() */ protected String getSelectedStyleClass() { return "selected"; } /** * Delegates to others methods depending wether the given model is a folder, * expanded, collapsed or selected. * * @see ITreeProvider#hasChildren(Object) * @see AbstractTree#getState(Object) * @see #isSelected() * @see #getOpenStyleClass() * @see #getClosedStyleClass() * @see #getOtherStyleClass(Object) * @see #getSelectedStyleClass() */ @Override protected String getStyleClass() { // TODO add error icons for invalid model elements final T t = getModelObject(); String styleClass; if (t instanceof Category) { if (tree.getState(t) == State.EXPANDED) { styleClass = getOpenStyleClass(); } else { styleClass = getClosedStyleClass(); } } else { styleClass = getOtherStyleClass(t); } // overwrite syle class for specific model classes (uses custom icons) final String configuredClass = styleClasses.get(t.getClass()); if (configuredClass != null) { styleClass = configuredClass; } if (getModel().equals(tree.getSelected())) { styleClass += " " + getSelectedStyleClass(); } return styleClass; } /** * Always clickable. * * @see ITreeProvider#hasChildren(Object) */ @Override protected boolean isClickable() { return true; } /* * (non-Javadoc) * * @see * wickettree.content.StyledLinkLabel#newLabelModel(org.apache.wicket.model * .IModel) */ @Override protected IModel<String> newLabelModel(final IModel<T> model) { final Object o = model.getObject(); final IModel<String> defaultModel = new PropertyModel<String>(model, expressions.get(o.getClass())); if (o instanceof TaskBlock) return Model.of("Aufgaben"); else if (o instanceof SubTaskDef) return new PropertyModel<String>(model, "xmlid"); return defaultModel; } /** * Toggle the node's {@link State} on click. */ @Override protected void onClick(final AjaxRequestTarget target) { final T t = getModelObject(); if (tree.getState(t) == State.COLLAPSED) { tree.expand(t); } tree.select(getModel(), target); } }