]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/TreeLayer2.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.browsing.ui.nattable / src / org / simantics / browsing / ui / nattable / override / TreeLayer2.java
index 7d0f64e47b1b88129cf5f50359c47b708ab0c3f5..a44944ce6a6792b9dbe36138168f2f4dd4bafdeb 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2012 Original authors and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- * \r
- * Contributors:\r
- *     Original authors and others - initial API and implementation\r
- ******************************************************************************/\r
-package org.simantics.browsing.ui.nattable.override;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.List;\r
-\r
-import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;\r
-import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;\r
-import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiRowHideCommand;\r
-import org.eclipse.nebula.widgets.nattable.hideshow.command.RowHideCommand;\r
-import org.eclipse.nebula.widgets.nattable.hideshow.event.HideRowPositionsEvent;\r
-import org.eclipse.nebula.widgets.nattable.hideshow.event.ShowRowPositionsEvent;\r
-import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;\r
-import org.eclipse.nebula.widgets.nattable.layer.LabelStack;\r
-import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;\r
-import org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter;\r
-import org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper;\r
-import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;\r
-import org.eclipse.nebula.widgets.nattable.tree.ITreeRowModel;\r
-import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;\r
-import org.eclipse.nebula.widgets.nattable.tree.config.DefaultTreeLayerConfiguration;\r
-import org.eclipse.nebula.widgets.nattable.tree.config.TreeConfigAttributes;\r
-import org.eclipse.nebula.widgets.nattable.tree.painter.IndentedTreeImagePainter;\r
-\r
-import it.unimi.dsi.fastutil.ints.IntRBTreeSet;\r
-\r
-public class TreeLayer2 extends AbstractRowHideShowLayer2 {\r
-\r
-    //private static final Log log = LogFactory.getLog(TreeLayer.class);\r
-\r
-    public static final String TREE_COLUMN_CELL = "TREE_COLUMN_CELL"; //$NON-NLS-1$\r
-\r
-    public static final int TREE_COLUMN_NUMBER = 0;\r
-\r
-    /**\r
-     * Flag to configure whether the tree column should be identified by\r
-     * position or by index. Default is position.\r
-     */\r
-    private boolean useTreeColumnIndex = false;\r
-\r
-    /**\r
-     * The ITreeRowModelListener that is used to get information about the tree\r
-     * structure.\r
-     */\r
-    private final ITreeRowModel<?> treeRowModel;\r
-\r
-    /**\r
-     * Collection of all row indexes that are hidden if tree nodes are\r
-     * collapsed.\r
-     * <p>\r
-     * Note: This collection is only in use if the used {@link ITreeRowModel}\r
-     * implementation is returning the row indexes of affected rows on\r
-     * expand/collapse. There are also implementations that use another approach\r
-     * where the hide/show approach is not used (e.g. GlazedListTreeRowModel)\r
-     * </p>\r
-     */\r
-       private final IntRBTreeSet hiddenRowIndexes = new IntRBTreeSet();\r
-\r
-    /**\r
-     * The IndentedTreeImagePainter that paints indentation to the left of the\r
-     * configured base painter and icons for expand/collapse if possible, to\r
-     * render tree structure accordingly.\r
-     */\r
-    private IndentedTreeImagePainter indentedTreeImagePainter;\r
-\r
-    /**\r
-     * Creates a TreeLayer instance based on the given information. Will use a\r
-     * default IndentedTreeImagePainter that uses 10 pixels for indentation and\r
-     * simple + and - icons for expand/collapse icons. It also uses the\r
-     * DefaultTreeLayerConfiguration.\r
-     *\r
-     * @param underlyingLayer\r
-     *            The underlying layer on whose top this layer will be set.\r
-     * @param treeRowModel\r
-     *            The ITreeRowModelListener that is used to get information\r
-     *            about the tree structure.\r
-     */\r
-    public TreeLayer2(IUniqueIndexLayer underlyingLayer, ITreeRowModel<?> treeRowModel) {\r
-        this(underlyingLayer, treeRowModel, new IndentedTreeImagePainter());\r
-    }\r
-\r
-    /**\r
-     * Creates a TreeLayer instance based on the given information. Allows to\r
-     * specify the IndentedTreeImagePainter while using the\r
-     * DefaultTreeLayerConfiguration.\r
-     *\r
-     * @param underlyingLayer\r
-     *            The underlying layer on whose top this layer will be set.\r
-     * @param treeRowModel\r
-     *            The ITreeRowModelListener that is used to get information\r
-     *            about the tree structure.\r
-     * @param indentedTreeImagePainter\r
-     *            The IndentedTreeImagePainter that paints indentation to the\r
-     *            left of the configured base painter and icons for\r
-     *            expand/collapse if possible, to render tree structure\r
-     *            accordingly.\r
-     */\r
-    public TreeLayer2(\r
-            IUniqueIndexLayer underlyingLayer,\r
-            ITreeRowModel<?> treeRowModel,\r
-            IndentedTreeImagePainter indentedTreeImagePainter) {\r
-        this(underlyingLayer, treeRowModel, indentedTreeImagePainter, true);\r
-    }\r
-\r
-    /**\r
-     * Creates a TreeLayer instance based on the given information. Will use a\r
-     * default IndentedTreeImagePainter that uses 10 pixels for indentation and\r
-     * simple + and - icons for expand/collapse icons.\r
-     *\r
-     * @param underlyingLayer\r
-     *            The underlying layer on whose top this layer will be set.\r
-     * @param treeRowModel\r
-     *            The ITreeRowModelListener that is used to get information\r
-     *            about the tree structure.\r
-     * @param useDefaultConfiguration\r
-     *            <code>true</code> to use the DefaultTreeLayerConfiguration,\r
-     *            <code>false</code> if you want to specify your own\r
-     *            configuration.\r
-     */\r
-    public TreeLayer2(\r
-            IUniqueIndexLayer underlyingLayer,\r
-            ITreeRowModel<?> treeRowModel,\r
-            boolean useDefaultConfiguration) {\r
-        this(underlyingLayer,\r
-                treeRowModel,\r
-                new IndentedTreeImagePainter(),\r
-                useDefaultConfiguration);\r
-    }\r
-\r
-    /**\r
-     * Creates a TreeLayer instance based on the given information.\r
-     *\r
-     * @param underlyingLayer\r
-     *            The underlying layer on whose top this layer will be set.\r
-     * @param treeRowModel\r
-     *            The ITreeRowModelListener that is used to get information\r
-     *            about the tree structure.\r
-     * @param indentedTreeImagePainter\r
-     *            The IndentedTreeImagePainter that paints indentation to the\r
-     *            left of the configured base painter and icons for\r
-     *            expand/collapse if possible, to render tree structure\r
-     *            accordingly.\r
-     * @param useDefaultConfiguration\r
-     *            <code>true</code> to use the DefaultTreeLayerConfiguration,\r
-     *            <code>false</code> if you want to specify your own\r
-     *            configuration.\r
-     */\r
-    public TreeLayer2(\r
-            IUniqueIndexLayer underlyingLayer,\r
-            ITreeRowModel<?> treeRowModel,\r
-            IndentedTreeImagePainter indentedTreeImagePainter,\r
-            boolean useDefaultConfiguration) {\r
-\r
-        super(underlyingLayer);\r
-        this.treeRowModel = treeRowModel;\r
-\r
-        if (useDefaultConfiguration) {\r
-            addConfiguration(new DefaultTreeLayerConfiguration2(this));\r
-        }\r
-\r
-        this.indentedTreeImagePainter = indentedTreeImagePainter;\r
-\r
-        registerCommandHandler(new TreeExpandCollapseCommandHandler(this));\r
-        registerCommandHandler(new TreeCollapseAllCommandHandler(this));\r
-        registerCommandHandler(new TreeExpandAllCommandHandler(this));\r
-        registerCommandHandler(new TreeExpandToLevelCommandHandler(this));\r
-    }\r
-\r
-    @Override\r
-    public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) {\r
-        LabelStack configLabels = super.getConfigLabelsByPosition(columnPosition, rowPosition);\r
-\r
-        if (isTreeColumn(columnPosition)) {\r
-            configLabels.addLabelOnTop(TREE_COLUMN_CELL);\r
-\r
-            int rowIndex = getRowIndexByPosition(rowPosition);\r
-            configLabels.addLabelOnTop(\r
-                    DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + this.treeRowModel.depth(rowIndex));\r
-            if (!this.treeRowModel.hasChildren(rowIndex)) {\r
-                configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);\r
-            } else {\r
-                if (this.treeRowModel.isCollapsed(rowIndex)) {\r
-                    configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);\r
-                } else {\r
-                    configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);\r
-                }\r
-            }\r
-        }\r
-        return configLabels;\r
-    }\r
-\r
-    /**\r
-     * @return The ITreeRowModelListener that is used to get information about\r
-     *         the tree structure.\r
-     */\r
-    public ITreeRowModel<?> getModel() {\r
-        return this.treeRowModel;\r
-    }\r
-\r
-    /**\r
-     * @return The IndentedTreeImagePainter that paints indentation to the left\r
-     *         of the configured base painter and icons for expand/collapse if\r
-     *         possible, to render tree structure accordingly.\r
-     *\r
-     * @deprecated since 1.1 the configured TreeImagePainter should be used\r
-     *             instead of the hard referenced one\r
-     */\r
-    @Deprecated\r
-    public IndentedTreeImagePainter getIndentedTreeImagePainter() {\r
-        return this.indentedTreeImagePainter;\r
-    }\r
-\r
-    /**\r
-     * @return The ICellPainter that is used to paint the images in the tree by\r
-     *         the IndentedTreeImagePainter. Usually it is some type of\r
-     *         TreeImagePainter that paints expand/collapse/leaf icons regarding\r
-     *         the node state.<br>\r
-     *         Can be <code>null</code> if set explicitly to the\r
-     *         IndentedTreeImagePainter!\r
-     *\r
-     * @deprecated since 1.1 the configured TreeImagePainter should be used\r
-     *             instead of the hard referenced one\r
-     */\r
-    @Deprecated\r
-    public ICellPainter getTreeImagePainter() {\r
-        return this.indentedTreeImagePainter != null ? this.indentedTreeImagePainter\r
-                .getTreeImagePainter() : null;\r
-    }\r
-\r
-    /**\r
-     * @param columnPosition\r
-     *            The column position to check.\r
-     * @return <code>true</code> if the given column position is the tree\r
-     *         column, <code>false</code> if not.\r
-     */\r
-    private boolean isTreeColumn(int columnPosition) {\r
-        if (this.useTreeColumnIndex)\r
-            return getColumnIndexByPosition(columnPosition) == TREE_COLUMN_NUMBER;\r
-\r
-        return columnPosition == TREE_COLUMN_NUMBER;\r
-    }\r
-\r
-    @Override\r
-    public ICellPainter getCellPainter(\r
-            int columnPosition, int rowPosition,\r
-            ILayerCell cell, IConfigRegistry configRegistry) {\r
-        ICellPainter cellPainter = super.getCellPainter(\r
-                columnPosition, rowPosition, cell, configRegistry);\r
-\r
-        if (cell.getConfigLabels().hasLabel(TREE_COLUMN_CELL)) {\r
-\r
-            ICellPainter treeCellPainter = configRegistry.getConfigAttribute(\r
-                    TreeConfigAttributes.TREE_STRUCTURE_PAINTER,\r
-                    cell.getDisplayMode(),\r
-                    cell.getConfigLabels().getLabels());\r
-\r
-            if (treeCellPainter != null) {\r
-                ICellPainter innerWrapper = treeCellPainter;\r
-                IndentedTreeImagePainter treePainter = null;\r
-                if (innerWrapper instanceof IndentedTreeImagePainter) {\r
-                    treePainter = (IndentedTreeImagePainter) innerWrapper;\r
-                } else {\r
-                    while (treePainter == null\r
-                            && innerWrapper != null\r
-                            && innerWrapper instanceof CellPainterWrapper\r
-                            && ((CellPainterWrapper) innerWrapper).getWrappedPainter() != null) {\r
-\r
-                        innerWrapper = ((CellPainterWrapper) innerWrapper).getWrappedPainter();\r
-                        if (innerWrapper instanceof IndentedTreeImagePainter) {\r
-                            treePainter = (IndentedTreeImagePainter) innerWrapper;\r
-                        }\r
-                    }\r
-                }\r
-\r
-                if (treePainter != null) {\r
-                    treePainter.setBaseCellPainter(cellPainter);\r
-                    cellPainter = treeCellPainter;\r
-                } else {\r
-                    // log error\r
-//                    log.warn("There is no IndentedTreeImagePainter found for TREE_STRUCTURE_PAINTER, " //$NON-NLS-1$\r
-//                            + "using local configured IndentedTreeImagePainter as fallback"); //$NON-NLS-1$\r
-                    // fallback\r
-                    this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);\r
-                    cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);\r
-                }\r
-            } else {\r
-                // backwards compatibility fallback\r
-                this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);\r
-                cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);\r
-            }\r
-        }\r
-\r
-        return cellPainter;\r
-    }\r
-\r
-    @Override\r
-    public boolean isRowIndexHidden(int rowIndex) {\r
-        return this.hiddenRowIndexes.contains(rowIndex)\r
-                || isHiddenInUnderlyingLayer(rowIndex);\r
-    }\r
-\r
-    @Override\r
-    public Collection<Integer> getHiddenRowIndexes() {\r
-        return this.hiddenRowIndexes;\r
-    }\r
-\r
-    /**\r
-     * Performs an expand/collapse action dependent on the current state of the\r
-     * tree node at the given row index.\r
-     *\r
-     * @param parentIndex\r
-     *            The index of the row that shows the tree node for which the\r
-     *            expand/collapse action should be performed.\r
-     */\r
-    public void expandOrCollapseIndex(int parentIndex) {\r
-        if (this.treeRowModel.isCollapsed(parentIndex)) {\r
-            expandTreeRow(parentIndex);\r
-        } else {\r
-            collapseTreeRow(parentIndex);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Collapses the tree node for the given row index.\r
-     *\r
-     * @param parentIndex\r
-     *            The index of the row that shows the node that should be\r
-     *            collapsed\r
-     */\r
-    public void collapseTreeRow(int parentIndex) {\r
-        List<Integer> rowIndexes = this.treeRowModel.collapse(parentIndex);\r
-        List<Integer> rowPositions = new ArrayList<Integer>();\r
-        for (Integer rowIndex : rowIndexes) {\r
-            int rowPos = getRowPositionByIndex(rowIndex);\r
-            // if the rowPos is negative, it is not visible because of hidden\r
-            // state in an underlying layer\r
-            if (rowPos >= 0) {\r
-                rowPositions.add(rowPos);\r
-            }\r
-        }\r
-        this.hiddenRowIndexes.addAll(rowIndexes);\r
-        invalidateCache();\r
-        fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));\r
-    }\r
-\r
-    /**\r
-     * Collapses all tree nodes in the tree.\r
-     */\r
-    public void collapseAll() {\r
-        List<Integer> rowIndexes = this.treeRowModel.collapseAll();\r
-        List<Integer> rowPositions = new ArrayList<Integer>();\r
-        for (Integer rowIndex : rowIndexes) {\r
-            int rowPos = getRowPositionByIndex(rowIndex);\r
-            // if the rowPos is negative, it is not visible because of hidden\r
-            // state in an underlying layer\r
-            if (rowPos >= 0) {\r
-                rowPositions.add(rowPos);\r
-            }\r
-        }\r
-        this.hiddenRowIndexes.addAll(rowIndexes);\r
-        invalidateCache();\r
-        fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));\r
-    }\r
-\r
-    /**\r
-     * Expands the tree node for the given row index.\r
-     *\r
-     * @param parentIndex\r
-     *            The index of the row that shows the node that should be\r
-     *            expanded\r
-     */\r
-    public void expandTreeRow(int parentIndex) {\r
-        List<Integer> rowIndexes = this.treeRowModel.expand(parentIndex);\r
-        // Bug 432865: iterating and removing every single item is faster than\r
-        // removeAll()\r
-        for (final Integer expandedChildRowIndex : rowIndexes) {\r
-            this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
-        }\r
-        invalidateCache();\r
-        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
-    }\r
-\r
-    /**\r
-     * Expands the tree node for the given row index in the tree to a certain\r
-     * level.\r
-     *\r
-     * @param parentIndex\r
-     *            The index of the row that shows the node that should be\r
-     *            expanded\r
-     * @param level\r
-     *            The level to which the tree node should be expanded.\r
-     */\r
-    public void expandTreeRowToLevel(int parentIndex, int level) {\r
-        List<Integer> rowIndexes = this.treeRowModel.expandToLevel(parentIndex, level);\r
-        // Bug 432865: iterating and removing every single item is faster than\r
-        // removeAll()\r
-        for (final Integer expandedChildRowIndex : rowIndexes) {\r
-            this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
-        }\r
-        invalidateCache();\r
-        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
-    }\r
-\r
-    /**\r
-     * Expands all tree nodes in the tree.\r
-     */\r
-    public void expandAll() {\r
-        List<Integer> rowIndexes = this.treeRowModel.expandAll();\r
-        this.hiddenRowIndexes.clear();\r
-        invalidateCache();\r
-        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
-    }\r
-\r
-    /**\r
-     * Expands all tree nodes in the tree to a certain level.\r
-     *\r
-     * @param level\r
-     *            The level to which the tree node should be expanded.\r
-     */\r
-    public void expandAllToLevel(int level) {\r
-        List<Integer> rowIndexes = this.treeRowModel.expandToLevel(level);\r
-        // Bug 432865: iterating and removing every single item is faster than\r
-        // removeAll()\r
-//        for (final Integer expandedChildRowIndex : rowIndexes) {\r
-//            this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
-//        }\r
-        if (rowIndexes == null)\r
-               return;\r
-        for (int i = rowIndexes.size()-1; i>=0; i--) {\r
-               this.hiddenRowIndexes.remove(rowIndexes.get(i));\r
-        }\r
-        invalidateCache();\r
-        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
-    }\r
-\r
-    /**\r
-     * Checks the underlying layer if the row is hidden by another layer.\r
-     *\r
-     * @param rowIndex\r
-     *            The index of the row whose hidden state should be checked\r
-     * @return <code>true</code> if the row at the given index is hidden in the\r
-     *         underlying layer <code>false</code> if not.\r
-     */\r
-    private boolean isHiddenInUnderlyingLayer(int rowIndex) {\r
-        IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();\r
-        return (underlyingLayer.getRowPositionByIndex(rowIndex) == -1);\r
-    }\r
-\r
-    @Override\r
-    public boolean doCommand(ILayerCommand command) {\r
-        // special command transformations are needed to hide also child nodes\r
-        if (command instanceof RowHideCommand) {\r
-            return handleRowHideCommand((RowHideCommand) command);\r
-        } else if (command instanceof MultiRowHideCommand) {\r
-            return handleMultiRowHideCommand((MultiRowHideCommand) command);\r
-        }\r
-        return super.doCommand(command);\r
-    }\r
-\r
-    /**\r
-     * Checks if the given command tries to hide a row that is a node that is\r
-     * not collapsed and has children. In that case also the child rows need to\r
-     * be hidden.\r
-     *\r
-     * @param command\r
-     *            The {@link RowHideCommand} to process\r
-     * @return <code>true</code> if the command has been handled,\r
-     *         <code>false</code> otherwise\r
-     */\r
-    protected boolean handleRowHideCommand(RowHideCommand command) {\r
-        // transform position to index\r
-        if (command.convertToTargetLayer(this)) {\r
-            int rowIndex = getRowIndexByPosition(command.getRowPosition());\r
-            if (this.treeRowModel.hasChildren(rowIndex)\r
-                    && !this.treeRowModel.isCollapsed(rowIndex)) {\r
-                List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);\r
-                int[] childPositions = new int[childIndexes.size() + 1];\r
-                childPositions[0] = command.getRowPosition();\r
-                for (int i = 1; i < childIndexes.size() + 1; i++) {\r
-                    int childPos = getRowPositionByIndex(childIndexes.get(i - 1));\r
-                    childPositions[i] = childPos;\r
-                }\r
-                return super.doCommand(new MultiRowHideCommand(this, childPositions));\r
-            }\r
-        }\r
-        return super.doCommand(command);\r
-    }\r
-\r
-    /**\r
-     * Checks if the given command tries to hide rows that are nodes that are\r
-     * not collapsed and have children. In that case also the child rows need to\r
-     * be hidden.\r
-     *\r
-     * @param command\r
-     *            The {@link MultiRowHideCommand} to process\r
-     * @return <code>true</code> if the command has been handled,\r
-     *         <code>false</code> otherwise\r
-     */\r
-    protected boolean handleMultiRowHideCommand(MultiRowHideCommand command) {\r
-        // transform position to index\r
-        if (command.convertToTargetLayer(this)) {\r
-            List<Integer> rowPositionsToHide = new ArrayList<Integer>();\r
-            for (Integer rowPos : command.getRowPositions()) {\r
-                rowPositionsToHide.add(rowPos);\r
-                int rowIndex = getRowIndexByPosition(rowPos);\r
-                if (this.treeRowModel.hasChildren(rowIndex)\r
-                        && !this.treeRowModel.isCollapsed(rowIndex)) {\r
-                    List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);\r
-                    for (Integer childIndex : childIndexes) {\r
-                        rowPositionsToHide.add(getRowPositionByIndex(childIndex));\r
-                    }\r
-                }\r
-            }\r
-\r
-            int[] childPositions = new int[rowPositionsToHide.size()];\r
-            for (int i = 0; i < rowPositionsToHide.size(); i++) {\r
-                childPositions[i] = rowPositionsToHide.get(i);\r
-            }\r
-            return super.doCommand(new MultiRowHideCommand(this, childPositions));\r
-        }\r
-        return super.doCommand(command);\r
-    }\r
-\r
-    /**\r
-     * @return <code>true</code> if the column index is used to determine the\r
-     *         tree column, <code>false</code> if the column position is used.\r
-     *         Default is <code>false</code>.\r
-     */\r
-    public boolean isUseTreeColumnIndex() {\r
-        return this.useTreeColumnIndex;\r
-    }\r
-\r
-    /**\r
-     * Configure whether (column index == 0) or (column position == 0) should be\r
-     * performed to identify the tree column.\r
-     *\r
-     * @param useTreeColumnIndex\r
-     *            <code>true</code> if the column index should be used to\r
-     *            determine the tree column, <code>false</code> if the column\r
-     *            position should be used.\r
-     */\r
-    public void setUseTreeColumnIndex(boolean useTreeColumnIndex) {\r
-        this.useTreeColumnIndex = useTreeColumnIndex;\r
-    }\r
-\r
-    /**\r
-     * @since 1.4\r
-     */\r
-    @Override\r
-    public Collection<String> getProvidedLabels() {\r
-        Collection<String> result = super.getProvidedLabels();\r
-\r
-        result.add(TreeLayer.TREE_COLUMN_CELL);\r
-        result.add(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);\r
-        result.add(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);\r
-        result.add(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);\r
-        // configure 5 levels to be configurable via CSS\r
-        // if you need more you need to override this method\r
-        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "0"); //$NON-NLS-1$\r
-        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "1"); //$NON-NLS-1$\r
-        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "2"); //$NON-NLS-1$\r
-        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "3"); //$NON-NLS-1$\r
-        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "4"); //$NON-NLS-1$\r
-\r
-        return result;\r
-    }\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2012 Original authors 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:
+ *     Original authors and others - initial API and implementation
+ ******************************************************************************/
+package org.simantics.browsing.ui.nattable.override;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiRowHideCommand;
+import org.eclipse.nebula.widgets.nattable.hideshow.command.RowHideCommand;
+import org.eclipse.nebula.widgets.nattable.hideshow.event.HideRowPositionsEvent;
+import org.eclipse.nebula.widgets.nattable.hideshow.event.ShowRowPositionsEvent;
+import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
+import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
+import org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter;
+import org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper;
+import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;
+import org.eclipse.nebula.widgets.nattable.tree.ITreeRowModel;
+import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;
+import org.eclipse.nebula.widgets.nattable.tree.config.DefaultTreeLayerConfiguration;
+import org.eclipse.nebula.widgets.nattable.tree.config.TreeConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.tree.painter.IndentedTreeImagePainter;
+
+import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
+
+public class TreeLayer2 extends AbstractRowHideShowLayer2 {
+
+    //private static final Log log = LogFactory.getLog(TreeLayer.class);
+
+    public static final String TREE_COLUMN_CELL = "TREE_COLUMN_CELL"; //$NON-NLS-1$
+
+    public static final int TREE_COLUMN_NUMBER = 0;
+
+    /**
+     * Flag to configure whether the tree column should be identified by
+     * position or by index. Default is position.
+     */
+    private boolean useTreeColumnIndex = false;
+
+    /**
+     * The ITreeRowModelListener that is used to get information about the tree
+     * structure.
+     */
+    private final ITreeRowModel<?> treeRowModel;
+
+    /**
+     * Collection of all row indexes that are hidden if tree nodes are
+     * collapsed.
+     * <p>
+     * Note: This collection is only in use if the used {@link ITreeRowModel}
+     * implementation is returning the row indexes of affected rows on
+     * expand/collapse. There are also implementations that use another approach
+     * where the hide/show approach is not used (e.g. GlazedListTreeRowModel)
+     * </p>
+     */
+       private final IntRBTreeSet hiddenRowIndexes = new IntRBTreeSet();
+
+    /**
+     * The IndentedTreeImagePainter that paints indentation to the left of the
+     * configured base painter and icons for expand/collapse if possible, to
+     * render tree structure accordingly.
+     */
+    private IndentedTreeImagePainter indentedTreeImagePainter;
+
+    /**
+     * Creates a TreeLayer instance based on the given information. Will use a
+     * default IndentedTreeImagePainter that uses 10 pixels for indentation and
+     * simple + and - icons for expand/collapse icons. It also uses the
+     * DefaultTreeLayerConfiguration.
+     *
+     * @param underlyingLayer
+     *            The underlying layer on whose top this layer will be set.
+     * @param treeRowModel
+     *            The ITreeRowModelListener that is used to get information
+     *            about the tree structure.
+     */
+    public TreeLayer2(IUniqueIndexLayer underlyingLayer, ITreeRowModel<?> treeRowModel) {
+        this(underlyingLayer, treeRowModel, new IndentedTreeImagePainter());
+    }
+
+    /**
+     * Creates a TreeLayer instance based on the given information. Allows to
+     * specify the IndentedTreeImagePainter while using the
+     * DefaultTreeLayerConfiguration.
+     *
+     * @param underlyingLayer
+     *            The underlying layer on whose top this layer will be set.
+     * @param treeRowModel
+     *            The ITreeRowModelListener that is used to get information
+     *            about the tree structure.
+     * @param indentedTreeImagePainter
+     *            The IndentedTreeImagePainter that paints indentation to the
+     *            left of the configured base painter and icons for
+     *            expand/collapse if possible, to render tree structure
+     *            accordingly.
+     */
+    public TreeLayer2(
+            IUniqueIndexLayer underlyingLayer,
+            ITreeRowModel<?> treeRowModel,
+            IndentedTreeImagePainter indentedTreeImagePainter) {
+        this(underlyingLayer, treeRowModel, indentedTreeImagePainter, true);
+    }
+
+    /**
+     * Creates a TreeLayer instance based on the given information. Will use a
+     * default IndentedTreeImagePainter that uses 10 pixels for indentation and
+     * simple + and - icons for expand/collapse icons.
+     *
+     * @param underlyingLayer
+     *            The underlying layer on whose top this layer will be set.
+     * @param treeRowModel
+     *            The ITreeRowModelListener that is used to get information
+     *            about the tree structure.
+     * @param useDefaultConfiguration
+     *            <code>true</code> to use the DefaultTreeLayerConfiguration,
+     *            <code>false</code> if you want to specify your own
+     *            configuration.
+     */
+    public TreeLayer2(
+            IUniqueIndexLayer underlyingLayer,
+            ITreeRowModel<?> treeRowModel,
+            boolean useDefaultConfiguration) {
+        this(underlyingLayer,
+                treeRowModel,
+                new IndentedTreeImagePainter(),
+                useDefaultConfiguration);
+    }
+
+    /**
+     * Creates a TreeLayer instance based on the given information.
+     *
+     * @param underlyingLayer
+     *            The underlying layer on whose top this layer will be set.
+     * @param treeRowModel
+     *            The ITreeRowModelListener that is used to get information
+     *            about the tree structure.
+     * @param indentedTreeImagePainter
+     *            The IndentedTreeImagePainter that paints indentation to the
+     *            left of the configured base painter and icons for
+     *            expand/collapse if possible, to render tree structure
+     *            accordingly.
+     * @param useDefaultConfiguration
+     *            <code>true</code> to use the DefaultTreeLayerConfiguration,
+     *            <code>false</code> if you want to specify your own
+     *            configuration.
+     */
+    public TreeLayer2(
+            IUniqueIndexLayer underlyingLayer,
+            ITreeRowModel<?> treeRowModel,
+            IndentedTreeImagePainter indentedTreeImagePainter,
+            boolean useDefaultConfiguration) {
+
+        super(underlyingLayer);
+        this.treeRowModel = treeRowModel;
+
+        if (useDefaultConfiguration) {
+            addConfiguration(new DefaultTreeLayerConfiguration2(this));
+        }
+
+        this.indentedTreeImagePainter = indentedTreeImagePainter;
+
+        registerCommandHandler(new TreeExpandCollapseCommandHandler(this));
+        registerCommandHandler(new TreeCollapseAllCommandHandler(this));
+        registerCommandHandler(new TreeExpandAllCommandHandler(this));
+        registerCommandHandler(new TreeExpandToLevelCommandHandler(this));
+    }
+
+    @Override
+    public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) {
+        LabelStack configLabels = super.getConfigLabelsByPosition(columnPosition, rowPosition);
+
+        if (isTreeColumn(columnPosition)) {
+            configLabels.addLabelOnTop(TREE_COLUMN_CELL);
+
+            int rowIndex = getRowIndexByPosition(rowPosition);
+            configLabels.addLabelOnTop(
+                    DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + this.treeRowModel.depth(rowIndex));
+            if (!this.treeRowModel.hasChildren(rowIndex)) {
+                configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);
+            } else {
+                if (this.treeRowModel.isCollapsed(rowIndex)) {
+                    configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);
+                } else {
+                    configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);
+                }
+            }
+        }
+        return configLabels;
+    }
+
+    /**
+     * @return The ITreeRowModelListener that is used to get information about
+     *         the tree structure.
+     */
+    public ITreeRowModel<?> getModel() {
+        return this.treeRowModel;
+    }
+
+    /**
+     * @return The IndentedTreeImagePainter that paints indentation to the left
+     *         of the configured base painter and icons for expand/collapse if
+     *         possible, to render tree structure accordingly.
+     *
+     * @deprecated since 1.1 the configured TreeImagePainter should be used
+     *             instead of the hard referenced one
+     */
+    @Deprecated
+    public IndentedTreeImagePainter getIndentedTreeImagePainter() {
+        return this.indentedTreeImagePainter;
+    }
+
+    /**
+     * @return The ICellPainter that is used to paint the images in the tree by
+     *         the IndentedTreeImagePainter. Usually it is some type of
+     *         TreeImagePainter that paints expand/collapse/leaf icons regarding
+     *         the node state.<br>
+     *         Can be <code>null</code> if set explicitly to the
+     *         IndentedTreeImagePainter!
+     *
+     * @deprecated since 1.1 the configured TreeImagePainter should be used
+     *             instead of the hard referenced one
+     */
+    @Deprecated
+    public ICellPainter getTreeImagePainter() {
+        return this.indentedTreeImagePainter != null ? this.indentedTreeImagePainter
+                .getTreeImagePainter() : null;
+    }
+
+    /**
+     * @param columnPosition
+     *            The column position to check.
+     * @return <code>true</code> if the given column position is the tree
+     *         column, <code>false</code> if not.
+     */
+    private boolean isTreeColumn(int columnPosition) {
+        if (this.useTreeColumnIndex)
+            return getColumnIndexByPosition(columnPosition) == TREE_COLUMN_NUMBER;
+
+        return columnPosition == TREE_COLUMN_NUMBER;
+    }
+
+    @Override
+    public ICellPainter getCellPainter(
+            int columnPosition, int rowPosition,
+            ILayerCell cell, IConfigRegistry configRegistry) {
+        ICellPainter cellPainter = super.getCellPainter(
+                columnPosition, rowPosition, cell, configRegistry);
+
+        if (cell.getConfigLabels().hasLabel(TREE_COLUMN_CELL)) {
+
+            ICellPainter treeCellPainter = configRegistry.getConfigAttribute(
+                    TreeConfigAttributes.TREE_STRUCTURE_PAINTER,
+                    cell.getDisplayMode(),
+                    cell.getConfigLabels().getLabels());
+
+            if (treeCellPainter != null) {
+                ICellPainter innerWrapper = treeCellPainter;
+                IndentedTreeImagePainter treePainter = null;
+                if (innerWrapper instanceof IndentedTreeImagePainter) {
+                    treePainter = (IndentedTreeImagePainter) innerWrapper;
+                } else {
+                    while (treePainter == null
+                            && innerWrapper != null
+                            && innerWrapper instanceof CellPainterWrapper
+                            && ((CellPainterWrapper) innerWrapper).getWrappedPainter() != null) {
+
+                        innerWrapper = ((CellPainterWrapper) innerWrapper).getWrappedPainter();
+                        if (innerWrapper instanceof IndentedTreeImagePainter) {
+                            treePainter = (IndentedTreeImagePainter) innerWrapper;
+                        }
+                    }
+                }
+
+                if (treePainter != null) {
+                    treePainter.setBaseCellPainter(cellPainter);
+                    cellPainter = treeCellPainter;
+                } else {
+                    // log error
+//                    log.warn("There is no IndentedTreeImagePainter found for TREE_STRUCTURE_PAINTER, " //$NON-NLS-1$
+//                            + "using local configured IndentedTreeImagePainter as fallback"); //$NON-NLS-1$
+                    // fallback
+                    this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);
+                    cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);
+                }
+            } else {
+                // backwards compatibility fallback
+                this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);
+                cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);
+            }
+        }
+
+        return cellPainter;
+    }
+
+    @Override
+    public boolean isRowIndexHidden(int rowIndex) {
+        return this.hiddenRowIndexes.contains(rowIndex)
+                || isHiddenInUnderlyingLayer(rowIndex);
+    }
+
+    @Override
+    public Collection<Integer> getHiddenRowIndexes() {
+        return this.hiddenRowIndexes;
+    }
+
+    /**
+     * Performs an expand/collapse action dependent on the current state of the
+     * tree node at the given row index.
+     *
+     * @param parentIndex
+     *            The index of the row that shows the tree node for which the
+     *            expand/collapse action should be performed.
+     */
+    public void expandOrCollapseIndex(int parentIndex) {
+        if (this.treeRowModel.isCollapsed(parentIndex)) {
+            expandTreeRow(parentIndex);
+        } else {
+            collapseTreeRow(parentIndex);
+        }
+    }
+
+    /**
+     * Collapses the tree node for the given row index.
+     *
+     * @param parentIndex
+     *            The index of the row that shows the node that should be
+     *            collapsed
+     */
+    public void collapseTreeRow(int parentIndex) {
+        List<Integer> rowIndexes = this.treeRowModel.collapse(parentIndex);
+        List<Integer> rowPositions = new ArrayList<Integer>();
+        for (Integer rowIndex : rowIndexes) {
+            int rowPos = getRowPositionByIndex(rowIndex);
+            // if the rowPos is negative, it is not visible because of hidden
+            // state in an underlying layer
+            if (rowPos >= 0) {
+                rowPositions.add(rowPos);
+            }
+        }
+        this.hiddenRowIndexes.addAll(rowIndexes);
+        invalidateCache();
+        fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));
+    }
+
+    /**
+     * Collapses all tree nodes in the tree.
+     */
+    public void collapseAll() {
+        List<Integer> rowIndexes = this.treeRowModel.collapseAll();
+        List<Integer> rowPositions = new ArrayList<Integer>();
+        for (Integer rowIndex : rowIndexes) {
+            int rowPos = getRowPositionByIndex(rowIndex);
+            // if the rowPos is negative, it is not visible because of hidden
+            // state in an underlying layer
+            if (rowPos >= 0) {
+                rowPositions.add(rowPos);
+            }
+        }
+        this.hiddenRowIndexes.addAll(rowIndexes);
+        invalidateCache();
+        fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));
+    }
+
+    /**
+     * Expands the tree node for the given row index.
+     *
+     * @param parentIndex
+     *            The index of the row that shows the node that should be
+     *            expanded
+     */
+    public void expandTreeRow(int parentIndex) {
+        List<Integer> rowIndexes = this.treeRowModel.expand(parentIndex);
+        // Bug 432865: iterating and removing every single item is faster than
+        // removeAll()
+        for (final Integer expandedChildRowIndex : rowIndexes) {
+            this.hiddenRowIndexes.remove(expandedChildRowIndex);
+        }
+        invalidateCache();
+        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));
+    }
+
+    /**
+     * Expands the tree node for the given row index in the tree to a certain
+     * level.
+     *
+     * @param parentIndex
+     *            The index of the row that shows the node that should be
+     *            expanded
+     * @param level
+     *            The level to which the tree node should be expanded.
+     */
+    public void expandTreeRowToLevel(int parentIndex, int level) {
+        List<Integer> rowIndexes = this.treeRowModel.expandToLevel(parentIndex, level);
+        // Bug 432865: iterating and removing every single item is faster than
+        // removeAll()
+        for (final Integer expandedChildRowIndex : rowIndexes) {
+            this.hiddenRowIndexes.remove(expandedChildRowIndex);
+        }
+        invalidateCache();
+        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));
+    }
+
+    /**
+     * Expands all tree nodes in the tree.
+     */
+    public void expandAll() {
+        List<Integer> rowIndexes = this.treeRowModel.expandAll();
+        this.hiddenRowIndexes.clear();
+        invalidateCache();
+        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));
+    }
+
+    /**
+     * Expands all tree nodes in the tree to a certain level.
+     *
+     * @param level
+     *            The level to which the tree node should be expanded.
+     */
+    public void expandAllToLevel(int level) {
+        List<Integer> rowIndexes = this.treeRowModel.expandToLevel(level);
+        // Bug 432865: iterating and removing every single item is faster than
+        // removeAll()
+//        for (final Integer expandedChildRowIndex : rowIndexes) {
+//            this.hiddenRowIndexes.remove(expandedChildRowIndex);
+//        }
+        if (rowIndexes == null)
+               return;
+        for (int i = rowIndexes.size()-1; i>=0; i--) {
+               this.hiddenRowIndexes.remove(rowIndexes.get(i));
+        }
+        invalidateCache();
+        fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));
+    }
+
+    /**
+     * Checks the underlying layer if the row is hidden by another layer.
+     *
+     * @param rowIndex
+     *            The index of the row whose hidden state should be checked
+     * @return <code>true</code> if the row at the given index is hidden in the
+     *         underlying layer <code>false</code> if not.
+     */
+    private boolean isHiddenInUnderlyingLayer(int rowIndex) {
+        IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();
+        return (underlyingLayer.getRowPositionByIndex(rowIndex) == -1);
+    }
+
+    @Override
+    public boolean doCommand(ILayerCommand command) {
+        // special command transformations are needed to hide also child nodes
+        if (command instanceof RowHideCommand) {
+            return handleRowHideCommand((RowHideCommand) command);
+        } else if (command instanceof MultiRowHideCommand) {
+            return handleMultiRowHideCommand((MultiRowHideCommand) command);
+        }
+        return super.doCommand(command);
+    }
+
+    /**
+     * Checks if the given command tries to hide a row that is a node that is
+     * not collapsed and has children. In that case also the child rows need to
+     * be hidden.
+     *
+     * @param command
+     *            The {@link RowHideCommand} to process
+     * @return <code>true</code> if the command has been handled,
+     *         <code>false</code> otherwise
+     */
+    protected boolean handleRowHideCommand(RowHideCommand command) {
+        // transform position to index
+        if (command.convertToTargetLayer(this)) {
+            int rowIndex = getRowIndexByPosition(command.getRowPosition());
+            if (this.treeRowModel.hasChildren(rowIndex)
+                    && !this.treeRowModel.isCollapsed(rowIndex)) {
+                List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);
+                int[] childPositions = new int[childIndexes.size() + 1];
+                childPositions[0] = command.getRowPosition();
+                for (int i = 1; i < childIndexes.size() + 1; i++) {
+                    int childPos = getRowPositionByIndex(childIndexes.get(i - 1));
+                    childPositions[i] = childPos;
+                }
+                return super.doCommand(new MultiRowHideCommand(this, childPositions));
+            }
+        }
+        return super.doCommand(command);
+    }
+
+    /**
+     * Checks if the given command tries to hide rows that are nodes that are
+     * not collapsed and have children. In that case also the child rows need to
+     * be hidden.
+     *
+     * @param command
+     *            The {@link MultiRowHideCommand} to process
+     * @return <code>true</code> if the command has been handled,
+     *         <code>false</code> otherwise
+     */
+    protected boolean handleMultiRowHideCommand(MultiRowHideCommand command) {
+        // transform position to index
+        if (command.convertToTargetLayer(this)) {
+            List<Integer> rowPositionsToHide = new ArrayList<Integer>();
+            for (Integer rowPos : command.getRowPositions()) {
+                rowPositionsToHide.add(rowPos);
+                int rowIndex = getRowIndexByPosition(rowPos);
+                if (this.treeRowModel.hasChildren(rowIndex)
+                        && !this.treeRowModel.isCollapsed(rowIndex)) {
+                    List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);
+                    for (Integer childIndex : childIndexes) {
+                        rowPositionsToHide.add(getRowPositionByIndex(childIndex));
+                    }
+                }
+            }
+
+            int[] childPositions = new int[rowPositionsToHide.size()];
+            for (int i = 0; i < rowPositionsToHide.size(); i++) {
+                childPositions[i] = rowPositionsToHide.get(i);
+            }
+            return super.doCommand(new MultiRowHideCommand(this, childPositions));
+        }
+        return super.doCommand(command);
+    }
+
+    /**
+     * @return <code>true</code> if the column index is used to determine the
+     *         tree column, <code>false</code> if the column position is used.
+     *         Default is <code>false</code>.
+     */
+    public boolean isUseTreeColumnIndex() {
+        return this.useTreeColumnIndex;
+    }
+
+    /**
+     * Configure whether (column index == 0) or (column position == 0) should be
+     * performed to identify the tree column.
+     *
+     * @param useTreeColumnIndex
+     *            <code>true</code> if the column index should be used to
+     *            determine the tree column, <code>false</code> if the column
+     *            position should be used.
+     */
+    public void setUseTreeColumnIndex(boolean useTreeColumnIndex) {
+        this.useTreeColumnIndex = useTreeColumnIndex;
+    }
+
+    /**
+     * @since 1.4
+     */
+    @Override
+    public Collection<String> getProvidedLabels() {
+        Collection<String> result = super.getProvidedLabels();
+
+        result.add(TreeLayer.TREE_COLUMN_CELL);
+        result.add(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);
+        result.add(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);
+        result.add(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);
+        // configure 5 levels to be configurable via CSS
+        // if you need more you need to override this method
+        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "0"); //$NON-NLS-1$
+        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "1"); //$NON-NLS-1$
+        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "2"); //$NON-NLS-1$
+        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "3"); //$NON-NLS-1$
+        result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "4"); //$NON-NLS-1$
+
+        return result;
+    }
+}