]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/override/TreeLayer2.java
Merge "Testing SonarQube with Simantics Platform SDK"
[simantics/platform.git] / bundles / org.simantics.browsing.ui.nattable / src / org / simantics / browsing / ui / nattable / override / TreeLayer2.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012 Original authors and others.\r
3  * All rights reserved. This program and the accompanying materials\r
4  * are made available under the terms of the Eclipse Public License v1.0\r
5  * which accompanies this distribution, and is available at\r
6  * http://www.eclipse.org/legal/epl-v10.html\r
7  * \r
8  * Contributors:\r
9  *     Original authors and others - initial API and implementation\r
10  ******************************************************************************/\r
11 package org.simantics.browsing.ui.nattable.override;\r
12 \r
13 import java.util.ArrayList;\r
14 import java.util.Collection;\r
15 import java.util.List;\r
16 \r
17 import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;\r
18 import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;\r
19 import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiRowHideCommand;\r
20 import org.eclipse.nebula.widgets.nattable.hideshow.command.RowHideCommand;\r
21 import org.eclipse.nebula.widgets.nattable.hideshow.event.HideRowPositionsEvent;\r
22 import org.eclipse.nebula.widgets.nattable.hideshow.event.ShowRowPositionsEvent;\r
23 import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;\r
24 import org.eclipse.nebula.widgets.nattable.layer.LabelStack;\r
25 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;\r
26 import org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter;\r
27 import org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper;\r
28 import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;\r
29 import org.eclipse.nebula.widgets.nattable.tree.ITreeRowModel;\r
30 import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;\r
31 import org.eclipse.nebula.widgets.nattable.tree.config.DefaultTreeLayerConfiguration;\r
32 import org.eclipse.nebula.widgets.nattable.tree.config.TreeConfigAttributes;\r
33 import org.eclipse.nebula.widgets.nattable.tree.painter.IndentedTreeImagePainter;\r
34 \r
35 import it.unimi.dsi.fastutil.ints.IntRBTreeSet;\r
36 \r
37 public class TreeLayer2 extends AbstractRowHideShowLayer2 {\r
38 \r
39     //private static final Log log = LogFactory.getLog(TreeLayer.class);\r
40 \r
41     public static final String TREE_COLUMN_CELL = "TREE_COLUMN_CELL"; //$NON-NLS-1$\r
42 \r
43     public static final int TREE_COLUMN_NUMBER = 0;\r
44 \r
45     /**\r
46      * Flag to configure whether the tree column should be identified by\r
47      * position or by index. Default is position.\r
48      */\r
49     private boolean useTreeColumnIndex = false;\r
50 \r
51     /**\r
52      * The ITreeRowModelListener that is used to get information about the tree\r
53      * structure.\r
54      */\r
55     private final ITreeRowModel<?> treeRowModel;\r
56 \r
57     /**\r
58      * Collection of all row indexes that are hidden if tree nodes are\r
59      * collapsed.\r
60      * <p>\r
61      * Note: This collection is only in use if the used {@link ITreeRowModel}\r
62      * implementation is returning the row indexes of affected rows on\r
63      * expand/collapse. There are also implementations that use another approach\r
64      * where the hide/show approach is not used (e.g. GlazedListTreeRowModel)\r
65      * </p>\r
66      */\r
67         private final IntRBTreeSet hiddenRowIndexes = new IntRBTreeSet();\r
68 \r
69     /**\r
70      * The IndentedTreeImagePainter that paints indentation to the left of the\r
71      * configured base painter and icons for expand/collapse if possible, to\r
72      * render tree structure accordingly.\r
73      */\r
74     private IndentedTreeImagePainter indentedTreeImagePainter;\r
75 \r
76     /**\r
77      * Creates a TreeLayer instance based on the given information. Will use a\r
78      * default IndentedTreeImagePainter that uses 10 pixels for indentation and\r
79      * simple + and - icons for expand/collapse icons. It also uses the\r
80      * DefaultTreeLayerConfiguration.\r
81      *\r
82      * @param underlyingLayer\r
83      *            The underlying layer on whose top this layer will be set.\r
84      * @param treeRowModel\r
85      *            The ITreeRowModelListener that is used to get information\r
86      *            about the tree structure.\r
87      */\r
88     public TreeLayer2(IUniqueIndexLayer underlyingLayer, ITreeRowModel<?> treeRowModel) {\r
89         this(underlyingLayer, treeRowModel, new IndentedTreeImagePainter());\r
90     }\r
91 \r
92     /**\r
93      * Creates a TreeLayer instance based on the given information. Allows to\r
94      * specify the IndentedTreeImagePainter while using the\r
95      * DefaultTreeLayerConfiguration.\r
96      *\r
97      * @param underlyingLayer\r
98      *            The underlying layer on whose top this layer will be set.\r
99      * @param treeRowModel\r
100      *            The ITreeRowModelListener that is used to get information\r
101      *            about the tree structure.\r
102      * @param indentedTreeImagePainter\r
103      *            The IndentedTreeImagePainter that paints indentation to the\r
104      *            left of the configured base painter and icons for\r
105      *            expand/collapse if possible, to render tree structure\r
106      *            accordingly.\r
107      */\r
108     public TreeLayer2(\r
109             IUniqueIndexLayer underlyingLayer,\r
110             ITreeRowModel<?> treeRowModel,\r
111             IndentedTreeImagePainter indentedTreeImagePainter) {\r
112         this(underlyingLayer, treeRowModel, indentedTreeImagePainter, true);\r
113     }\r
114 \r
115     /**\r
116      * Creates a TreeLayer instance based on the given information. Will use a\r
117      * default IndentedTreeImagePainter that uses 10 pixels for indentation and\r
118      * simple + and - icons for expand/collapse icons.\r
119      *\r
120      * @param underlyingLayer\r
121      *            The underlying layer on whose top this layer will be set.\r
122      * @param treeRowModel\r
123      *            The ITreeRowModelListener that is used to get information\r
124      *            about the tree structure.\r
125      * @param useDefaultConfiguration\r
126      *            <code>true</code> to use the DefaultTreeLayerConfiguration,\r
127      *            <code>false</code> if you want to specify your own\r
128      *            configuration.\r
129      */\r
130     public TreeLayer2(\r
131             IUniqueIndexLayer underlyingLayer,\r
132             ITreeRowModel<?> treeRowModel,\r
133             boolean useDefaultConfiguration) {\r
134         this(underlyingLayer,\r
135                 treeRowModel,\r
136                 new IndentedTreeImagePainter(),\r
137                 useDefaultConfiguration);\r
138     }\r
139 \r
140     /**\r
141      * Creates a TreeLayer instance based on the given information.\r
142      *\r
143      * @param underlyingLayer\r
144      *            The underlying layer on whose top this layer will be set.\r
145      * @param treeRowModel\r
146      *            The ITreeRowModelListener that is used to get information\r
147      *            about the tree structure.\r
148      * @param indentedTreeImagePainter\r
149      *            The IndentedTreeImagePainter that paints indentation to the\r
150      *            left of the configured base painter and icons for\r
151      *            expand/collapse if possible, to render tree structure\r
152      *            accordingly.\r
153      * @param useDefaultConfiguration\r
154      *            <code>true</code> to use the DefaultTreeLayerConfiguration,\r
155      *            <code>false</code> if you want to specify your own\r
156      *            configuration.\r
157      */\r
158     public TreeLayer2(\r
159             IUniqueIndexLayer underlyingLayer,\r
160             ITreeRowModel<?> treeRowModel,\r
161             IndentedTreeImagePainter indentedTreeImagePainter,\r
162             boolean useDefaultConfiguration) {\r
163 \r
164         super(underlyingLayer);\r
165         this.treeRowModel = treeRowModel;\r
166 \r
167         if (useDefaultConfiguration) {\r
168             addConfiguration(new DefaultTreeLayerConfiguration2(this));\r
169         }\r
170 \r
171         this.indentedTreeImagePainter = indentedTreeImagePainter;\r
172 \r
173         registerCommandHandler(new TreeExpandCollapseCommandHandler(this));\r
174         registerCommandHandler(new TreeCollapseAllCommandHandler(this));\r
175         registerCommandHandler(new TreeExpandAllCommandHandler(this));\r
176         registerCommandHandler(new TreeExpandToLevelCommandHandler(this));\r
177     }\r
178 \r
179     @Override\r
180     public LabelStack getConfigLabelsByPosition(int columnPosition, int rowPosition) {\r
181         LabelStack configLabels = super.getConfigLabelsByPosition(columnPosition, rowPosition);\r
182 \r
183         if (isTreeColumn(columnPosition)) {\r
184             configLabels.addLabelOnTop(TREE_COLUMN_CELL);\r
185 \r
186             int rowIndex = getRowIndexByPosition(rowPosition);\r
187             configLabels.addLabelOnTop(\r
188                     DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + this.treeRowModel.depth(rowIndex));\r
189             if (!this.treeRowModel.hasChildren(rowIndex)) {\r
190                 configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);\r
191             } else {\r
192                 if (this.treeRowModel.isCollapsed(rowIndex)) {\r
193                     configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);\r
194                 } else {\r
195                     configLabels.addLabelOnTop(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);\r
196                 }\r
197             }\r
198         }\r
199         return configLabels;\r
200     }\r
201 \r
202     /**\r
203      * @return The ITreeRowModelListener that is used to get information about\r
204      *         the tree structure.\r
205      */\r
206     public ITreeRowModel<?> getModel() {\r
207         return this.treeRowModel;\r
208     }\r
209 \r
210     /**\r
211      * @return The IndentedTreeImagePainter that paints indentation to the left\r
212      *         of the configured base painter and icons for expand/collapse if\r
213      *         possible, to render tree structure accordingly.\r
214      *\r
215      * @deprecated since 1.1 the configured TreeImagePainter should be used\r
216      *             instead of the hard referenced one\r
217      */\r
218     @Deprecated\r
219     public IndentedTreeImagePainter getIndentedTreeImagePainter() {\r
220         return this.indentedTreeImagePainter;\r
221     }\r
222 \r
223     /**\r
224      * @return The ICellPainter that is used to paint the images in the tree by\r
225      *         the IndentedTreeImagePainter. Usually it is some type of\r
226      *         TreeImagePainter that paints expand/collapse/leaf icons regarding\r
227      *         the node state.<br>\r
228      *         Can be <code>null</code> if set explicitly to the\r
229      *         IndentedTreeImagePainter!\r
230      *\r
231      * @deprecated since 1.1 the configured TreeImagePainter should be used\r
232      *             instead of the hard referenced one\r
233      */\r
234     @Deprecated\r
235     public ICellPainter getTreeImagePainter() {\r
236         return this.indentedTreeImagePainter != null ? this.indentedTreeImagePainter\r
237                 .getTreeImagePainter() : null;\r
238     }\r
239 \r
240     /**\r
241      * @param columnPosition\r
242      *            The column position to check.\r
243      * @return <code>true</code> if the given column position is the tree\r
244      *         column, <code>false</code> if not.\r
245      */\r
246     private boolean isTreeColumn(int columnPosition) {\r
247         if (this.useTreeColumnIndex)\r
248             return getColumnIndexByPosition(columnPosition) == TREE_COLUMN_NUMBER;\r
249 \r
250         return columnPosition == TREE_COLUMN_NUMBER;\r
251     }\r
252 \r
253     @Override\r
254     public ICellPainter getCellPainter(\r
255             int columnPosition, int rowPosition,\r
256             ILayerCell cell, IConfigRegistry configRegistry) {\r
257         ICellPainter cellPainter = super.getCellPainter(\r
258                 columnPosition, rowPosition, cell, configRegistry);\r
259 \r
260         if (cell.getConfigLabels().hasLabel(TREE_COLUMN_CELL)) {\r
261 \r
262             ICellPainter treeCellPainter = configRegistry.getConfigAttribute(\r
263                     TreeConfigAttributes.TREE_STRUCTURE_PAINTER,\r
264                     cell.getDisplayMode(),\r
265                     cell.getConfigLabels().getLabels());\r
266 \r
267             if (treeCellPainter != null) {\r
268                 ICellPainter innerWrapper = treeCellPainter;\r
269                 IndentedTreeImagePainter treePainter = null;\r
270                 if (innerWrapper instanceof IndentedTreeImagePainter) {\r
271                     treePainter = (IndentedTreeImagePainter) innerWrapper;\r
272                 } else {\r
273                     while (treePainter == null\r
274                             && innerWrapper != null\r
275                             && innerWrapper instanceof CellPainterWrapper\r
276                             && ((CellPainterWrapper) innerWrapper).getWrappedPainter() != null) {\r
277 \r
278                         innerWrapper = ((CellPainterWrapper) innerWrapper).getWrappedPainter();\r
279                         if (innerWrapper instanceof IndentedTreeImagePainter) {\r
280                             treePainter = (IndentedTreeImagePainter) innerWrapper;\r
281                         }\r
282                     }\r
283                 }\r
284 \r
285                 if (treePainter != null) {\r
286                     treePainter.setBaseCellPainter(cellPainter);\r
287                     cellPainter = treeCellPainter;\r
288                 } else {\r
289                     // log error\r
290 //                    log.warn("There is no IndentedTreeImagePainter found for TREE_STRUCTURE_PAINTER, " //$NON-NLS-1$\r
291 //                            + "using local configured IndentedTreeImagePainter as fallback"); //$NON-NLS-1$\r
292                     // fallback\r
293                     this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);\r
294                     cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);\r
295                 }\r
296             } else {\r
297                 // backwards compatibility fallback\r
298                 this.indentedTreeImagePainter.setBaseCellPainter(cellPainter);\r
299                 cellPainter = new BackgroundPainter(this.indentedTreeImagePainter);\r
300             }\r
301         }\r
302 \r
303         return cellPainter;\r
304     }\r
305 \r
306     @Override\r
307     public boolean isRowIndexHidden(int rowIndex) {\r
308         return this.hiddenRowIndexes.contains(rowIndex)\r
309                 || isHiddenInUnderlyingLayer(rowIndex);\r
310     }\r
311 \r
312     @Override\r
313     public Collection<Integer> getHiddenRowIndexes() {\r
314         return this.hiddenRowIndexes;\r
315     }\r
316 \r
317     /**\r
318      * Performs an expand/collapse action dependent on the current state of the\r
319      * tree node at the given row index.\r
320      *\r
321      * @param parentIndex\r
322      *            The index of the row that shows the tree node for which the\r
323      *            expand/collapse action should be performed.\r
324      */\r
325     public void expandOrCollapseIndex(int parentIndex) {\r
326         if (this.treeRowModel.isCollapsed(parentIndex)) {\r
327             expandTreeRow(parentIndex);\r
328         } else {\r
329             collapseTreeRow(parentIndex);\r
330         }\r
331     }\r
332 \r
333     /**\r
334      * Collapses the tree node for the given row index.\r
335      *\r
336      * @param parentIndex\r
337      *            The index of the row that shows the node that should be\r
338      *            collapsed\r
339      */\r
340     public void collapseTreeRow(int parentIndex) {\r
341         List<Integer> rowIndexes = this.treeRowModel.collapse(parentIndex);\r
342         List<Integer> rowPositions = new ArrayList<Integer>();\r
343         for (Integer rowIndex : rowIndexes) {\r
344             int rowPos = getRowPositionByIndex(rowIndex);\r
345             // if the rowPos is negative, it is not visible because of hidden\r
346             // state in an underlying layer\r
347             if (rowPos >= 0) {\r
348                 rowPositions.add(rowPos);\r
349             }\r
350         }\r
351         this.hiddenRowIndexes.addAll(rowIndexes);\r
352         invalidateCache();\r
353         fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));\r
354     }\r
355 \r
356     /**\r
357      * Collapses all tree nodes in the tree.\r
358      */\r
359     public void collapseAll() {\r
360         List<Integer> rowIndexes = this.treeRowModel.collapseAll();\r
361         List<Integer> rowPositions = new ArrayList<Integer>();\r
362         for (Integer rowIndex : rowIndexes) {\r
363             int rowPos = getRowPositionByIndex(rowIndex);\r
364             // if the rowPos is negative, it is not visible because of hidden\r
365             // state in an underlying layer\r
366             if (rowPos >= 0) {\r
367                 rowPositions.add(rowPos);\r
368             }\r
369         }\r
370         this.hiddenRowIndexes.addAll(rowIndexes);\r
371         invalidateCache();\r
372         fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));\r
373     }\r
374 \r
375     /**\r
376      * Expands the tree node for the given row index.\r
377      *\r
378      * @param parentIndex\r
379      *            The index of the row that shows the node that should be\r
380      *            expanded\r
381      */\r
382     public void expandTreeRow(int parentIndex) {\r
383         List<Integer> rowIndexes = this.treeRowModel.expand(parentIndex);\r
384         // Bug 432865: iterating and removing every single item is faster than\r
385         // removeAll()\r
386         for (final Integer expandedChildRowIndex : rowIndexes) {\r
387             this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
388         }\r
389         invalidateCache();\r
390         fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
391     }\r
392 \r
393     /**\r
394      * Expands the tree node for the given row index in the tree to a certain\r
395      * level.\r
396      *\r
397      * @param parentIndex\r
398      *            The index of the row that shows the node that should be\r
399      *            expanded\r
400      * @param level\r
401      *            The level to which the tree node should be expanded.\r
402      */\r
403     public void expandTreeRowToLevel(int parentIndex, int level) {\r
404         List<Integer> rowIndexes = this.treeRowModel.expandToLevel(parentIndex, level);\r
405         // Bug 432865: iterating and removing every single item is faster than\r
406         // removeAll()\r
407         for (final Integer expandedChildRowIndex : rowIndexes) {\r
408             this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
409         }\r
410         invalidateCache();\r
411         fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
412     }\r
413 \r
414     /**\r
415      * Expands all tree nodes in the tree.\r
416      */\r
417     public void expandAll() {\r
418         List<Integer> rowIndexes = this.treeRowModel.expandAll();\r
419         this.hiddenRowIndexes.clear();\r
420         invalidateCache();\r
421         fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
422     }\r
423 \r
424     /**\r
425      * Expands all tree nodes in the tree to a certain level.\r
426      *\r
427      * @param level\r
428      *            The level to which the tree node should be expanded.\r
429      */\r
430     public void expandAllToLevel(int level) {\r
431         List<Integer> rowIndexes = this.treeRowModel.expandToLevel(level);\r
432         // Bug 432865: iterating and removing every single item is faster than\r
433         // removeAll()\r
434 //        for (final Integer expandedChildRowIndex : rowIndexes) {\r
435 //            this.hiddenRowIndexes.remove(expandedChildRowIndex);\r
436 //        }\r
437         if (rowIndexes == null)\r
438                 return;\r
439         for (int i = rowIndexes.size()-1; i>=0; i--) {\r
440                 this.hiddenRowIndexes.remove(rowIndexes.get(i));\r
441         }\r
442         invalidateCache();\r
443         fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
444     }\r
445 \r
446     /**\r
447      * Checks the underlying layer if the row is hidden by another layer.\r
448      *\r
449      * @param rowIndex\r
450      *            The index of the row whose hidden state should be checked\r
451      * @return <code>true</code> if the row at the given index is hidden in the\r
452      *         underlying layer <code>false</code> if not.\r
453      */\r
454     private boolean isHiddenInUnderlyingLayer(int rowIndex) {\r
455         IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();\r
456         return (underlyingLayer.getRowPositionByIndex(rowIndex) == -1);\r
457     }\r
458 \r
459     @Override\r
460     public boolean doCommand(ILayerCommand command) {\r
461         // special command transformations are needed to hide also child nodes\r
462         if (command instanceof RowHideCommand) {\r
463             return handleRowHideCommand((RowHideCommand) command);\r
464         } else if (command instanceof MultiRowHideCommand) {\r
465             return handleMultiRowHideCommand((MultiRowHideCommand) command);\r
466         }\r
467         return super.doCommand(command);\r
468     }\r
469 \r
470     /**\r
471      * Checks if the given command tries to hide a row that is a node that is\r
472      * not collapsed and has children. In that case also the child rows need to\r
473      * be hidden.\r
474      *\r
475      * @param command\r
476      *            The {@link RowHideCommand} to process\r
477      * @return <code>true</code> if the command has been handled,\r
478      *         <code>false</code> otherwise\r
479      */\r
480     protected boolean handleRowHideCommand(RowHideCommand command) {\r
481         // transform position to index\r
482         if (command.convertToTargetLayer(this)) {\r
483             int rowIndex = getRowIndexByPosition(command.getRowPosition());\r
484             if (this.treeRowModel.hasChildren(rowIndex)\r
485                     && !this.treeRowModel.isCollapsed(rowIndex)) {\r
486                 List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);\r
487                 int[] childPositions = new int[childIndexes.size() + 1];\r
488                 childPositions[0] = command.getRowPosition();\r
489                 for (int i = 1; i < childIndexes.size() + 1; i++) {\r
490                     int childPos = getRowPositionByIndex(childIndexes.get(i - 1));\r
491                     childPositions[i] = childPos;\r
492                 }\r
493                 return super.doCommand(new MultiRowHideCommand(this, childPositions));\r
494             }\r
495         }\r
496         return super.doCommand(command);\r
497     }\r
498 \r
499     /**\r
500      * Checks if the given command tries to hide rows that are nodes that are\r
501      * not collapsed and have children. In that case also the child rows need to\r
502      * be hidden.\r
503      *\r
504      * @param command\r
505      *            The {@link MultiRowHideCommand} to process\r
506      * @return <code>true</code> if the command has been handled,\r
507      *         <code>false</code> otherwise\r
508      */\r
509     protected boolean handleMultiRowHideCommand(MultiRowHideCommand command) {\r
510         // transform position to index\r
511         if (command.convertToTargetLayer(this)) {\r
512             List<Integer> rowPositionsToHide = new ArrayList<Integer>();\r
513             for (Integer rowPos : command.getRowPositions()) {\r
514                 rowPositionsToHide.add(rowPos);\r
515                 int rowIndex = getRowIndexByPosition(rowPos);\r
516                 if (this.treeRowModel.hasChildren(rowIndex)\r
517                         && !this.treeRowModel.isCollapsed(rowIndex)) {\r
518                     List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);\r
519                     for (Integer childIndex : childIndexes) {\r
520                         rowPositionsToHide.add(getRowPositionByIndex(childIndex));\r
521                     }\r
522                 }\r
523             }\r
524 \r
525             int[] childPositions = new int[rowPositionsToHide.size()];\r
526             for (int i = 0; i < rowPositionsToHide.size(); i++) {\r
527                 childPositions[i] = rowPositionsToHide.get(i);\r
528             }\r
529             return super.doCommand(new MultiRowHideCommand(this, childPositions));\r
530         }\r
531         return super.doCommand(command);\r
532     }\r
533 \r
534     /**\r
535      * @return <code>true</code> if the column index is used to determine the\r
536      *         tree column, <code>false</code> if the column position is used.\r
537      *         Default is <code>false</code>.\r
538      */\r
539     public boolean isUseTreeColumnIndex() {\r
540         return this.useTreeColumnIndex;\r
541     }\r
542 \r
543     /**\r
544      * Configure whether (column index == 0) or (column position == 0) should be\r
545      * performed to identify the tree column.\r
546      *\r
547      * @param useTreeColumnIndex\r
548      *            <code>true</code> if the column index should be used to\r
549      *            determine the tree column, <code>false</code> if the column\r
550      *            position should be used.\r
551      */\r
552     public void setUseTreeColumnIndex(boolean useTreeColumnIndex) {\r
553         this.useTreeColumnIndex = useTreeColumnIndex;\r
554     }\r
555 \r
556     /**\r
557      * @since 1.4\r
558      */\r
559     @Override\r
560     public Collection<String> getProvidedLabels() {\r
561         Collection<String> result = super.getProvidedLabels();\r
562 \r
563         result.add(TreeLayer.TREE_COLUMN_CELL);\r
564         result.add(DefaultTreeLayerConfiguration.TREE_LEAF_CONFIG_TYPE);\r
565         result.add(DefaultTreeLayerConfiguration.TREE_COLLAPSED_CONFIG_TYPE);\r
566         result.add(DefaultTreeLayerConfiguration.TREE_EXPANDED_CONFIG_TYPE);\r
567         // configure 5 levels to be configurable via CSS\r
568         // if you need more you need to override this method\r
569         result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "0"); //$NON-NLS-1$\r
570         result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "1"); //$NON-NLS-1$\r
571         result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "2"); //$NON-NLS-1$\r
572         result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "3"); //$NON-NLS-1$\r
573         result.add(DefaultTreeLayerConfiguration.TREE_DEPTH_CONFIG_TYPE + "4"); //$NON-NLS-1$\r
574 \r
575         return result;\r
576     }\r
577 }\r