/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. */ package org.olat.course.tree; import org.olat.core.gui.components.tree.GenericTreeModel; import org.olat.core.gui.components.tree.GenericTreeNode; import org.olat.core.gui.components.tree.TreeNode; import org.olat.core.util.nodes.INode; import org.olat.core.util.tree.INodeFilter; import org.olat.course.Structure; /** * Initial Date: Jun 3, 2004 * * @author Mike Stock */ public class PublishTreeModel extends GenericTreeModel implements INodeFilter { private static final long serialVersionUID = 8262940754776391142L; private Structure currentRunStructure; /** * Build a new publish tree model. Node proxies in the model get the ident's * of their correspondents in the CourseEditorTreeModel. * * @param cetm */ public PublishTreeModel(CourseEditorTreeModel cetm, Structure runStructure) { // build InsertModel (copy of this Structure with all possible // insert-positions) GenericTreeNode gtn = new GenericTreeNode(); gtn.setAccessible(false); gtn.setTitle(""); setRootNode(gtn); currentRunStructure = runStructure; CourseEditorTreeNode cnRoot = (CourseEditorTreeNode) cetm.getRootNode(); gtn.addChild(buildNode(cnRoot, false, false, false)); } private GenericTreeNode buildNode(CourseEditorTreeNode cetn, boolean parentIsNew, boolean parentIsDeleted, boolean parentIsMoved) { GenericTreeNode gtn = new GenericTreeNode(); gtn.setIdent(cetn.getIdent()); gtn.setTitle(cetn.getTitle()); gtn.setAltText(cetn.getAltText()); gtn.setIconCssClass("o_icon " + cetn.getIconCssClass()); if (parentIsNew || parentIsDeleted || parentIsMoved) gtn.setAccessible(false); else { gtn.setAccessible(cetn.hasPublishableChanges()); } gtn.setCssClass(cetn.getCssClass()); int childcnt = cetn.getChildCount(); if (childcnt > 0) { for (int i = 0; i < childcnt; i++) { parentIsNew = parentIsNew || cetn.isNewnode(); parentIsDeleted = parentIsDeleted || cetn.isDeleted(); parentIsMoved = parentIsMoved || isMoved(cetn); GenericTreeNode childNode = buildNode((CourseEditorTreeNode) cetn.getChildAt(i), parentIsNew, parentIsDeleted, parentIsMoved); // if this is the first new node, enable it if (!parentIsNew && cetn.isNewnode()) childNode.setAccessible(true); // if this is the first deleted node, enable it if (!parentIsDeleted && cetn.isDeleted()) childNode.setAccessible(true); // if this is the first moved node, enable it if (!parentIsMoved && isMoved(cetn)) childNode.setAccessible(true); gtn.insert(childNode, i); } } return gtn; } public boolean isMoved(CourseEditorTreeNode cetn) { if (cetn.isNewnode() || cetn.isDeleted()) { return false; } else if (currentRunStructure.getNode(cetn.getCourseNode().getIdent()) == null) { // No course node in runstructure return true; } else { INode node = currentRunStructure.getNode(cetn.getCourseNode().getIdent()); String runPath = getPositionPathFor(node); String editorPath = getPositionPathFor(cetn); return (!(runPath.equals(editorPath))) && cetn.isDirty(); // TODO: pb: Review : cetn.isDirty() added by chg to FIX OLAT-1662 } } private String getPositionPathFor(INode node) { String path = ""; INode parent = node.getParent(); if (parent == null) { path = "__root__"; } while (parent!= null) { path += parent.getIdent() + ":" + node.getPosition() + "]"; parent = parent.getParent(); } return path; } /** * Check if this publish tree node has any publishable changes. */ public boolean hasPublishableChanges() { return recursiveHasPublishableChanges(getRootNode()); } private boolean recursiveHasPublishableChanges(TreeNode currentNode) { if (currentNode.isAccessible()) return true; for (int i = 0; i < currentNode.getChildCount(); i++) { if (recursiveHasPublishableChanges((TreeNode) currentNode.getChildAt(i))) return true; } return false; } public boolean isSelectable(INode node) { TreeNode tn = (TreeNode)node; return tn.isAccessible(); } @Override public boolean isVisible(INode node) { TreeNode tn = (TreeNode)node; if(tn.isAccessible()) { return true; } return isVisibleRec(tn); } private boolean isVisibleRec(TreeNode tn) { for(int i=tn.getChildCount(); i-->0; ) { TreeNode child = (TreeNode)tn.getChildAt(i); if(child.isAccessible()) { return true; } if(child.getChildCount() > 0) { if(isVisibleRec(child)) { return true; } } } return false; } }