6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.javafx.scene.control.skin;
27
28 import javafx.collections.FXCollections;
29 import javafx.scene.control.Control;
30 import javafx.scene.control.TableColumnBase;
31 import javafx.scene.control.TreeItem;
32 import javafx.scene.control.TreeTableCell;
33 import javafx.scene.control.TreeTableColumn;
34 import javafx.scene.control.TreeTablePosition;
35 import javafx.scene.control.TreeTableRow;
36 import javafx.scene.control.TreeTableView;
37
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.List;
41
42 import javafx.beans.property.DoubleProperty;
43 import javafx.scene.AccessibleAttribute;
44 import javafx.scene.Node;
45 import javafx.css.StyleableDoubleProperty;
46 import javafx.css.CssMetaData;
47
48 import com.sun.javafx.css.converters.SizeConverter;
49 import com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler;
50 import com.sun.javafx.scene.control.behavior.TreeTableRowBehavior;
51
52 import javafx.beans.property.ObjectProperty;
53 import javafx.beans.property.SimpleObjectProperty;
54 import javafx.beans.value.WritableValue;
55 import javafx.collections.ObservableList;
56 import javafx.css.Styleable;
57 import javafx.css.StyleableProperty;
58
59 public class TreeTableRowSkin<T> extends TableRowSkinBase<TreeItem<T>, TreeTableRow<T>, TreeTableRowBehavior<T>, TreeTableCell<T,?>> {
60
61 /***************************************************************************
62 * *
63 * Private Fields *
64 * *
65 **************************************************************************/
66
67 // maps into the TreeTableViewSkin items property via
68 // TreeTableViewSkin.treeItemToListMap
69 private SimpleObjectProperty<ObservableList<TreeItem<T>>> itemsProperty;
70 private TreeItem<?> treeItem;
71 private boolean disclosureNodeDirty = true;
72 private Node graphic;
73
74 private TreeTableViewSkin treeTableViewSkin;
75
76 private boolean childrenDirty = false;
77
78
79
80 /***************************************************************************
81 * *
82 * Constructors *
83 * *
84 **************************************************************************/
85
86 public TreeTableRowSkin(TreeTableRow<T> control) {
87 super(control, new TreeTableRowBehavior<T>(control));
88
89 super.init(control);
90
91 updateTreeItem();
92 updateTableViewSkin();
93
94 registerChangeListener(control.treeTableViewProperty(), "TREE_TABLE_VIEW");
95 registerChangeListener(control.indexProperty(), "INDEX");
96 registerChangeListener(control.treeItemProperty(), "TREE_ITEM");
97 registerChangeListener(control.getTreeTableView().treeColumnProperty(), "TREE_COLUMN");
98 }
99
100
101
102 /***************************************************************************
103 * *
104 * Listeners *
105 * *
106 **************************************************************************/
107
108 private MultiplePropertyChangeListenerHandler treeItemListener = new MultiplePropertyChangeListenerHandler(p -> {
109 if ("GRAPHIC".equals(p)) {
110 disclosureNodeDirty = true;
111 getSkinnable().requestLayout();
112 }
113 return null;
114 });
115
116
117
118 /***************************************************************************
119 * *
120 * Properties *
121 * *
122 **************************************************************************/
123
124 /**
125 * The amount of space to multiply by the treeItem.level to get the left
126 * margin for this tree cell. This is settable from CSS
127 */
128 private DoubleProperty indent = null;
129 public final void setIndent(double value) { indentProperty().set(value); }
130 public final double getIndent() { return indent == null ? 10.0 : indent.get(); }
131 public final DoubleProperty indentProperty() {
132 if (indent == null) {
133 indent = new StyleableDoubleProperty(10.0) {
134 @Override public Object getBean() {
135 return TreeTableRowSkin.this;
136 }
137
138 @Override public String getName() {
139 return "indent";
140 }
141
142 @Override public CssMetaData<TreeTableRow<?>,Number> getCssMetaData() {
143 return TreeTableRowSkin.StyleableProperties.INDENT;
144 }
145 };
146 }
147 return indent;
148 }
149
150
151
152 /***************************************************************************
153 * *
154 * Public Methods *
155 * *
156 **************************************************************************/
157
158 @Override protected void handleControlPropertyChanged(String p) {
159 super.handleControlPropertyChanged(p);
160
161 if ("TREE_ABLE_VIEW".equals(p)) {
162 updateTableViewSkin();
163 } else if ("INDEX".equals(p)) {
164 updateCells = true;
165 } else if ("TREE_ITEM".equals(p)) {
166 updateTreeItem();
167 isDirty = true;
168 } else if ("TREE_COLUMN".equals(p)) {
169 // Fix for RT-27782: Need to set isDirty to true, rather than the
170 // cheaper updateCells, as otherwise the text indentation will not
171 // be recalculated in TreeTableCellSkin.leftLabelPadding()
172 isDirty = true;
173 getSkinnable().requestLayout();
174 }
175 }
176
177 @Override protected void updateChildren() {
178 super.updateChildren();
179
180 updateDisclosureNodeAndGraphic();
181
182 if (childrenDirty) {
183 childrenDirty = false;
184 if (cells.isEmpty()) {
185 getChildren().clear();
186 } else {
187 // TODO we can optimise this by only showing cells that are
188 // visible based on the table width and the amount of horizontal
189 // scrolling.
190 getChildren().addAll(cells);
191 }
192 }
193 }
194
195 @Override protected void layoutChildren(double x, double y, double w, double h) {
196 if (disclosureNodeDirty) {
197 updateDisclosureNodeAndGraphic();
198 disclosureNodeDirty = false;
199 }
200
201 Node disclosureNode = getDisclosureNode();
202 if (disclosureNode != null && disclosureNode.getScene() == null) {
203 updateDisclosureNodeAndGraphic();
204 }
205
206 super.layoutChildren(x, y, w, h);
207 }
208
209 @Override protected TreeTableCell<T, ?> getCell(TableColumnBase tcb) {
210 TreeTableColumn tableColumn = (TreeTableColumn<T,?>) tcb;
211 TreeTableCell cell = (TreeTableCell) tableColumn.getCellFactory().call(tableColumn);
212
213 cell.updateTreeTableColumn(tableColumn);
214 cell.updateTreeTableView(tableColumn.getTreeTableView());
215
216 return cell;
217 }
218
219 @Override protected void updateCells(boolean resetChildren) {
220 super.updateCells(resetChildren);
221
222 if (resetChildren) {
223 childrenDirty = true;
224 updateChildren();
225 }
226 }
227
228 @Override protected boolean isIndentationRequired() {
229 return true;
230 }
231
232 @Override protected TableColumnBase getTreeColumn() {
233 return getSkinnable().getTreeTableView().getTreeColumn();
234 }
235
236 @Override protected int getIndentationLevel(TreeTableRow<T> control) {
237 return control.getTreeTableView().getTreeItemLevel(control.getTreeItem());
238 }
239
240 @Override protected double getIndentationPerLevel() {
241 return getIndent();
242 }
243
244 @Override protected Node getDisclosureNode() {
245 return getSkinnable().getDisclosureNode();
246 }
247
248 @Override protected boolean isDisclosureNodeVisible() {
249 return getDisclosureNode() != null && treeItem != null && ! treeItem.isLeaf();
250 }
251
252 @Override protected boolean isShowRoot() {
253 return getSkinnable().getTreeTableView().isShowRoot();
254 }
255
256 @Override protected ObservableList<TreeTableColumn<T, ?>> getVisibleLeafColumns() {
257 return getSkinnable().getTreeTableView().getVisibleLeafColumns();
258 }
259
260 @Override protected void updateCell(TreeTableCell<T, ?> cell, TreeTableRow<T> row) {
261 cell.updateTreeTableRow(row);
262 }
263
264 @Override protected boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
265 return treeTableViewSkin == null ? false : treeTableViewSkin.isColumnPartiallyOrFullyVisible(tc);
266 }
267
268 @Override protected TreeTableColumn<T, ?> getTableColumnBase(TreeTableCell cell) {
269 return cell.getTableColumn();
270 }
271
272 @Override protected ObjectProperty<Node> graphicProperty() {
273 TreeTableRow<T> treeTableRow = getSkinnable();
274 if (treeTableRow == null) return null;
275 if (treeItem == null) return null;
276
277 return treeItem.graphicProperty();
278 }
279
280 @Override protected Control getVirtualFlowOwner() {
281 return getSkinnable().getTreeTableView();
282 }
283
284 @Override protected DoubleProperty fixedCellSizeProperty() {
285 return getSkinnable().getTreeTableView().fixedCellSizeProperty();
286 }
287
288
289
290 /***************************************************************************
291 * *
292 * Private Implementation *
293 * *
294 **************************************************************************/
295
296 private void updateTreeItem() {
297 if (treeItem != null) {
298 treeItemListener.unregisterChangeListener(treeItem.expandedProperty());
299 treeItemListener.unregisterChangeListener(treeItem.graphicProperty());
300 }
301 treeItem = getSkinnable().getTreeItem();
302 if (treeItem != null) {
303 treeItemListener.registerChangeListener(treeItem.graphicProperty(), "GRAPHIC");
304 }
305 }
306
307 private void updateDisclosureNodeAndGraphic() {
308 if (getSkinnable().isEmpty()) return;
309
310 // check for graphic missing
311 ObjectProperty<Node> graphicProperty = graphicProperty();
312 Node newGraphic = graphicProperty == null ? null : graphicProperty.get();
313 if (newGraphic != null) {
314 // RT-30466: remove the old graphic
315 if (newGraphic != graphic) {
316 getChildren().remove(graphic);
317 }
318
319 if (! getChildren().contains(newGraphic)) {
320 getChildren().add(newGraphic);
321 graphic = newGraphic;
322 }
323 }
370 DoubleProperty p = ((TreeTableRowSkin<?>) n.getSkin()).indentProperty();
371 return p == null || !p.isBound();
372 }
373
374 @Override public StyleableProperty<Number> getStyleableProperty(TreeTableRow<?> n) {
375 final TreeTableRowSkin<?> skin = (TreeTableRowSkin<?>) n.getSkin();
376 return (StyleableProperty<Number>)(WritableValue<Number>)skin.indentProperty();
377 }
378 };
379
380 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
381 static {
382 final List<CssMetaData<? extends Styleable, ?>> styleables =
383 new ArrayList<CssMetaData<? extends Styleable, ?>>(CellSkinBase.getClassCssMetaData());
384 styleables.add(INDENT);
385 STYLEABLES = Collections.unmodifiableList(styleables);
386 }
387 }
388
389 /**
390 * @return The CssMetaData associated with this class, which may include the
391 * CssMetaData of its super classes.
392 */
393 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
394 return StyleableProperties.STYLEABLES;
395 }
396
397 /**
398 * {@inheritDoc}
399 */
400 @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
401 return getClassCssMetaData();
402 }
403
404
405
406 @Override
407 protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
408 final TreeTableView<T> treeTableView = getSkinnable().getTreeTableView();
409 switch (attribute) {
410 case SELECTED_ITEMS: {
411 // FIXME this could be optimised to iterate over cellsMap only
412 // (selectedCells could be big, cellsMap is much smaller)
413 List<Node> selection = new ArrayList<>();
414 int index = getSkinnable().getIndex();
415 for (TreeTablePosition<T,?> pos : treeTableView.getSelectionModel().getSelectedCells()) {
416 if (pos.getRow() == index) {
417 TreeTableColumn<T,?> column = pos.getTableColumn();
418 if (column == null) {
419 /* This is the row-based case */
420 column = treeTableView.getVisibleLeafColumn(0);
421 }
422 TreeTableCell<T,?> cell = cellsMap.get(column).get();
423 if (cell != null) selection.add(cell);
424 }
425 return FXCollections.observableArrayList(selection);
426 }
427 }
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.scene.control.skin;
27
28 import com.sun.javafx.scene.control.behavior.BehaviorBase;
29 import javafx.beans.InvalidationListener;
30 import javafx.collections.FXCollections;
31 import javafx.scene.control.Control;
32 import javafx.scene.control.TableColumnBase;
33 import javafx.scene.control.TreeItem;
34 import javafx.scene.control.TreeTableCell;
35 import javafx.scene.control.TreeTableColumn;
36 import javafx.scene.control.TreeTablePosition;
37 import javafx.scene.control.TreeTableRow;
38 import javafx.scene.control.TreeTableView;
39
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.List;
43
44 import javafx.beans.property.DoubleProperty;
45 import javafx.scene.AccessibleAttribute;
46 import javafx.scene.Node;
47 import javafx.css.StyleableDoubleProperty;
48 import javafx.css.CssMetaData;
49
50 import javafx.css.converter.SizeConverter;
51 import com.sun.javafx.scene.control.behavior.TreeTableRowBehavior;
52
53 import javafx.beans.property.ObjectProperty;
54 import javafx.beans.value.WritableValue;
55 import javafx.collections.ObservableList;
56 import javafx.css.Styleable;
57 import javafx.css.StyleableProperty;
58
59 /**
60 * Default skin implementation for the {@link TreeTableRow} control.
61 *
62 * @see TreeTableRow
63 * @since 9
64 */
65 public class TreeTableRowSkin<T> extends TableRowSkinBase<TreeItem<T>, TreeTableRow<T>, TreeTableCell<T,?>> {
66
67 /***************************************************************************
68 * *
69 * Private Fields *
70 * *
71 **************************************************************************/
72
73 // maps into the TreeTableViewSkin items property via
74 // TreeTableViewSkin.treeItemToListMap
75 private TreeItem<?> treeItem;
76 private boolean disclosureNodeDirty = true;
77 private Node graphic;
78 private final BehaviorBase<TreeTableRow<T>> behavior;
79
80 private TreeTableViewSkin treeTableViewSkin;
81
82 private boolean childrenDirty = false;
83
84
85
86 /***************************************************************************
87 * *
88 * Constructors *
89 * *
90 **************************************************************************/
91
92 /**
93 * Creates a new TreeTableRowSkin instance, installing the necessary child
94 * nodes into the Control {@link Control#getChildren() children} list, as
95 * well as the necessary input mappings for handling key, mouse, etc events.
96 *
97 * @param control The control that this skin should be installed onto.
98 */
99 public TreeTableRowSkin(TreeTableRow<T> control) {
100 super(control);
101
102 // install default input map for the TreeTableRow control
103 behavior = new TreeTableRowBehavior<>(control);
104 // control.setInputMap(behavior.getInputMap());
105
106 updateTreeItem();
107 updateTableViewSkin();
108
109 registerChangeListener(control.treeTableViewProperty(), e -> updateTableViewSkin());
110 registerChangeListener(control.indexProperty(), e -> updateCells = true);
111 registerChangeListener(control.treeItemProperty(), e -> {
112 updateTreeItem();
113 isDirty = true;
114 });
115 registerChangeListener(control.getTreeTableView().treeColumnProperty(), e -> {
116 // Fix for RT-27782: Need to set isDirty to true, rather than the
117 // cheaper updateCells, as otherwise the text indentation will not
118 // be recalculated in TreeTableCellSkin.leftLabelPadding()
119 isDirty = true;
120 getSkinnable().requestLayout();
121 });
122 }
123
124
125 /***************************************************************************
126 * *
127 * Listeners *
128 * *
129 **************************************************************************/
130
131 private final InvalidationListener graphicListener = o -> {
132 disclosureNodeDirty = true;
133 getSkinnable().requestLayout();
134 };
135
136
137 /***************************************************************************
138 * *
139 * Properties *
140 * *
141 **************************************************************************/
142
143 /**
144 * The amount of space to multiply by the treeItem.level to get the left
145 * margin for this tree cell. This is settable from CSS
146 */
147 private DoubleProperty indent = null;
148 public final void setIndent(double value) { indentProperty().set(value); }
149 public final double getIndent() { return indent == null ? 10.0 : indent.get(); }
150 public final DoubleProperty indentProperty() {
151 if (indent == null) {
152 indent = new StyleableDoubleProperty(10.0) {
153 @Override public Object getBean() {
154 return TreeTableRowSkin.this;
155 }
156
157 @Override public String getName() {
158 return "indent";
159 }
160
161 @Override public CssMetaData<TreeTableRow<?>,Number> getCssMetaData() {
162 return TreeTableRowSkin.StyleableProperties.INDENT;
163 }
164 };
165 }
166 return indent;
167 }
168
169
170
171 /***************************************************************************
172 * *
173 * Public API *
174 * *
175 **************************************************************************/
176
177 /** {@inheritDoc} */
178 @Override public void dispose() {
179 super.dispose();
180
181 if (behavior != null) {
182 behavior.dispose();
183 }
184 }
185
186 /** {@inheritDoc} */
187 @Override protected void updateChildren() {
188 super.updateChildren();
189
190 updateDisclosureNodeAndGraphic();
191
192 if (childrenDirty) {
193 childrenDirty = false;
194 if (cells.isEmpty()) {
195 getChildren().clear();
196 } else {
197 // TODO we can optimise this by only showing cells that are
198 // visible based on the table width and the amount of horizontal
199 // scrolling.
200 getChildren().addAll(cells);
201 }
202 }
203 }
204
205 /** {@inheritDoc} */
206 @Override protected void layoutChildren(double x, double y, double w, double h) {
207 if (disclosureNodeDirty) {
208 updateDisclosureNodeAndGraphic();
209 disclosureNodeDirty = false;
210 }
211
212 Node disclosureNode = getDisclosureNode();
213 if (disclosureNode != null && disclosureNode.getScene() == null) {
214 updateDisclosureNodeAndGraphic();
215 }
216
217 super.layoutChildren(x, y, w, h);
218 }
219
220
221
222 /***************************************************************************
223 * *
224 * Private Implementation *
225 * *
226 **************************************************************************/
227
228 /** {@inheritDoc} */
229 @Override TreeTableCell<T, ?> getCell(TableColumnBase tcb) {
230 TreeTableColumn tableColumn = (TreeTableColumn<T,?>) tcb;
231 TreeTableCell cell = (TreeTableCell) tableColumn.getCellFactory().call(tableColumn);
232
233 cell.updateTreeTableColumn(tableColumn);
234 cell.updateTreeTableView(tableColumn.getTreeTableView());
235
236 return cell;
237 }
238
239 /** {@inheritDoc} */
240 @Override void updateCells(boolean resetChildren) {
241 super.updateCells(resetChildren);
242
243 if (resetChildren) {
244 childrenDirty = true;
245 updateChildren();
246 }
247 }
248
249 /** {@inheritDoc} */
250 @Override boolean isIndentationRequired() {
251 return true;
252 }
253
254 /** {@inheritDoc} */
255 @Override TableColumnBase getTreeColumn() {
256 return getSkinnable().getTreeTableView().getTreeColumn();
257 }
258
259 /** {@inheritDoc} */
260 @Override int getIndentationLevel(TreeTableRow<T> control) {
261 return control.getTreeTableView().getTreeItemLevel(control.getTreeItem());
262 }
263
264 /** {@inheritDoc} */
265 @Override double getIndentationPerLevel() {
266 return getIndent();
267 }
268
269 /** {@inheritDoc} */
270 @Override Node getDisclosureNode() {
271 return getSkinnable().getDisclosureNode();
272 }
273
274 @Override boolean isDisclosureNodeVisible() {
275 return getDisclosureNode() != null && treeItem != null && ! treeItem.isLeaf();
276 }
277
278 @Override boolean isShowRoot() {
279 return getSkinnable().getTreeTableView().isShowRoot();
280 }
281
282 /** {@inheritDoc} */
283 @Override ObservableList<TreeTableColumn<T, ?>> getVisibleLeafColumns() {
284 return getSkinnable().getTreeTableView().getVisibleLeafColumns();
285 }
286
287 /** {@inheritDoc} */
288 @Override void updateCell(TreeTableCell<T, ?> cell, TreeTableRow<T> row) {
289 cell.updateTreeTableRow(row);
290 }
291
292 /** {@inheritDoc} */
293 @Override boolean isColumnPartiallyOrFullyVisible(TableColumnBase tc) {
294 return treeTableViewSkin == null ? false : treeTableViewSkin.isColumnPartiallyOrFullyVisible(tc);
295 }
296
297 /** {@inheritDoc} */
298 @Override TreeTableColumn<T, ?> getTableColumnBase(TreeTableCell cell) {
299 return cell.getTableColumn();
300 }
301
302 /** {@inheritDoc} */
303 @Override ObjectProperty<Node> graphicProperty() {
304 TreeTableRow<T> treeTableRow = getSkinnable();
305 if (treeTableRow == null) return null;
306 if (treeItem == null) return null;
307
308 return treeItem.graphicProperty();
309 }
310
311 /** {@inheritDoc} */
312 @Override Control getVirtualFlowOwner() {
313 return getSkinnable().getTreeTableView();
314 }
315
316 /** {@inheritDoc} */
317 @Override DoubleProperty fixedCellSizeProperty() {
318 return getSkinnable().getTreeTableView().fixedCellSizeProperty();
319 }
320
321 private void updateTreeItem() {
322 if (treeItem != null) {
323 treeItem.graphicProperty().removeListener(graphicListener);
324 }
325 treeItem = getSkinnable().getTreeItem();
326 if (treeItem != null) {
327 treeItem.graphicProperty().addListener(graphicListener);
328 }
329 }
330
331 private void updateDisclosureNodeAndGraphic() {
332 if (getSkinnable().isEmpty()) return;
333
334 // check for graphic missing
335 ObjectProperty<Node> graphicProperty = graphicProperty();
336 Node newGraphic = graphicProperty == null ? null : graphicProperty.get();
337 if (newGraphic != null) {
338 // RT-30466: remove the old graphic
339 if (newGraphic != graphic) {
340 getChildren().remove(graphic);
341 }
342
343 if (! getChildren().contains(newGraphic)) {
344 getChildren().add(newGraphic);
345 graphic = newGraphic;
346 }
347 }
394 DoubleProperty p = ((TreeTableRowSkin<?>) n.getSkin()).indentProperty();
395 return p == null || !p.isBound();
396 }
397
398 @Override public StyleableProperty<Number> getStyleableProperty(TreeTableRow<?> n) {
399 final TreeTableRowSkin<?> skin = (TreeTableRowSkin<?>) n.getSkin();
400 return (StyleableProperty<Number>)(WritableValue<Number>)skin.indentProperty();
401 }
402 };
403
404 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
405 static {
406 final List<CssMetaData<? extends Styleable, ?>> styleables =
407 new ArrayList<CssMetaData<? extends Styleable, ?>>(CellSkinBase.getClassCssMetaData());
408 styleables.add(INDENT);
409 STYLEABLES = Collections.unmodifiableList(styleables);
410 }
411 }
412
413 /**
414 * Returns the CssMetaData associated with this class, which may include the
415 * CssMetaData of its super classes.
416 */
417 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
418 return StyleableProperties.STYLEABLES;
419 }
420
421 /**
422 * {@inheritDoc}
423 */
424 @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
425 return getClassCssMetaData();
426 }
427
428
429 /** {@inheritDoc} */
430 @Override protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
431 final TreeTableView<T> treeTableView = getSkinnable().getTreeTableView();
432 switch (attribute) {
433 case SELECTED_ITEMS: {
434 // FIXME this could be optimised to iterate over cellsMap only
435 // (selectedCells could be big, cellsMap is much smaller)
436 List<Node> selection = new ArrayList<>();
437 int index = getSkinnable().getIndex();
438 for (TreeTablePosition<T,?> pos : treeTableView.getSelectionModel().getSelectedCells()) {
439 if (pos.getRow() == index) {
440 TreeTableColumn<T,?> column = pos.getTableColumn();
441 if (column == null) {
442 /* This is the row-based case */
443 column = treeTableView.getVisibleLeafColumn(0);
444 }
445 TreeTableCell<T,?> cell = cellsMap.get(column).get();
446 if (cell != null) selection.add(cell);
447 }
448 return FXCollections.observableArrayList(selection);
449 }
450 }
|