/* 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 java.util.Iterator; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.html.IHeaderResponse; import org.apache.wicket.model.IModel; import org.apache.wicket.request.resource.CssResourceReference; import wickettree.ITreeProvider; import wickettree.NestedTree; 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.Indexed; 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.TextSubTaskDef; import de.elatexam.model.TextTaskBlock; /** * @author Steffen Dienst * */ public class ComplexTaskDefTree<T extends Indexed> extends NestedTree<T> { final static ImmutableMap<Class<?>, String[]> tranferTypes = new ImmutableMap.Builder<Class<?>, String[]>() .put(MappingTaskBlock.class, new String[]{"mapping", "category"}) .put(MappingSubTaskDef.class, new String[]{"mapping"}) .put(McTaskBlock.class, new String[]{"mc", "category"}) .put(McSubTaskDef.class, new String[]{"mc"}) .put(ClozeTaskBlock.class, new String[]{"cloze", "category"}) .put(ClozeSubTaskDef.class, new String[]{"cloze"}) .put(PaintTaskBlock.class, new String[]{"paint", "category"}) .put(PaintSubTaskDef.class, new String[]{"paint"}) .put(TextTaskBlock.class, new String[]{"text", "category"}) .put(TextSubTaskDef.class, new String[]{"text"}) .put(Category.class, new String[]{"category"}) .put(BasicUser.class,new String[]{"user"}) .put(ComplexTaskDef.class,new String[]{"complextask"}) .build(); final static ImmutableMap<Class<?>, String> dragStarts = new ImmutableMap.Builder<Class<?>, String>() .put(MappingSubTaskDef.class, "a.tree-mapping.subtaskdef") .put(McSubTaskDef.class, "a.tree-mc.subtaskdef") .put(ClozeSubTaskDef.class, "a.tree-cloze.subtaskdef") .put(PaintSubTaskDef.class, "a.tree-paint.subtaskdef") .put(TextSubTaskDef.class, "a.tree-text.subtaskdef") .put(MappingTaskBlock.class, "a.tree-mapping.taskblock") .put(McTaskBlock.class, "a.tree-mc.taskblock") .put(ClozeTaskBlock.class, "a.tree-cloze.taskblock") .put(PaintTaskBlock.class, "a.tree-paint.taskblock") .put(TextTaskBlock.class, "a.tree-text.taskblock") .build(); private IModel<ComplexTaskDef> currentTaskdef; private IModel<T> selectedModel; /** * @param id * @param provider */ public ComplexTaskDefTree(final String id, final ComplexTaskdefTreeProvider provider) { super(id, provider); } /* (non-Javadoc) * @see org.apache.wicket.Component#renderHead(org.apache.wicket.markup.html.IHeaderResponse) */ @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); response.renderCSSReference(new CssResourceReference(ComplexTaskDefTree.class, "theme/theme.css")); } /* * (non-Javadoc) * * @see org.apache.wicket.Component#detachModels() */ @Override public void detachModels() { super.detachModels(); if (selectedModel != null) { selectedModel.detach(); } if (currentTaskdef != null) { currentTaskdef.detach(); } } public IModel<ComplexTaskDef> getCurrentTaskdef() { return currentTaskdef; } /* (non-Javadoc) * @see wickettree.AbstractTree#newContentComponent(java.lang.String, org.apache.wicket.model.IModel) */ @Override protected Component newContentComponent(final String id, final IModel model) { return new TaskTreeElement(id, this, model); } /** * Inform the tree about the selection. This is needed to be able to fire a {@link TreeSelectionEvent}. * * @param model * @param tree2 * @param target */ void select(final IModel<T> model, final AjaxRequestTarget target) { if (selectedModel != null && selectedModel.getObject() != null) { // redraw the now deselected node updateNode(selectedModel.getObject(), target); selectedModel.detach(); selectedModel = null; } selectedModel = model; updateNode(model.getObject(), target); this.currentTaskdef = (IModel<ComplexTaskDef>) findCurrentTaskDef(model); send(getPage(),Broadcast.BREADTH,target); } /** * traverse parents to find taskdef predecessor for every object! * * @param selected */ private IModel<T> findCurrentTaskDef(final IModel<T> selected) { if (isComplextask(selected)) return selected; final ITreeProvider<T> prov = getProvider(); final Iterator<? extends T> it = prov.getRoots(); while (it.hasNext()) { final IModel<T> root = prov.model(it.next()); final IModel<T> ctdModel = findTaskDefThatContains(selected, root); if (ctdModel != null) return ctdModel; } return null; } /** * @param selected * @return */ private boolean isComplextask(final IModel<T> selected) { return selected.getObject().getClass().equals(ComplexTaskDef.class); } private IModel<T> findTaskDefThatContains(final IModel<T> selected, final IModel<T> currentNode) { final ITreeProvider<T> provider = getProvider(); if (currentNode.equals(selected)) return currentNode; else if (provider.hasChildren(currentNode.getObject())) { final Iterator<? extends T> childrenIterator = provider.getChildren(currentNode.getObject()); while (childrenIterator.hasNext()) { final IModel<T> inSubtree = findTaskDefThatContains(selected, provider.model(childrenIterator.next())); if (inSubtree != null) { if (inSubtree.getObject().getClass().equals(ComplexTaskDef.class)) return inSubtree; else return currentNode; } } } return null; } /** * Return model of the currently selected node. * * @return */ public IModel<T> getSelected() { return selectedModel; } /* (non-Javadoc) * @see org.apache.wicket.Component#onEvent(org.apache.wicket.event.IEvent) */ @Override public void onEvent(IEvent<?> event) { super.onEvent(event); if(event.getPayload() instanceof AjaxRequestTarget) ((AjaxRequestTarget) event.getPayload()).add(this); } }