/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.navigation.model; import java.util.Iterator; import java.util.LinkedList; import org.eclipse.riena.navigation.IModuleNode; import org.eclipse.riena.navigation.INavigationNode; import org.eclipse.riena.navigation.ISubModuleNode; import org.eclipse.riena.navigation.NavigationNodeId; import org.eclipse.riena.navigation.listener.IModuleNodeListener; import org.eclipse.riena.navigation.listener.INavigationNodeListener; /** * Default implementation for the module node */ public class ModuleNode extends NavigationNode<IModuleNode, ISubModuleNode, IModuleNodeListener> implements IModuleNode { private boolean presentSingleSubModule; private boolean closable; /** * Creates a ModuleNode. * */ public ModuleNode() { super(null); initialize(); } public Class<ISubModuleNode> getValidChildType() { return ISubModuleNode.class; } /** * Creates a ModuleNode. * * @param nodeId * Identifies the node in the application model tree. */ public ModuleNode(final NavigationNodeId nodeId) { super(nodeId); initialize(); } /** * Creates a ModuleNode. * * @param nodeId * Identifies the node in the application model tree. * @param label * Label of the module displayed in the modules title bar. */ public ModuleNode(final NavigationNodeId nodeId, final String label) { super(nodeId, label); initialize(); } /** * Creates a ModuleNode. * * @param label * Label of the module displayed in the modules title bar. */ public ModuleNode(final String label) { this(null, label); } /** * Initializes the properties of the module. */ private void initialize() { presentSingleSubModule = false; closable = true; } @Override public void moveTo(final NavigationNodeId targetId) { getNavigationProcessor().move(this, targetId); } /** * @return the presentSingleSubModule */ public boolean isPresentSingleSubModule() { return presentSingleSubModule; } /** * @param presentSingleSubModule * the presentSingleSubModule to set */ public void setPresentSingleSubModule(final boolean presentSingleSubModule) { this.presentSingleSubModule = presentSingleSubModule; notifyPresentSingleSubModuleChanged(); } private void notifyPresentSingleSubModuleChanged() { for (final INavigationNodeListener<?, ?> next : getListeners()) { if (next instanceof IModuleNodeListener) { final IModuleNodeListener moduleNodeListener = (IModuleNodeListener) next; moduleNodeListener.presentSingleSubModuleChanged(this); } } } public boolean isPresentSubModules() { // 1. check if flag is set // 2. check if module has more than one child // 3. check if module has only one child with subChilds return isPresentSingleSubModule() || getVisibleChildCount(this) > 1 || hasSingleChildWithChildren(); } /** * Checks if this node has a single child with children as well. * * @return */ private boolean hasSingleChildWithChildren() { if (getVisibleChildCount(this) == 1) { for (final INavigationNode<?> child : getChildren()) { if (child.isVisible() && !child.getChildren().isEmpty()) { return true; } } } return false; } /* * Counts the number of visible children for the given node */ private int getVisibleChildCount(final INavigationNode<?> node) { int result = 0; final Iterator<INavigationNode<?>> childIter = (Iterator<INavigationNode<?>>) node.getChildren().iterator(); while (childIter.hasNext()) { final INavigationNode<?> child = childIter.next(); if (child.isVisible()) { result++; } } return result; } public int calcDepth() { if (!isPresentSubModules()) { return 0; } return calcDepth(this); } /** * Calculates the number of the visible and expanded children below the * given node. * * @param node * start node * @return number of children */ private int calcDepth(final INavigationNode<?> node) { int depth = 0; if ((node == this) || node.isExpanded()) { for (final INavigationNode<?> child : node.getChildren()) { if (child.isVisible()) { depth++; depth += calcDepth(child); } } } return depth; } public boolean isClosable() { return closable; } public void setClosable(final boolean closeable) { this.closable = closeable; } /* * (non-Javadoc) * * @see org.eclipse.riena.navigation.model.NavigationNode#setLabel(java.lang.String) */ @Override public void setLabel(final String label) { super.setLabel(label); fireHierarchyLabelChange(); } private void fireHierarchyLabelChange() { for (final ISubModuleNode child : new LinkedList<ISubModuleNode>(getChildren())) { if (child instanceof SubModuleNode) { ((SubModuleNode) child).notifyHierarchyLabelChangeListeners(this); } } } }