Class SJTree

java.lang.Object
com.vaadin.flow.component.Component
com.vaadin.flow.component.grid.Grid<Object>
com.vaadin.flow.component.treegrid.TreeGrid<Object>
com.vaadin.swingbridge.surrogates.SJTree
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.BlurNotifier<com.vaadin.flow.component.grid.Grid<Object>>, com.vaadin.flow.component.DetachNotifier, com.vaadin.flow.component.Focusable<com.vaadin.flow.component.grid.Grid<Object>>, com.vaadin.flow.component.FocusNotifier<com.vaadin.flow.component.grid.Grid<Object>>, com.vaadin.flow.component.HasElement, com.vaadin.flow.component.HasEnabled, com.vaadin.flow.component.HasSize, com.vaadin.flow.component.HasStyle, com.vaadin.flow.component.HasTheme, com.vaadin.flow.data.event.SortEvent.SortNotifier<com.vaadin.flow.component.grid.Grid<Object>, com.vaadin.flow.component.grid.GridSortOrder<Object>>, com.vaadin.flow.data.provider.HasDataGenerators<Object>, com.vaadin.flow.data.provider.HasDataView<Object, Void, com.vaadin.flow.component.grid.dataview.GridDataView<Object>>, com.vaadin.flow.data.provider.HasLazyDataView<Object, Void, com.vaadin.flow.component.grid.dataview.GridLazyDataView<Object>>, com.vaadin.flow.data.provider.HasListDataView<Object, com.vaadin.flow.component.grid.dataview.GridListDataView<Object>>, com.vaadin.flow.data.provider.hierarchy.HasHierarchicalDataProvider<Object>, ComponentMixin, ContainerMixin, JComponentMixin, Serializable, EventListener, TreeModelListener, TreeSelectionListener

public class SJTree extends com.vaadin.flow.component.treegrid.TreeGrid<Object> implements JComponentMixin, TreeModelListener, TreeSelectionListener
Surrogate for JTree (SD_sjtree). Extends Vaadin TreeGrid<Object> — the JDK TreeModel's node objects are the Vaadin items, the installed model is the single source of truth (R_swing_is_truth), and a custom lazy AbstractBackEndHierarchicalDataProvider reads getRoot/getChild/getChildCount/isLeaf live (children fetched only when a node expands). The third Grid-family surrogate after SJTable (SD_sjtable) and SJList (SD_sjlist).

Node-Object identity (SD_sjtree_node_identity)

Items are keyed on the model's node objects directly — JDK's TreeModel contract is node-as-Object, and the SJTable/SJList Integer-index dodge can't transfer (a hierarchical provider must navigate parent⇄child; a flat index is unstable under expand/collapse). DefaultMutableTreeNode doesn't override equals, so the dominant case is identity-keyed. Accepted R_best_effort_behaviour limitation: a custom model returning value-equals nodes (the same String at two positions) collides in Vaadin's key-mapper; documented, not defended.

Parent map (SD_sjtree_lazy_provider)

Every fetchChildrenFromBackEnd records child→parent in an identity map. Not an R_vaadin_first shadow cache: the data provider's getParent/getItemIndex overrides (required by TreeGrid.scrollToItem(T) for a non-in-memory provider) and the selection bridge's node→TreePath reconstruction both need to walk up, and the JDK TreeModel has no getParent.

Selection bridge (SD_sjtree_selection_bridge)

JDK TreeSelectionModel is path-set–based, Grid selection is item-set–based. SJTree IS-A TreeSelectionListener on the installed model (JDK→peer push); a Vaadin selection listener reconstructs TreePaths via the parent map and writes through setSelectionPaths (peer→JDK), both guarded by preventPeerEvents. getSelectionModel() clashes with the inherited Grid.getSelectionModel(): GridSelectionModel — exactly SJTable's clash — so the JDK-shaped accessor here is getTreeSelectionModel(); the emulator keeps the JDK name. Mode changes are observed via the model's "selectionMode" PCE (JDK code calls tree.getSelectionModel().setSelectionMode(...) — there is no JTree.setSelectionMode).

Hierarchy-column render seam (SD_sjtree_hierarchy_render)

One addComponentHierarchyColumn installs at ctor time; its closure reads TreeStateStore.componentProvider live. TreeGrid's expand/collapse toggle chrome lives in HierarchyColumnComponentRenderer's template, so the renderer is never re-installed — the emulator's D_jtree_renderer_registry JDK-TreeCellRenderer bridge swaps the function via setHierarchyComponentProvider(Function). Pure-surrogate users get a fresh-per-call Span of the node's text (D_jcombobox DOM-adoption guard).

