private int count(TreeItem<?> node) { if (node == null) { return 0; } int count = 1; if (node.getValue() == null || (node.getValue() != null && node.getValue() .getClass() .equals(RecursiveTreeObject.class))) { count = 0; } for (TreeItem<?> child : node.getChildren()) { count += count(child); } return count; } }
private ChangeListener<String> setupSearchField(final JFXTreeTableView<TreeTableViewController.Person> tableView) { return (o, oldVal, newVal) -> tableView.setPredicate(personProp -> { final Person person = personProp.getValue(); return person.firstName.get().contains(newVal) || person.lastName.get().contains(newVal) || Integer.toString(person.age.get()).contains(newVal); }); }
@Override public int getTreeItemLevel(TreeItem<?> node) { final TreeItem<?> root = getRoot(); if (node == null) { return -1; } if (node == root) { return 0; } int level = 0; TreeItem<?> parent = node.getParent(); while (parent != null) { level++; if (parent == root) { break; } // handle group nodes if (parent.getValue() != null && parent.getValue() instanceof RecursiveTreeObject && ((RecursiveTreeObject<?>) parent.getValue()).getGroupedColumn() != null) { level--; } parent = parent.getParent(); } return level; }
private <T> void setupCellValueFactory(JFXTreeTableColumn<Person, T> column, Function<Person, ObservableValue<T>> mapper) { column.setCellValueFactory((TreeTableColumn.CellDataFeatures<Person, T> param) -> { if (column.validateValue(param)) { return mapper.apply(param.getValue().getValue()); } else { return column.getComputedValue(param); } }); }
.filter(item -> item.getValue() == currentNode) .findAny() .map(ASTTreeItem.class::cast)
/** * validates the value of the tree item, * this method also hides the column value for the grouped nodes * * @param param tree item * @return true if the value is valid else false */ public final boolean validateValue(CellDataFeatures<S, T> param) { Object rowObject = param.getValue().getValue(); return !((rowObject instanceof RecursiveTreeObject && rowObject.getClass() == RecursiveTreeObject.class) || (param.getTreeTableView() instanceof JFXTreeTableView && ((JFXTreeTableView<?>) param.getTreeTableView()).getGroupOrder().contains(this) // make sure the node is a direct child to a group node && param.getValue().getParent() != null && param.getValue().getParent().getValue() != null && param.getValue().getParent().getValue().getClass() == RecursiveTreeObject.class )); }
/** * @param param tree item * @return the data represented by the tree item */ public final ObservableValue<T> getComputedValue(CellDataFeatures<S, T> param) { Object rowObject = param.getValue().getValue(); if (rowObject instanceof RecursiveTreeObject) { RecursiveTreeObject<?> item = (RecursiveTreeObject<?>) rowObject; if (item.getGroupedColumn() == this) { return new ReadOnlyObjectWrapper(item.getGroupedValue()); } } return null; }
/** * only allows editing for items that are not grouped * * @return whether the item is grouped or not */ private boolean checkGroupedColumn() { boolean allowEdit = true; if (getTreeTableRow().getTreeItem() != null) { Object rowObject = getTreeTableRow().getTreeItem().getValue(); if (rowObject instanceof RecursiveTreeObject && rowObject.getClass() == RecursiveTreeObject.class) { allowEdit = false; } else { // check grouped columns in the tableview if (getTableColumn() instanceof JFXTreeTableColumn && ((JFXTreeTableColumn) getTableColumn()).isGrouped()) { // make sure that the object is a direct child to a group node if (getTreeTableRow().getTreeItem().getParent() != null && getTreeTableRow().getTreeItem().getParent().getValue().getClass() == RecursiveTreeObject.class) { allowEdit = false; } } } } return allowEdit; }
private void displayScopes(Node node, boolean focusScopeView) { // current selection TreeItem<Object> previousSelection = scopeHierarchyTreeView.getSelectionModel().getSelectedItem(); ScopeHierarchyTreeItem rootScope = ScopeHierarchyTreeItem.buildAscendantHierarchy(node); scopeHierarchyTreeView.setRoot(rootScope); if (focusScopeView && previousSelection != null) { // Try to find the node that was previously selected and focus it in the new ascendant hierarchy. // Otherwise, when you select a node in the scope tree, since focus of the app is shifted to that // node, the scope hierarchy is reset and you lose the selection - even though obviously the node // you selected is in its own scope hierarchy so it looks buggy. int maxDepth = DesignerIteratorUtil.count(DesignerIteratorUtil.parentIterator(previousSelection, true)); rootScope.tryFindNode(previousSelection.getValue(), maxDepth) .ifPresent(scopeHierarchyTreeView.getSelectionModel()::select); } }
private JFXButton createLastButton(TreeItem temp, TreeItem parent) { return new JFXButton(temp.getValue().toString()) { private boolean noParent = parent == null; { setPadding(new Insets(getOffset(), getOffset(), getOffset(), (noParent? 1 : 2) * getOffset())); setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY))); } @Override protected void layoutChildren() { super.layoutChildren(); double width = getWidth(); Polygon polygon = new Polygon(); final double height = getHeight(); polygon.getPoints().addAll(new Double[] { 0.0, 0.0, width, 0.0, width, height, 0.0, height, noParent ? 0 : getOffset(), noParent ? 0 : height / 2}); setClip(polygon); } }; }
public JFXButton createFirstButton(TreeItem temp) { return new JFXButton(temp.getValue().toString()) { { setPadding(new Insets(getOffset(), 1.5 * getOffset(), getOffset(), getOffset())); setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY))); } @Override protected void layoutChildren() { super.layoutChildren(); double width = getWidth(); Polygon polygon = new Polygon(); final double height = getHeight(); polygon.getPoints().addAll(new Double[] { 0.0, 0.0, width - getOffset(), 0.0, width, height / 2, width - getOffset(), height, 0.0, height}); setClip(polygon); } }; }
private JFXButton createNextButton(TreeItem temp) { return new JFXButton(temp.getValue().toString()) { { setPadding(new Insets(getOffset(), 1.5 * getOffset(), getOffset(), 2 * getOffset())); setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY))); } @Override protected void layoutChildren() { super.layoutChildren(); double width = getWidth(); Polygon polygon = new Polygon(); final double height = getHeight(); polygon.getPoints().addAll(new Double[] { 0.0, 0.0, width - getOffset(), 0.0, width, height / 2, width - getOffset(), height, 0.0, height, getOffset(), height / 2}); setClip(polygon); } }; }
boolean found = false; for (TreeItem<String> depNode : rootNode.getChildren()) { if (depNode.getValue().contentEquals(employee.getDepartment())) { ((FilterableTreeItem)depNode).getInternalChildren().add(empLeaf); found = true;
@Override protected void updateItem(Node item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); return; } else { setText(item.toString() + (item.getImage() == null ? "" : " \"" + item.getImage() + "\"")); setContextMenu(buildContextMenu(item)); } // Reclicking the selected node in the ast will scroll back to the node in the editor this.addEventHandler(MouseEvent.MOUSE_CLICKED, t -> { if (t.getButton() == MouseButton.PRIMARY && getTreeView().getSelectionModel().getSelectedItem().getValue() == item) { controller.onNodeItemSelected(item); t.consume(); } }); }
private void updateDisclosureNode() { Node disclosureNode = ((JFXTreeTableCell<S, T>) getSkinnable()).getDisclosureNode(); if (disclosureNode != null) { TreeItem<S> item = getSkinnable().getTreeTableRow().getTreeItem(); final S value = item == null ? null : item.getValue(); boolean disclosureVisible = value != null && !item.isLeaf() && value instanceof RecursiveTreeObject && ((RecursiveTreeObject) value).getGroupedColumn() == getSkinnable().getTableColumn(); disclosureNode.setVisible(disclosureVisible); if (!disclosureVisible) { getChildren().remove(disclosureNode); } else if (disclosureNode.getParent() == null) { getChildren().add(disclosureNode); disclosureNode.toFront(); } else { disclosureNode.toBack(); } if (disclosureNode.getScene() != null) { disclosureNode.applyCss(); } } }
public FilterableTreeItem(T value) { super(value); this.sourceList = FXCollections.observableArrayList(); this.filteredList = new FilteredList<>(this.sourceList); this.filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> { return child -> { // Set the predicate of child items to force filtering if (child instanceof FilterableTreeItem) { FilterableTreeItem<T> filterableChild = (FilterableTreeItem<T>) child; filterableChild.setPredicate(this.predicate.get()); } // If there is no predicate, keep this tree item if (this.predicate.get() == null) return true; // If there are children, keep this tree item if (child.getChildren().size() > 0) return true; // Otherwise ask the TreeItemPredicate return this.predicate.get().test(this, child.getValue()); }; }, this.predicate)); setHiddenFieldChildren(this.filteredList); }
protected void init() { this.getStyleClass().add(DEFAULT_STYLE_CLASS); this.setRowFactory(param -> new JFXTreeTableRow<>()); this.getSelectionModel().selectedItemProperty().addListener((o, oldVal, newVal) -> { if (newVal != null && newVal.getValue() != null) { itemWasSelected = true; } }); this.predicate.addListener(observable -> filter(getPredicate())); this.sceneProperty().addListener(observable -> { if (getScene() == null) { threadPool.shutdownNow(); } else if (threadPool.isTerminated()) { threadPool = createThreadPool(); } }); this.rootProperty().addListener(observable -> { if (getRoot() != null) { setCurrentItemsCount(count(getRoot())); } if(!internalSetRoot) { originalRoot = getRoot(); reGroup(); } }); // compute the current items count setCurrentItemsCount(count(getRoot())); }
.getTreeItem(t.getTreeTablePosition() .getRow()) .getValue().firstName.set(t.getNewValue()); }); lastNameEditableColumn.setCellFactory((TreeTableColumn<Person, String> param) -> { .getTreeItem(t.getTreeTablePosition() .getRow()) .getValue().lastName.set(t.getNewValue()); }); ageEditableColumn.setCellFactory((TreeTableColumn<Person, Integer> param) -> { .getTreeItem(t.getTreeTablePosition() .getRow()) .getValue().age.set(t.getNewValue()); });
private void setupReadOnlyTableView() { setupCellValueFactory(firstNameColumn, Person::firstNameProperty); setupCellValueFactory(lastNameColumn, Person::lastNameProperty); setupCellValueFactory(ageColumn, p -> p.age.asObject()); ObservableList<Person> dummyData = generateDummyData(100); treeTableView.setRoot(new RecursiveTreeItem<>(dummyData, RecursiveTreeObject::getChildren)); treeTableView.setShowRoot(false); treeTableViewCount.textProperty() .bind(Bindings.createStringBinding(() -> PREFIX + treeTableView.getCurrentItemsCount() + POSTFIX, treeTableView.currentItemsCountProperty())); treeTableViewAdd.disableProperty() .bind(Bindings.notEqual(-1, treeTableView.getSelectionModel().selectedIndexProperty())); treeTableViewRemove.disableProperty() .bind(Bindings.equal(-1, treeTableView.getSelectionModel().selectedIndexProperty())); treeTableViewAdd.setOnMouseClicked((e) -> { dummyData.add(createNewRandomPerson()); final IntegerProperty currCountProp = treeTableView.currentItemsCountProperty(); currCountProp.set(currCountProp.get() + 1); }); treeTableViewRemove.setOnMouseClicked((e) -> { dummyData.remove(treeTableView.getSelectionModel().selectedItemProperty().get().getValue()); final IntegerProperty currCountProp = treeTableView.currentItemsCountProperty(); currCountProp.set(currCountProp.get() - 1); }); searchField.textProperty().addListener(setupSearchField(treeTableView)); }