Class SJTabbedPane

java.lang.Object
com.vaadin.flow.component.Component
com.vaadin.flow.component.tabs.TabSheet
com.vaadin.swingbridge.surrogates.SJTabbedPane
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, 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.HasPrefix, com.vaadin.flow.component.shared.HasSuffix, com.vaadin.flow.component.shared.HasThemeVariant<com.vaadin.flow.component.tabs.TabSheetVariant>, ComponentMixin, ContainerMixin, JComponentMixin, Serializable

@StyleSheet("emul/sjtabbedpane.css") public class SJTabbedPane extends com.vaadin.flow.component.tabs.TabSheet implements JComponentMixin
Surrogate for JTabbedPane (SD_sjtabbedpane). Tab strip + content swap on top of Vaadin TabSheet. Selection lives on the peer (R_vaadin_first source-of-truth); per-tab metadata (title/icon/tooltip/custom-header) lives in TabbedPaneStateStore and is rendered into each Vaadin Tab's children on every change.

Why children-based, never Tab.setLabel

tab.setLabel("X") wipes the Tab's children — so an icon added with tab.add(icon) disappears on the next title change. The children-based render strategy (tab.removeAll(); tab.add(icon); tab.add(new Span(title));) sidesteps the wipe and keeps a uniform state machine across (title only / title + icon / custom header) modes. HasAriaLabel.setAriaLabel(String) preserves accessibility regardless of visual mode.

API partition (per SD_sjtabbedpane)