R_vaadin_first drop-and-WARN surface

addTreeWillExpandListener (no Vaadin pre-expansion vetoable hook — D_gap_severity_triage sub-bucket (a)); in-cell editing (sub-bucket (b), the JTable cell-editor precedent). Round-trip-only knobs (showsRootHandles, rowHeight, toggleClickCount, …) live emulator-side per the asymmetric R_swing_is_truth-shadow split (SD_sjtoolbar/SD_sjsplitpane/SD_sjlist) and aren't present here at all.
See Also:
  • Constructor Details

    • SJTree

      public SJTree()
      Pure-surrogate convenience: a single empty root, hidden.
    • SJTree

      public SJTree(TreeModel model)
  • Method Details

    • createDefaultSelectionModel

      protected TreeSelectionModel createDefaultSelectionModel()
    • getModel

      public TreeModel getModel()
    • setModel

      public void setModel(TreeModel model)
    • isRootVisible

      public boolean isRootVisible()
    • setRootVisible

      public void setRootVisible(boolean rootVisible)
      false hides the model root: its children become Vaadin top-level items. The only rootVisible behaviour reproduced (R_best_effort_behaviour) — the root-handle-on-top-level nuance is setShowsRootHandles, an emulator-side visual shadow per D_jtree_field_shadows.
    • setHierarchyComponentProvider

      public void setHierarchyComponentProvider(Function<Object, com.vaadin.flow.component.Component> provider)
      Swap the hierarchy-column's per-node component factory. The installed column closure reads the function live, so no Vaadin renderer re-installs — TreeGrid's expand/collapse toggle chrome survives. The emulator's JDK-TreeCellRenderer bridge (D_jtree_renderer_registry) is the canonical caller; stage-3 users may install their own factory directly.
    • convertValueToText

      public String convertValueToText(Object node)
      Node-to-text conversion for the default render path. The JDK's overridable JTree.convertValueToText hook lives on the emulator (D_jtree_renderer_registry) — this surrogate-side conversion only feeds the pure-surrogate default cell.
    • getPathForNode

      public TreePath getPathForNode(Object node)
      Reconstruct the full JDK TreePath (always rooted at the model root, even when rootVisible is false) for a node. Parent-map walk with a live-model DFS fallback; null when the node isn't reachable from the current model.
    • treeNodesChanged

      public void treeNodesChanged(TreeModelEvent e)
      Specified by:
      treeNodesChanged in interface TreeModelListener
    • treeNodesInserted

      public void treeNodesInserted(TreeModelEvent e)
      Specified by:
      treeNodesInserted in interface TreeModelListener
    • treeNodesRemoved

      public void treeNodesRemoved(TreeModelEvent e)
      Specified by:
      treeNodesRemoved in interface TreeModelListener
    • treeStructureChanged

      public void treeStructureChanged(TreeModelEvent e)
      Specified by:
      treeStructureChanged in interface TreeModelListener
    • getTreeSelectionModel

      public TreeSelectionModel getTreeSelectionModel()
      JDK getSelectionModel(): TreeSelectionModel can't coexist with Vaadin Grid's inherited getSelectionModel(): GridSelectionModel<T> (unrelated return types). Per R_vaadin_first the Vaadin shape wins at the surrogate; the emulator (:emulators.JTree) keeps the JDK-shaped getter and reaches the model through this differently-named accessor. Same resolution SJTable / SJList use.
    • setSelectionModel

      public void setSelectionModel(TreeSelectionModel selectionModel)
      Install a different selection model. null installs a fresh DefaultTreeSelectionModel (R_best_effort_behaviour close-enough for the JDK's EmptySelectionModel substitution).
    • valueChanged

      public void valueChanged(TreeSelectionEvent e)
      JDK→peer push: the installed TreeSelectionModel changed.
      Specified by:
      valueChanged in interface TreeSelectionListener
    • setSelectionPath

      public void setSelectionPath(TreePath path)
    • setSelectionPaths

      public void setSelectionPaths(TreePath[] paths)
    • addSelectionPath

      public void addSelectionPath(TreePath path)
    • removeSelectionPath

      public void removeSelectionPath(TreePath path)
    • getSelectionPath

      public TreePath getSelectionPath()
    • getSelectionPaths

      public TreePath[] getSelectionPaths()
    • getSelectionCount

      public int getSelectionCount()
    • isPathSelected

      public boolean isPathSelected(TreePath path)
    • isSelectionEmpty

      public boolean isSelectionEmpty()
    • clearSelection

      public void clearSelection()
    • getLastSelectedPathComponent

      public Object getLastSelectedPathComponent()
    • expandPath

      public void expandPath(TreePath path)
      Ensures the node at path is expanded and its ancestors are too (JDK shape).
    • collapsePath

      public void collapsePath(TreePath path)
      Collapses the node at path (ancestors stay as-is, JDK shape).
    • isExpanded

      public boolean isExpanded(TreePath path)
      JDK contract: true only when the node is expanded and every ancestor is expanded (i.e. the expansion is actually displayed).
    • isCollapsed

      public boolean isCollapsed(TreePath path)
    • makeVisible

      public void makeVisible(TreePath path)
      Expands the path's ancestors so the node itself is displayable.
    • isVisible

      public boolean isVisible(TreePath path)
      True when every ancestor of path is expanded.
    • scrollPathToVisible

      public void scrollPathToVisible(TreePath path)
      Expand ancestors (via the public expand(), firing the JDK TreeExpansionEvent fan-out) then TreeGrid.scrollToItem(T) — D_jtree_row_path_bridge: scrollToItem's own built-in ancestor expansion fires no ExpandEvent and would silently skip listeners. No pixel scroll guarantee (R_layouts_close_enough).
    • getExpandedDescendants

      public List<TreePath> getExpandedDescendants(TreePath parent)
      Expanded descendants of parent (including parent itself, JDK shape); null when parent isn't expanded. Reflects TreeGrid's lazy expansion state: descendants of never-expanded nodes report collapsed (R_best_effort_behaviour).
    • addTreeExpansionListener

      public void addTreeExpansionListener(TreeExpansionListener l)
      Per-registration TreeExpansion wire: one Vaadin expand + one collapse subscription per Swing listener, combined into one Registration (R_vaadin_first's per-registration shape). Fires for both client and programmatic expands — matching JDK's expandPath firing semantics.
    • removeTreeExpansionListener

      public void removeTreeExpansionListener(TreeExpansionListener l)
    • getTreeExpansionListeners

      public TreeExpansionListener[] getTreeExpansionListeners()
    • addTreeWillExpandListener

      public void addTreeWillExpandListener(TreeWillExpandListener l)
      R_vaadin_first drop-and-WARN — D_gap_severity_triage sub-bucket (a) blocked-upstream: Vaadin has no pre-expansion vetoable hook, so the listener would never fire. The emulator owns expansion and fires it (D_jtree_row_path_bridge); here it drops.
    • removeTreeWillExpandListener

      public void removeTreeWillExpandListener(TreeWillExpandListener l)
    • getRowCount

      public int getRowCount()
    • getPathForRow

      public TreePath getPathForRow(int row)
    • getRowForPath

      public int getRowForPath(TreePath path)
      -1 when an ancestor is collapsed (the node isn't visible).
    • getRowForNode

      public int getRowForNode(Object node)
      Visible-row index of a node by identity; -1 when not visible.
    • getRowForLocation

      public int getRowForLocation(int x, int y)
      Returns the visible-row index currently being click-dispatched (stashed by addMouseListener(SMouseListener)'s item-click wire), or -1 outside a dispatch. There is no server-side pixel→row map (R_layouts_close_enough) — called from a user mousePressed/mouseClicked handler (the CaseTreeView.selectOnRightClick idiom) it returns the clicked row.
    • getPathForLocation

      public TreePath getPathForLocation(int x, int y)
    • getClosestPathForLocation

      public TreePath getClosestPathForLocation(int x, int y)
      Same stash answer — we have no "closest" notion without pixels (R_layouts_close_enough).
    • getClosestRowForLocation

      public int getClosestRowForLocation(int x, int y)
    • addMouseListener

      public void addMouseListener(SMouseListener l)
      Overrides the inherited ComponentMixin wire — TreeGrid dispatches item clicks (carrying the node), not generic component clicks. Each item-click dispatches the MOUSE_PRESSED → MOUSE_RELEASED → MOUSE_CLICKED sequence (best-effort R_best_effort_behaviour: the browser reports a click, not the raw press/release stream), carrying the browser button so right-click → SMouseEvent.isPopupTrigger(). popupTrigger is set on both press and release for a right-click — we can't know the host platform's convention, and firing on both serves listeners written for either (the CaseTreeView.selectOnRightClick idiom listens on both; the duplicate select is idempotent). The clicked node + its visible row are stashed around the fan-out for getRowForLocation(int, int)/getPathForLocation(int, int).
      Specified by:
      addMouseListener in interface ComponentMixin
    • getUIClassID

      public String getUIClassID()
      Description copied from interface: JComponentMixin
      Deliberate no-op — L&F key.
      Specified by:
      getUIClassID in interface JComponentMixin