Class SJMenuBar

java.lang.Object
com.vaadin.flow.component.Component
com.vaadin.flow.component.menubar.MenuBar
com.vaadin.swingbridge.surrogates.SJMenuBar
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.contextmenu.HasMenuItems, com.vaadin.flow.component.DetachNotifier, 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.component.shared.HasThemeVariant<com.vaadin.flow.component.menubar.MenuBarVariant>, ComponentMixin, ContainerMixin, JComponentMixin, Serializable

public class SJMenuBar extends com.vaadin.flow.component.menubar.MenuBar implements JComponentMixin
Surrogate for JMenuBar (SD_sjmenubar). Extends Vaadin MenuBar directly and reproduces the Swing menubar surface via a tree-rebuild API that the emulator-side :emulators.swing.JMenuBar pushes through on every JDK menu-tree mutation.

Why MenuBar, asymmetric split

Vaadin MenuItem's ctor is effectively package-private (it requires a Vaadin-internal ContextMenu owner + content-reset callback), so a surrogate cannot extend it as SJMenuItem extends MenuItem and substitute it where Vaadin's own addItem would return one. The smallest surrogate-layer unit that's a true Vaadin Component is therefore the whole bar, not the individual items. R_vaadin_first then says don't ship a parallel SJMenu / SJMenuItem surface that exists only to mirror JDK shape — pure-surrogate users compose with MenuBar.addItem(String, com.vaadin.flow.component.ComponentEventListener) directly.

Tree-rebuild API

The emulator walks its JDK tree and pushes a List<MenuNode> snapshot via rebuildFromTree(List). The actual Vaadin-side walk lives in the shared MenuTreeBuilder (SD_sjpopupmenu — same engine SJPopupMenu uses, keyed on Vaadin's HasMenuItems). Click handlers funnel through SHelper.callSwing(Runnable) (R_callswing_envelope).

Top-level separators + mnemonics: drop-and-WARN R_vaadin_first

Vaadin MenuBar doesn't expose top-level addSeparator() (separators only land inside a SubMenu); the rebuild's top-level separator callback logs via SHelper.onUnimplemented(Object, String, Object...) and skips. (SJPopupMenu's ContextMenu peer does support top-level separators — that's the one asymmetry the shared builder's per-caller callback covers.) Top-level mnemonics have no Vaadin counterpart either. Both are R_match_swing_errors sub-bucket (a).

Accelerators

Per-item KeyStroke accelerators install as UI-scoped Shortcuts bindings via MenuTreeBuilder.installAccelerators(UI, Component, Map, Map). Each rebuild tears the old registrations down before installing fresh ones, keyed by JDK KeyStroke in MenuBarStateStore.acceleratorRegistrations.
See Also:
  • Constructor Details

    • SJMenuBar

      public SJMenuBar()
  • Method Details

    • rebuildFromTree

      public void rebuildFromTree(List<MenuNode> tree)
      Push a fresh JDK menu-tree snapshot through to the Vaadin MenuBar. A snapshot that changes only checked states, handlers or accelerators updates the existing items (MenuTreeBuilder.patchInPlace(List, List, List)); anything else tears the tree down and rebuilds it. Accelerators are reinstalled either way.

      The preventRebuild re-entrancy guard short-circuits recursive calls — a click handler that runs as part of this rebuild (toggle-item commit, etc.) firing back into the emulator can't cascade into another nested rebuild.

      null or empty tree fully clears the menubar.

    • onAttach

      protected void onAttach(com.vaadin.flow.component.AttachEvent attachEvent)
      Re-install accelerators on attach. The first rebuildFromTree call may run before the menubar is attached (e.g. building the bar in a JFrame ctor before setVisible(true)); the install pass skips silently in that case. This hook re-walks the current tree once the UI exists.
      Overrides:
      onAttach in class com.vaadin.flow.component.Component
    • getCurrentTree

      public List<MenuNode> getCurrentTree()
      Convenience accessor for tests + diagnostics — returns the most recently pushed MenuNode snapshot. Live mutation of the returned list does not affect the rendered tree (snapshot is stored as an immutable copy).
    • getUIClassID

      public String getUIClassID()
      JDK matches "MenuBarUI".
      Specified by:
      getUIClassID in interface JComponentMixin