Methods Vaadin can reproduce are real impls (add/insert/remove, selectedIndex, title/icon/tooltip/enabled at, tabComponentAt). The cluster Vaadin doesn't expose Java-side — setBackgroundAt, setForegroundAt, setDisabledIconAt, setMnemonicAt, setDisplayedMnemonicIndexAt, setModel — drop-and-WARN. Round-trip for those headline properties that warrant it lives on the emulator's vaadinx.swing.JTabbedPane; per-tab no-counterpart attributes stay drop-and-WARN both layers (R_vaadin_first + per-tab arrays would be storage for storage's sake without a Vaadin pulse behind them).

Tab placement / layout policy

  • setTabPlacement(TOP) — delivered (Vaadin TabSheet is top-only).
  • setTabPlacement(LEFT|RIGHT|BOTTOM) — WARN, field-shadow round-trip on emulator. R_match_swing_errors sub-bucket (a) blocked-upstream: Vaadin TabSheet exposes no orientation knob.
  • setTabLayoutPolicy(SCROLL_TAB_LAYOUT) — silently accepted (Vaadin auto-scrolls on overflow already; no WARN since user intent is already met).
  • setTabLayoutPolicy(WRAP_TAB_LAYOUT) — WARN, field-shadow round-trip. R_match_swing_errors sub-bucket (a): Vaadin has no wrap mode.

Garbage placement / policy ints throw IllegalArgumentException matching JDK (R_match_swing_errors).

Selection bridge

Two-way wire: peer SelectedChangeEvent → callSwing (R_callswing_envelope) → model.setSelectedIndex → internal modelListener fires ChangeListeners + pushes back to peer iff peer differs. preventPeerEvents guards the peer-push leg against re-entrancy. The model is JDK-side DefaultSingleSelectionModel; user code can getModel().addChangeListener(...) and observe the same fan-out as tabbedPane.addChangeListener(...).

removeTabAt selection-shift

Vaadin TabSheet's remove(int) reshuffles selection identically to JDK across every corner (remove middle: stays at index; remove last: shifts to i-1; remove below: decrements; remove above: unchanged; remove only-tab: -1). No bridge translation needed — just forward.

Loading-spinner suppression

vaadin-tabsheet shows an indeterminate spinner whenever the selected tab has no attached content; an empty tab strip (all tabs closed) is exactly that, so it would spin forever. Swing renders a blank content area instead, so emul/sjtabbedpane.css (StyleSheet below) hides the loader part. The loading state is web-component-owned (no server-side lever). The CSS ships as a plain servlet-served static resource (META-INF/ resources/emul/sjtabbedpane.css), not a frontend import, so it never forces a Vite dev-bundle rebuild.

See Also:
  • Field Details

  • Constructor Details

    • SJTabbedPane

      public SJTabbedPane()
    • SJTabbedPane

      public SJTabbedPane(int tabPlacement)
    • SJTabbedPane

      public SJTabbedPane(int tabPlacement, int tabLayoutPolicy)
  • Method Details

    • addChangeListener

      public void addChangeListener(ChangeListener l)
    • removeChangeListener

      public void removeChangeListener(ChangeListener l)
    • getChangeListeners

      public ChangeListener[] getChangeListeners()
    • getModel

      public SingleSelectionModel getModel()
    • setModel

      public void setModel(SingleSelectionModel model)
      Swap the selection model, as the JDK allows: unhooks the internal modelListener from the old model, hooks it to the new one, and syncs the peer to the new model's selection. The model is JDK-side machinery (a SingleSelectionModel), so this is pure rewiring — no Vaadin counterpart is involved, which is why it is implemented rather than drop-and-WARN (the R_vaadin_first model carve-out).
    • setSelectedIndex

      public void setSelectedIndex(int index)
      Overrides:
      setSelectedIndex in class com.vaadin.flow.component.tabs.TabSheet
    • getSelectedComponent

      public com.vaadin.flow.component.Component getSelectedComponent()
    • setSelectedComponent

      public void setSelectedComponent(com.vaadin.flow.component.Component c)
    • getTabPlacement

      public int getTabPlacement()
    • setTabPlacement

      public void setTabPlacement(int tabPlacement)
    • getTabLayoutPolicy

      public int getTabLayoutPolicy()
    • setTabLayoutPolicy

      public void setTabLayoutPolicy(int tabLayoutPolicy)
    • addTab

      public void addTab(String title, com.vaadin.flow.component.Component component)
    • addTab

      public void addTab(String title, Icon icon, com.vaadin.flow.component.Component component)
    • addTab

      public void addTab(String title, Icon icon, com.vaadin.flow.component.Component component, String tip)
    • insertTab

      public void insertTab(String title, Icon icon, com.vaadin.flow.component.Component component, String tip, int index)
    • removeTabAt

      public void removeTabAt(int index)
    • removeAll

      public void removeAll()
    • getTitleAt

      public String getTitleAt(int index)
    • setTitleAt

      public void setTitleAt(int index, String title)
    • getIconAt

      public Icon getIconAt(int index)
    • setIconAt

      public void setIconAt(int index, Icon icon)
    • getToolTipTextAt

      public String getToolTipTextAt(int index)
    • setToolTipTextAt

      public void setToolTipTextAt(int index, String tip)
    • isEnabledAt

      public boolean isEnabledAt(int index)
    • setEnabledAt

      public void setEnabledAt(int index, boolean enabled)
    • getTabComponentAt

      public com.vaadin.flow.component.Component getTabComponentAt(int index)
    • setTabComponentAt

      public void setTabComponentAt(int index, com.vaadin.flow.component.Component tabComponent)
    • indexOfTab

      public int indexOfTab(String title)
    • indexOfComponent

      public int indexOfComponent(com.vaadin.flow.component.Component component)
    • indexOfTabComponent

      public int indexOfTabComponent(com.vaadin.flow.component.Component tabComponent)
    • getComponentAt

      public com.vaadin.flow.component.Component getComponentAt(int index)
    • setComponentAt

      public void setComponentAt(int index, com.vaadin.flow.component.Component component)
    • setMnemonicAt

      public void setMnemonicAt(int index, int mnemonic)
      No Vaadin counterpart for per-tab keyboard accelerator on the tab header. R_vaadin_first drop-and-WARN; round-trip can lift to emulator field- shadow if a real migration target needs it.
    • getMnemonicAt

      public int getMnemonicAt(int index)
    • setDisplayedMnemonicIndexAt

      public void setDisplayedMnemonicIndexAt(int index, int mnemonicIndex)
    • getDisplayedMnemonicIndexAt

      public int getDisplayedMnemonicIndexAt(int index)
    • setBackgroundAt

      public void setBackgroundAt(int index, Color background)
      Per-tab background colour. No Vaadin per-tab background knob (theme-controlled); R_vaadin_first drop-and-WARN.
    • getBackgroundAt

      public Color getBackgroundAt(int index)
    • setForegroundAt

      public void setForegroundAt(int index, Color foreground)
    • getForegroundAt

      public Color getForegroundAt(int index)
    • setDisabledIconAt

      public void setDisabledIconAt(int index, Icon disabledIcon)
    • getDisabledIconAt

      public Icon getDisabledIconAt(int index)
    • getBoundsAt

      public Rectangle getBoundsAt(int index)
    • indexAtLocation

      public int indexAtLocation(int x, int y)
    • getTabRunCount

      public int getTabRunCount()
      JDK always returns ≥1; we always have a single row of tabs (no WRAP).
    • getUIClassID

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

      public void updateUI()
      Description copied from interface: JComponentMixin
      Deliberate no-op — L&F dispatch isn't modelled.
      Specified by:
      updateUI in interface JComponentMixin
    • setUI

      public void setUI(TabbedPaneUI ui)
    • getAccessibleContext

      public AccessibleContext getAccessibleContext()