public HierarchyTreeCell()

in kit/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/treeview/HierarchyTreeCell.java [161:456]


    public HierarchyTreeCell(final AbstractHierarchyPanelController c) {
        super();
        this.panelController = c;

        iconsStack.getChildren().setAll(
                classNameImageView,
                warningBadgeImageView);
        iconsLabel.setGraphic(iconsStack);
        // RT-31645 : we cannot dynamically update the HBox graphic children 
        // in the cell.updateItem method.
        // We set once the graphic children, then we update the managed property
        // of the children depending on the cell item. 
        graphic.getChildren().setAll(
                includedFileImageView,
                placeHolderImageView,
                iconsLabel,
                placeHolderLabel,
                classNameInfoLabel,
                displayInfoLabel);

        // Add style class used when invoking lookupAll
        this.getStyleClass().add(HIERARCHY_TREE_CELL);

        // Update vertical insert line indicator stroke width
        insertLineIndicator.setStrokeWidth(2.0);

        // CSS
        graphic.getStyleClass().add(TREE_CELL_GRAPHIC);
        updatePlaceHolder();
        displayInfoLabel.getStyleClass().add(HIERARCHY_READWRITE_LABEL);
        placeHolderLabel.getStyleClass().add(HIERARCHY_PLACE_HOLDER_LABEL);
        // Layout
        classNameInfoLabel.setMinWidth(Control.USE_PREF_SIZE);
        displayInfoLabel.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(displayInfoLabel, Priority.ALWAYS);

        panelController.displayOptionProperty().addListener(
                new WeakChangeListener<>(displayOptionListener));

        // Key events
        //----------------------------------------------------------------------
        final EventHandler<KeyEvent> keyEventHandler = e -> filterKeyEvent(e);
        this.addEventFilter(KeyEvent.ANY, keyEventHandler);

        // Mouse events
        //----------------------------------------------------------------------
        final EventHandler<MouseEvent> mouseEventHandler = e -> filterMouseEvent(e);
        this.addEventFilter(MouseEvent.ANY, mouseEventHandler);

        // Drag events
        //----------------------------------------------------------------------
        final HierarchyDNDController dndController = panelController.getDNDController();

        setOnDragDropped(event -> {
            final TreeItem<HierarchyItem> treeItem
                    = HierarchyTreeCell.this.getTreeItem();
            // Forward to the DND controller
            dndController.handleOnDragDropped(treeItem, event);

            // CSS
            panelController.clearBorderColor(HierarchyTreeCell.this);
            // Remove insert line indicator
            panelController.removeFromPanelControlSkin(insertLineIndicator);
        });
        setOnDragEntered(event -> {
            final TreeItem<HierarchyItem> treeItem
                    = HierarchyTreeCell.this.getTreeItem();
            // Forward to the DND controller
            dndController.handleOnDragEntered(treeItem, event);
        });
        setOnDragExited(event -> {
            final TreeItem<HierarchyItem> treeItem
                    = HierarchyTreeCell.this.getTreeItem();
            final Bounds bounds = HierarchyTreeCell.this.getLayoutBounds();
            final Point2D point = HierarchyTreeCell.this.localToScene(bounds.getMinX(), bounds.getMinY(), true /* rootScene */);
            final DroppingMouseLocation location;
            if (event.getSceneY() <= point.getY()) {
                location = DroppingMouseLocation.TOP;
            } else {
                location = DroppingMouseLocation.BOTTOM;
            }

            // Forward to the DND controller
            dndController.handleOnDragExited(treeItem, event, location);

            // CSS
            panelController.clearBorderColor(HierarchyTreeCell.this);
            // Remove insert line indicator
            panelController.removeFromPanelControlSkin(insertLineIndicator);
        });
        setOnDragOver(event -> {
            final TreeItem<HierarchyItem> treeItem
                    = HierarchyTreeCell.this.getTreeItem();
            final DragController dragController
                    = panelController.getEditorController().getDragController();
            final DroppingMouseLocation location = getDroppingMouseLocation(event);

            // Forward to the DND controller
            dndController.handleOnDragOver(treeItem, event, location); // (1)

            panelController.clearBorderColor();
            // Update vertical insert line indicator stroke color
            final Paint paint = panelController.getParentRingColor();
            insertLineIndicator.setStroke(paint);
            // Remove insert line indicator
            panelController.removeFromPanelControlSkin(insertLineIndicator);

            // If an animation timeline is running 
            // (auto-scroll when DND to the top or bottom of the Hierarchy),
            // we do not display insert indicators.
            if (panelController.isTimelineRunning()) {
                return;
            }

            // Drop target has been updated because of (1)
            if (dragController.isDropAccepted()) {

                final AbstractDropTarget dropTarget = dragController.getDropTarget();
                final FXOMObject dropTargetObject = dropTarget.getTargetObject();
                final TreeItem<?> rootTreeItem = getTreeView().getRoot();

                if (dropTarget instanceof RootDropTarget) {
                    // No visual feedback in case of dropping the root node
                    return;
                }

                //==========================================================
                // ACCESSORIES :
                //
                // No need to handle the insert line indicator.
                // Border is set either on the accessory place holder cell
                // or on the accessory owner cell.
                //==========================================================
                if (dropTarget instanceof AccessoryDropTarget) {

                    final AccessoryDropTarget accessoryDropTarget = (AccessoryDropTarget) dropTarget;
                    final TreeCell<?> cell;

                    // TreeItem is null when dropping below the datas
                    // => the drop target is the root
                    if (treeItem == null) {
                        cell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), rootTreeItem);
                    } else {
                        final HierarchyItem item = treeItem.getValue();
                        assert item != null;

                        if (item.isPlaceHolder()) {
                            cell = HierarchyTreeCell.this;
                        } else if (accessoryDropTarget.getAccessory() == Accessory.GRAPHIC) {
                            // Check if an empty graphic TreeItem has been added
                            final TreeItem<HierarchyItem> graphicTreeItem
                                    = dndController.getEmptyGraphicTreeItemFor(treeItem);
                            if (graphicTreeItem != null) {
                                cell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), graphicTreeItem);
                            } else {
                                final TreeItem<HierarchyItem> accessoryOwnerTreeItem1
                                        = panelController.lookupTreeItem(dropTargetObject);
                                cell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), accessoryOwnerTreeItem1);
                            }
                        } else {
                            final TreeItem<HierarchyItem> accessoryOwnerTreeItem2
                                    = panelController.lookupTreeItem(dropTargetObject);
                            cell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), accessoryOwnerTreeItem2);
                        }
                    }

                    panelController.setBorder(cell, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                }//
                //==========================================================
                // SUB COMPONENTS :
                //
                // Need to handle the insert line indicator.
                //==========================================================
                else {
                    assert dropTarget instanceof ContainerZDropTarget
                            || dropTarget instanceof GridPaneDropTarget;
                    TreeItem<?> startTreeItem;
                    TreeCell<?> startCell, stopCell;

                    // TreeItem is null when dropping below the datas
                    // => the drop target is the root
                    if (treeItem == null) {
                        if (rootTreeItem.isLeaf() || !rootTreeItem.isExpanded()) {
                            final TreeCell<?> rootCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), 0);
                            panelController.setBorder(rootCell, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                        } else {
                            final TreeItem<?> lastTreeItem = panelController.getLastVisibleTreeItem(rootTreeItem);
                            final TreeCell<?> lastCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), lastTreeItem);
                            // As we are dropping below the datas, the last cell is visible
                            assert lastCell != null;
                            panelController.setBorder(lastCell, BorderSide.BOTTOM);

                            // Update vertical insert line
                            startTreeItem = rootTreeItem;
                            startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
                            stopCell = lastCell;
                            updateInsertLineIndicator(startCell, stopCell);
                            panelController.addToPanelControlSkin(insertLineIndicator);
                        }

                    } else {
                        final HierarchyItem item = treeItem.getValue();
                        assert item != null;

                        if (item.isPlaceHolder() || item.getFxomObject() == dropTargetObject) {
                            // The place holder item is filled with a container
                            // accepting sub components
                            panelController.setBorder(HierarchyTreeCell.this, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                        } else {
                            // REORDERING :
                            // To avoid visual movement of the horizontal border when
                            // dragging from one cell to another,
                            // we always set the border on the cell bottom location :
                            // - if we handle REORDER BELOW gesture, just set the bottom 
                            // border on the current cell
                            // - if we handle REORDER ABOVE gesture, we set the bottom 
                            // border on the previous cell
                            //
                            switch (location) {

                                // REORDER ABOVE gesture
                                case TOP:
                                    if (treeItem == rootTreeItem) {
                                        panelController.setBorder(HierarchyTreeCell.this, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                                    } else {
                                        final int index = getIndex();
                                        // Retrieve the previous cell
                                        // Note : we set the border on the bottom of the previous cell 
                                        // instead of using the top of the current cell in order to avoid
                                        // visual gap when DND from one cell to another
                                        final TreeCell<?> previousCell
                                                = HierarchyTreeViewUtils.getTreeCell(getTreeView(), index - 1);
                                        // The previous cell is null when the item is not visible
                                        if (previousCell != null) {
                                            panelController.setBorder(previousCell, BorderSide.BOTTOM);
                                        }

                                        // Update vertical insert line
                                        startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
                                        stopCell = previousCell;
                                        updateInsertLineIndicator(startCell, stopCell);
                                        panelController.addToPanelControlSkin(insertLineIndicator);
                                    }
                                    break;

                                // REPARENT gesture
                                case CENTER:
                                    if (treeItem.isLeaf() || !treeItem.isExpanded()) {
                                        panelController.setBorder(HierarchyTreeCell.this, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                                    } else {
                                        // Reparent to the treeItem as last child
                                        final TreeItem<?> lastTreeItem = panelController.getLastVisibleTreeItem(treeItem);
                                        final TreeCell<?> lastCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), lastTreeItem);
                                        // Last cell is null when the item is not visible
                                        if (lastCell != null) {
                                            panelController.setBorder(lastCell, BorderSide.BOTTOM);
                                        }

                                        // Update vertical insert line
                                        startTreeItem = getTreeItem();
                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
                                        stopCell = lastCell;
                                        updateInsertLineIndicator(startCell, stopCell);
                                        panelController.addToPanelControlSkin(insertLineIndicator);
                                    }
                                    break;

                                // REORDER BELOW gesture
                                case BOTTOM:
                                    if (treeItem == rootTreeItem
                                            && (treeItem.isLeaf() || !treeItem.isExpanded())) {
                                        panelController.setBorder(HierarchyTreeCell.this, BorderSide.TOP_RIGHT_BOTTOM_LEFT);
                                    } else {
                                        // Reparent to the treeItem as first child
                                        panelController.setBorder(HierarchyTreeCell.this, BorderSide.BOTTOM);

                                        // Update vertical insert line
                                        startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
                                        stopCell = HierarchyTreeCell.this;
                                        updateInsertLineIndicator(startCell, stopCell);
                                        panelController.addToPanelControlSkin(insertLineIndicator);
                                    }
                                    break;

                                default:
                                    assert false;
                                    break;
                            }
                        }
                    }
                }
            }
        });
    }