Class SJFrame

java.lang.Object
com.vaadin.flow.component.Component
com.vaadin.flow.component.dialog.Dialog
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.DetachNotifier, com.vaadin.flow.component.HasAriaRole, com.vaadin.flow.component.HasComponents, com.vaadin.flow.component.HasComponentsOfType<com.vaadin.flow.component.Component>, 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.dialog.DialogVariant>, ComponentMixin, ContainerMixin, JComponentMixin, Serializable

public class SJFrame extends SFrame
Surrogate for JFrame per SD_sjframe. Extends SFrame (the java.awt.Window + java.awt.Frame surface) and adds the JFrame-specific layer: defaultCloseOperation + WindowConstants surface, content-pane routing, JRootPane holder, and the "FrameUI" L&F class id.

Why inheritance, not composition

JDK shape is JFrame IS-A Frame IS-A Window. SJFrame refines SFrame with the JRootPane + close-op + content-pane surface so the surrogate hierarchy mirrors JDK exactly: customer code that ported extends Frame → extends SFrame doesn't pay for JFrame affordances it doesn't use; customer code that ported extends JFrame → extends SJFrame gets the full surface.

Default close operation

HIDE (default) / DISPOSE / DO_NOTHING map cleanly onto Dialog (setOpened(false) / removeFromParent / blocked closeOnEsc+closeOnOutsideClick). EXIT_ON_CLOSE is silently accepted at set-time but throws IllegalStateException at close-time per [D_gap_severity_triage](../emulators/decisions.md#D_gap_severity_triage)'s second throw case. The processWindowEvent(SWindowEvent) override layers the close-op switch on top of SWindow's standard listener dispatch.

Content-pane routing

JFrame's post-Java-5 contract: frame.add(child) routes into the content pane. We reproduce this by overriding the Dialog add/remove family to redirect into a lazy Div contentPane. The stateful machinery (lazy panes, the rootPaneCheckingEnabled recursion guard, menubar slot) lives single-copy on the package-private RootPaneScaffold shared with SJDialog / SJWindow.

Accessor naming — getRootPane()

JComponentMixin.getRootPane() returns SJRootPane on the surrogate layer (the inherited signature carries no type collision with javax.swing.JRootPane — SJRootPane is the surrogate-layer root-pane type, and the mixin's walk-and-return surface this directly). SJFrame overrides getRootPane() to return its own lazy-constructed pane rather than walking parents, matching JDK JFrame's "I am the root-pane host" semantics.

Lazy rootPane construction

AWT contract: JRootPane accessors are lazy — most JFrames never reach through getRootPane(), and eager construction would allocate three panes per frame for nothing. getRootPane() constructs on first read via createRootPane(); the factory is a subclass hook matching JDK JFrame's override point. Before first read, the root pane is null and setContentPane(Div) doesn't force-construct it — the setter just updates this class's own contentPane Div, and the lazy seed at first read picks up the current contentPane.

Content-pane mirror invariant

Migrated code that alternates frame.getContentPane() and frame.getRootPane().getContentPane() expects both to report the same Div across content-pane swaps. setContentPane(Div) mirrors the reference into any already-constructed rootPane. Mirror-on-write beats a listener subscription — content pane swaps are rare and cheap to bridge explicitly.
See Also:
  • Constructor Details

    • SJFrame

      public SJFrame()
      Untitled, no owner.
    • SJFrame

      public SJFrame(String title)
      Titled, no owner. Null title coerces to empty per SFrame.
    • SJFrame

      public SJFrame(SFrame owner)
      Untitled, with owner. Null owner makes this top-level.
    • SJFrame

      public SJFrame(String title, SFrame owner)
      Full ctor — forwards to SFrame(String, SFrame).
  • Method Details

    • getDefaultCloseOperation

      public int getDefaultCloseOperation()
      Current close operation; one of WindowConstants's four values.
    • setDefaultCloseOperation

      public void setDefaultCloseOperation(int operation)
      Validate + apply. All four WindowConstants values are accepted silently at set-time. The throw trigger for EXIT_ON_CLOSE fires at close-time (per [D_gap_severity_triage](../emulators/decisions.md#D_gap_severity_triage)'s second case): processWindowEvent(SWindowEvent) throws IllegalStateException when a peer-originated close-attempt lands while the op is EXIT_ON_CLOSE, so the migrator's "terminate" intent is surfaced rather than silently ignored. DO_NOTHING_ON_CLOSE disables the peer's ESC / outside-click dismissal so the close gesture never fires.

      Throws IllegalArgumentException on unknown values per Swing's contract (D_never_fail_on_gaps — incomplete-emulation rule doesn't scope over inputs Swing itself rejects).

    • processWindowEvent

      public void processWindowEvent(SWindowEvent e)
      JFrame-shape: let user listeners run first (they may call System.exit or otherwise short-circuit), then apply the default close operation. HIDE calls setVisible(false) — setVisible is idempotent, so on the native ESC / outside-click path (where SWindow.onPeerOpenedChanged(boolean) already flipped visible to false before routing here) it early-returns, while on the header close-X path (which fires WINDOW_CLOSING directly via SFrame.installHeaderCloseButton() without touching the peer's opened state) it performs the real hide; DISPOSE calls through to SWindow.dispose() for the detach + WINDOW_CLOSED; DO_NOTHING is a genuine no-op (the window must stay open even when the close-X — which is never disarmed — delivers the event).

      EXIT_ON_CLOSE throws IllegalStateException per [D_gap_severity_triage](../emulators/decisions.md#D_gap_severity_triage)'s second throw case. The exception propagates per R_callswing_envelope to Vaadin's ErrorHandler; the dialog stays visually closed because the peer already closed before we got the close event, but the throw surfaces the migrator's "terminate the JVM" intent rather than letting it silently noop. A later revision may swap this to close the Vaadin session instead.

      Overrides:
      processWindowEvent in class SWindow
    • getContentPane

      public com.vaadin.flow.component.html.Div getContentPane()
      Lazy-creates if never accessed. Never returns null.
    • setContentPane

      public void setContentPane(com.vaadin.flow.component.html.Div newPane)
      Swap the content pane. JDK contract: null throws IllegalComponentStateException; existing children are NOT migrated; the SD_sjframe mirror invariant (frame.getContentPane() == frame.getRootPane().getContentPane()) holds across swaps. All carried by RootPaneScaffold.
    • add

      public void add(Collection<com.vaadin.flow.component.Component> components)
      Route into content pane while the scaffold's checking flag is set.
    • addComponentAtIndex

      public void addComponentAtIndex(int index, com.vaadin.flow.component.Component component)
      Route into content pane while the scaffold's checking flag is set.
      Specified by:
      addComponentAtIndex in interface com.vaadin.flow.component.HasComponentsOfType<com.vaadin.flow.component.Component>
      Overrides:
      addComponentAtIndex in class com.vaadin.flow.component.dialog.Dialog
    • remove

      public void remove(com.vaadin.flow.component.Component... components)
      Route into content pane while the scaffold's checking flag is set.
    • remove

      public void remove(Collection<com.vaadin.flow.component.Component> components)
      Route into content pane while the scaffold's checking flag is set.
    • removeAll

      public void removeAll()
      Route into content pane while the scaffold's checking flag is set. Otherwise delegate to Dialog's removeAll (which iterates children manually to preserve the overlay's slot elements).
      Specified by:
      removeAll in interface com.vaadin.flow.component.HasComponentsOfType<com.vaadin.flow.component.Component>
      Overrides:
      removeAll in class com.vaadin.flow.component.dialog.Dialog
    • setJMenuBar

      public void setJMenuBar(SJMenuBar bar)
      Attach a menubar to this frame. Pass null to detach. Slot semantics (index 0, sibling of the content pane, detach-old- first) live on RootPaneScaffold.
    • getJMenuBar

      public SJMenuBar getJMenuBar()
      null until setJMenuBar(SJMenuBar) attaches one.
    • getRootPane

      public SJRootPane getRootPane()
      Lazy-constructs via createRootPane() on first read (the scaffold captures the hook and seeds the SD_sjframe mirror invariant). Covariant override of JComponentMixin.getRootPane() — SJFrame returns its own held pane rather than walking parents.
    • setRootPane

      public void setRootPane(SJRootPane root)
      Replaces the root pane, as the JDK's protected setRootPane does: the outgoing one leaves this window and root becomes its one child, holding the content pane from then on. Public so the emulator layer can hand down the peer of the root pane it built itself, which is how one root pane serves both layers.
      Parameters:
      root - null leaves the window without a root pane, as the JDK allows
    • createRootPane

      protected SJRootPane createRootPane()
      Subclass hook matching JDK JFrame's createRootPane. Called once on first getRootPane() read. Subclasses can override to supply a custom SJRootPane; the default returns a plain one.
    • getLayeredPane

      public com.vaadin.flow.component.Component getLayeredPane()
      Delegates to getRootPane().getLayeredPane().
    • setLayeredPane

      public void setLayeredPane(com.vaadin.flow.component.Component layered)
      Delegates to getRootPane().setLayeredPane(...).
    • getGlassPane

      public com.vaadin.flow.component.Component getGlassPane()
      Delegates to getRootPane().getGlassPane().
    • setGlassPane

      public void setGlassPane(com.vaadin.flow.component.Component glass)
      Delegates to getRootPane().setGlassPane(...).
    • getDefaultButton

      public com.vaadin.flow.component.button.Button getDefaultButton()
      Convenience accessor: getRootPane().getDefaultButton().
    • getUIClassID

      public String getUIClassID()
      Matches javax.swing.JFrame.getUIClassID().
    • paramString

      public String paramString()
      Extends SFrame.paramString() with the defaultCloseOperation report. Diagnostic only — not a contract users should rely on.
      Overrides:
      paramString in class SFrame