Repository navigation
A JavaFX UI for KeY - #3993
A JavaFX UI for KeY#3993wadoon wants to merge 337 commits into
Conversation
…tive theme (dark theme fix)
…e whose sequent carries origin labels
…layout slots F10-F12/Ctrl+F10) * weigl/ocfx-docking: key.ui.fx: docking: make the shutdown layout save robust - cache the arrangement on the FX thread and persist the cached snapshot if the scene graph is already dying; hook now catches Throwable and traces to stderr key.ui.fx: docking: fromSwingSpec defaults unspecified modifiers to UP (Swing KeyStroke parity) key.ui.fx: docking: remove duplicated java.util.List import key.ui.fx: docking: tab context menu, maximize, named layout slots with F10-F12/Ctrl+F10, docking self test # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/java/de/uka/ilkd/key/gui/fx/MainWindowF.java
…pletion registry, IssueDialogF/AutoDismissDialogF/LogViewF) * weigl/ocfx-seam: key.ui.fx: seam: load failures surface in the IssueDialogF (parity with the ProblemLoader branch of Swing taskFinishedInternal, WindowUserInterfaceControl.java:236-244) key.ui.fx: seam: remove duplicated shown field declaration key.ui.fx: seam: IssueDialogF.wasShown survives the modal dismissal (self test reports after OK) key.ui.fx: seam: View menu entry for LogViewF (Swing trigger is a status-line extension button; no FX extension SPI yet) key.ui.fx: seam: wire WindowUserInterfaceControlF into the load path, View menu log view, uicontrol self test (key.fx.verify.uicontrol) key.ui.fx: seam: port the Swing dialog trio (IssueDialog, AutoDismissDialog, LogView) + per-run logback file appender key.ui.fx: seam: WindowUserInterfaceControlF routes core callbacks into the FX window and hosts the rule-completion registry # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/java/de/uka/ilkd/key/gui/fx/MainWindowF.java # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-dark.css # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-light.css
…riants, ApplyTacletDialogF base) * weigl/ocfx-tacletmatch: key.ui.fx: tacletmatch: style the redesigned dialog scene with the active theme (dark theme fix) key.ui.fx: tacletmatch: run the classic-dialog assertion before the destructive apply step key.ui.fx: tacletmatch: self test asserts the classic table dialog (render, cancel) and shows it; hold-classic screenshot mode key.ui.fx: tacletmatch: self test prefers proposable skolem applications (deeper candidates via getTacletAppAtAndBelow) key.ui.fx: tacletmatch: classic table-based completion dialog and if-selection panel key.ui.fx: tacletmatch: key.fx.verify.tacletmatch self test hooked into the demo load key.ui.fx: tacletmatch: redesigned taclet match dialog with shared apply semantics and theme styles key.ui.fx: tacletmatch: port match/instantiation/assumes/result-preview panels with match highlighting key.ui.fx: tacletmatch: port shared helpers (text, printing, styling, palette, responsive split, assumes-input logic) # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/java/de/uka/ilkd/key/gui/fx/MainWindowF.java # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-dark.css # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-light.css
…on, predicate abstraction, self test) * weigl/ocfx-joinmerge: key.ui.fx: joinmerge: show the join dialog for the screenshot window key.ui.fx: joinmerge: synthetic merge app fallback with harness parity check key.ui.fx: joinmerge: fix verify chain and add merge scan diagnostics key.ui.fx: joinmerge: join dialog, self-test hook and theme styles key.ui.fx: joinmerge: merge rule completion, partner selection and predicate abstraction dialogs # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-dark.css # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-light.css
…VisualizerF, NodeInfo visualizer registry, TermLabelMenuF) * weigl/ocfx-lemmaorigin: key.ui.fx: lemmaorigin: the origin-visualizer self test prefers a node whose sequent carries origin labels key.ui.fx: lemmaorigin: improve the term-label self test: search the proof tree for a node whose sequent prints term labels (the root sequent of a freshly loaded problem has none) key.ui.fx: lemmaorigin: origin term label visualizer (OriginTermLabelVisualizerF) + node info visualizer registry (NodeInfoVisualizerF) key.ui.fx: lemmaorigin: port the term-labels View menu (TermLabelMenuF) + hide-package-prefix and origin-tracking toggles # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/java/de/uka/ilkd/key/gui/fx/MainWindowF.java # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-dark.css # key.ui.fx/src/main/resources/de/uka/ilkd/key/gui/fx/theme/key-light.css
…ialog, javac settings (JavaFX) Ports the remaining small-dialog packages to JavaFX in key.ui.fx: - profileloading/: LoadingOptionsDialogF (Swing KeYFileChooserLoadingOptions accessory) + WDLoadOptionPanelF (well-definedness profile). The JavaFX FileChooser has no accessory, so options are collected in a pre-load dialog; Cancel aborts like the Swing chooser. MainWindowF threads the LoadOptions through the load path (OpenFileAction.java:70-76 parity). - soundiness/: SoundinessAnalyzer (HTML report) + SoundinessDialogF (JavaFX WebView). ShowSoundinessAction lives in the View menu until the FX proof-list dockable exists. - plugins/javac/: JavacSettingsProviderF, registered in SettingsManagerF (Swing JavacExtension settings capability; FX extension SPI not ready). - build.gradle: add javafx.web module (WebView) and key.core.wd dependency (WDLoadOptionPanelF); new key.fx.verify.profileloading/.profileloadingdialog/ .soundiness/.javacsettings self-test flags.
…ons, soundiness report, javac settings) * weigl/ocfx-smalldialogs: key.ui.fx: smalldialogs: profile loading options, soundiness report dialog, javac settings (JavaFX) key.ui.fx: help: port HelpFacade/HelpInfo as HelpFacadeF with F1 context help and self test # Conflicts: # key.ui.fx/build.gradle # key.ui.fx/src/main/java/de/uka/ilkd/key/gui/fx/MainWindowF.java
…ral skeleton, partition helpers)
…ntTermContextMenuF)
…ral skeleton, partition helpers, comparator)
…shows the sequent menu)
… sequent context menu
…aclet-match dialogs (S4 seam)
…tched dialog step (S4)
…ter and register the exception-failure task by default (S4)
…uentMenuModelF, SequentTermContextMenuF, right-click hit test, seam-wired taclet-match dialogs) * weigl/ocfx-termmenu: key.ui.fx: termmenu: route load failures through the notification center and register the exception-failure task by default (S4) key.ui.fx: termmenu: extend tacletmatch self test with the seam-dispatched dialog step (S4) key.ui.fx: termmenu: wire completeAndApplyTacletMatch to the ported taclet-match dialogs (S4 seam) key.ui.fx: termmenu: key.fx.verify.termmenu headless self test of the sequent context menu key.ui.fx: termmenu: sequent view context-menu hit test (right-click shows the sequent menu) key.ui.fx: termmenu: headless unit test of SequentMenuModelF (structural skeleton, partition helpers, comparator) key.ui.fx: termmenu: JavaFX shell for the sequent context menu (SequentTermContextMenuF) key.ui.fx: termmenu: headless unit test of SequentMenuModelF (structural skeleton, partition helpers) key.ui.fx: termmenu: pure-Java model of the sequent context menu (SequentMenuModelF)
…, statistics/settings/known-types entries)
… tooltip toggles, ToolTip Options dialog
…rward selection history (SelectionHistoryF)
… to walk the View menu
…MT Solvers… entry (SMTSettingsProviderF), Options line in the parity self-test - Confirm Exit / Auto Save Proofs / Minimize Interaction / Right Click for Proof Macros / Ensure Source Consistency as CheckMenuItems initialized from and writing back to ProofIndependentSettings (ViewSettings / GeneralSettings), mirroring Swing ToggleConfirmExitAction, AutoSave, MinimizeInteraction, RightMouseClickToggleAction, EnsureSourceConsistencyToggleAction. Mediator/filter/macro wiring deferred: the FX KeYMediatorF has no setAutoSave, the goal-view taclet filter and the direct-macro right-click are not wired, the FX port has no source-consistency machinery (// menu: notes). - SMT Solvers… replaced notYetImplemented() by the real settings-dialog entry focused on the new SMTSettingsProviderF (registered as SettingsManagerF.SMT_SETTINGS like Swing SettingsManager.SMT_SETTINGS): per-solver check boxes from SolverTypes.getSolverTypes() (initial state containsSolver, persisted via setActiveSolver) plus the four 1:1 persisted toggles (show results, store SMT/taclet translation, enable-on-load); the un-ported Swing options stay KNOWN-DEFERRED // menu:. - verifyMenuParityReport() gains the OPTIONS_MENU_EXPECTED table and emits the third 'Menu parity verification (Options):' PASS/FAIL line.
…user-defined taclets + Prove submenu, About menu via HostServices, File/About in the parity self-test
…d resizes with the dialog
…nslation providers
|
Round 3 pushed (
On item 7 of the earlier list (right-click macros in the Sequent view): the FX port already follows Swing ( All locally verified through the real sweep runner: |
…tion dialog onApplyException now puts the exception message into the dialog's status line (warning glyph + full-text tooltip) and opens the modal issue dialog, like Swing TacletMatchDialog.ButtonListener (TacletMatchDialog.java:367-372), instead of only logging and toasting.
The bar and both label groups now use BASELINE_LEFT/BASELINE_RIGHT so labels and taller controls share one text line (reviewer request, Swing MainStatusLine look).
…tton Swing JavacExtension is StatusLine+Startup+Settings; only the settings provider had been ported. This adds the missing extension: a status-line button that runs the javac check on proof selection (diagnostics cached in the proof's user data) and opens the issue list on click. Because key.ui (Swing) is not a dependency of key.ui.fx, the facade and its diagnostic type are ported as JavaCompilerCheckFacadeF and PositionedIssueStringF, checked against key.ui/plugins/javac/JavaCompilerCheckFacade.java and gui/PositionedIssueString.java. Unlike the Swing original, the check completion is forwarded to the FX thread instead of blocking the UI thread with get() (Swing JavacExtension.java:126-176).
The version label becomes a read-only borderless text field so the version string (incl. the internal revision) can be selected and copied into bug reports.
… late The top area grows after the root's first layout pass (icon fonts and theme styles settle late and raise the toolbar row's preferred height) while the BorderPane keeps the center pane at the stale top height; the transparent center pane then covers the toolbar row — buttons stay visible but every mouse press picks the center pane instead of the buttons (keyboard activation is unaffected, matching the reviewer report "mouse clicks on the toolbar are ignored, keyboard events work"). Late size changes of the top/bottom areas are now forwarded to the root's layout, and one extra re-stack runs after the first pulses. Diagnosed with a synthetic-click pick log on the live app: the toolbar click picked the center StackPane at scene (23,45) while the top spanned 0..60.
A drawer with no expanded item used to leave the main-area split entirely, which also removed its toggle bar — the panels became unreachable. The drawers are now permanent split members: a drawer without expanded items collapses to its button bar (DrawerF. collapseToButtonBar binds the width to the live strip width, so the split pane clamps the divider at the strip) and expanding an item restores the saved divider position.
The drawer toggles showed rotated text only. The glyphs mirror the tab icons of the Swing panels: ProofTreeView PROOF_TREE (Sitemap), GoalList FLAG_CHECKERED, InfoView INFO_CIRCLE, StrategySelectionView COG, SlicingLeftPanel SLICE_ICON (AlignJustify); the proof list, the source view and the exploration panel get semantic list/code glyphs and the exploration compass. Extension left-panel tabs contribute their own tab graphic (SlicingExtensionF sets the Swing-parity glyph, which needs the ikonli dependency in keyext.slicing.fx).
Both tabs (By Target, By Proof) now place the selection list (contract targets / proofs) and the contract panel in a SplitPane with a draggable divider (0.4), replacing the fixed-width BorderPane side regions.
With icons the rotated buttons grew, so the strip pushed its last toggle into the ToolBar overflow button (hidden = unreachable). The button bar is now wrapped in a chrome-free ScrollPane (vertical strips scroll vertically, horizontal bars horizontally) and the buttons lose their default padding. The collapsed drawer is no longer bound to the laid-out strip width (feedback loop once the scrollbar reserves width): min/max clamp to the content-driven bar pref width plus a scrollbar allowance, re-clamped when the strip's laid-out width becomes known at the first layout pass (the rotated buttons' groups report zero bounds before).
|
Round 4 — reviewer items 15–23 processed (each its own commit, pushed as c81b675):
Details:
Verify sweep for the affected flags ( |
sideRight/sideBottom compared the BorderPane slot against the plain ToolBar; the bar is wrapped in the chrome-free scroller now.
The toolbar buttons are icon-only since c4516f2 (reviewer request: tooltips and accessible names kept, visible text dropped); the verify still asserted Button.getText and failed. It now checks the accessible names.
|
Follow-up on the CI run for c81b675: 95 checks green, 2 sweep jobs red — both were stale verify-harness expectations against newer UI structure, no product bugs:
Also re-verified locally after these fixes: |
…xtension) The settings dialog lacked the "Extension Settings" provider (Swing ExtensionManager, key.ui/extension/ExtensionManager.java:33-150, registered by SettingsManager.java:62 right after the SMT provider): a checkbox per discovered extension whose state persists as forbidden class names and takes effect on the next restart. - ExtensionSettingsF: the persisted disabled-class set, using the same "Extensions"/"disabled" section and key as the Swing ExtensionSettings, so the Swing app and the FX app share the persisted state. - ExtensionManagerF: the panel (Swing parity) — the "Settings will be applied on next restart" subtitle, the flask explanation, per extension a checkbox (editable iff optional, ExtensionManager.java:68), the flask marker for experimental ones (:74-76), the italic Provides line (:104-112) and the description; apply writes the unchecked class names (:139-148). Swing's per-extension help button is not ported (only @HelpInfo-annotated extension classes get one; no FX extension class carries the annotation). - KeYGuiExtensionFacadeF: discovery filters forbidden extensions like Swing loadExtensions (isNotForbidden: static block list + -P<fqn>=false, KeYGuiExtensionFacade.java:279-283+309-315); the contribution getters use contributingExtensions() (Swing getExtensionsStream filters isDisabled(), :290-294). The experimental-feature gating of Extension.isDisabled (Extension.java:57-63) is deliberately not applied — the FX port contributes every discovered extension unconditionally (pinned by the key.fx.verify.extensions self test), so the checkboxes reflect exactly what the FX app enforces. forbidClass is ported (:429-434). - IconFactoryF: EXPERIMENTAL_EXTENSION flask key (Swing IconFactory). Verified live: the panel lists all 12 extensions with the provides lines and descriptions, Exploration carries the flask, the mandatory status-line extensions have disabled checkboxes; unchecking + Apply persists the class name into [Extensions]/disabled, and after a restart the disabled extension contributes nothing (its menu is gone) while all others stay.
Round 5 — the extension settings in the settings dialog (
|
| Piece | Swing original | FX port |
|---|---|---|
| Persisted disabled-class set | ExtensionSettings (Extensions/disabled section) |
ExtensionSettingsF — same section and key, so Swing and FX share the persisted state |
| Checkbox panel | ExtensionManager (ExtensionManager.java:39-148) |
ExtensionManagerF — subtitle "Settings will be applied on next restart", flask explanation, checkbox (editable iff optional, :68), flask marker for experimental extensions (:74-76), italic Provides: line (:104-112), description |
| Enforcement at restart | loadExtensions filters isNotForbidden (KeYGuiExtensionFacade.java:279-283), capability streams filter isDisabled() (:290-294) |
KeYGuiExtensionFacadeF: discovery filter (isNotForbidden, incl. -P<fqn>=false + forbidClass), all contribution getters route through contributingExtensions() |
One deliberate divergence, documented in the code: Swing's Extension.isDisabled also gates experimental extensions on their feature flag (Extension.java:57-63) — the FX port contributes every discovered extension unconditionally (the key.fx.verify.extensions self test pins the 12 discovered providers), so the checkboxes reflect exactly what the FX app enforces. Swing's per-extension help button is not ported (only @HelpInfo-annotated classes get one; no FX extension class carries it).
Verified live: the dialog now shows Extensions between SMT and Taclet Options (Swing order); the panel lists all 12 extensions with provides lines and descriptions, Exploration carries the flask, and the mandatory status-line extensions have disabled checkboxes. Unchecking + Apply persists the class name into [Extensions]/disabled immediately; after a restart the disabled extension contributes nothing (its menu is gone) while all others stay. Local sweep extensions dialogs javacsettings: all PASS.
…width Round-5 reviewer report: the expanded strip showed a beveled blank column. Three causes, all fixed here: - modena styles the vertical ToolBar itself (gradient, outer border, padding 6/5); the strip ToolBar is now transparent with padding 0 - the strip scrollbar is a child of the ScrollPane skin, not of the ToolBar, so the old `.drawer-button-bar .scroll-bar` selectors matched nothing; the scroller carries the new drawer-strip style class and all scrollbar rules (track, arrows, thumb) live under it, slimmed to 6px - the wrapper's own preferred size derives from the bars' laid widths while they still report the modena size, and its computed minimum carries the modena allowance too — both win the layout and keep a dead column; the size is now set explicitly (pref and min) from the strip tool bar's preference plus the slim scrollbar whenever it is visible The toggles are flat (transparent, hover derived from the key border, the focus ring strictly inside the bounds), the selected slab #818181 with white text comes from the theme stylesheets instead of inline styles, matching TornadoFX DrawerStyles.buttonArea (DrawerStyles.kt).
File/View/Proof/Options/About carry the same VK_F/V/P/O/A mnemonics as the Swing main window (MainWindow.java:993,1035,1084,1165); the extension menus stay untouched. Menu lookups in the verify hooks compare the display text via the new menuDisplayText helper since the menu texts now carry the mnemonic marker.
JavaFX shows a black window for a short fraction of time at startup: the window becomes visible before the first rendered frame is composited (also JDK-8088179). The stage is shown visually transparent and faded in after the first rendered frame; opacity must be small but not zero because a stage with opacity 0 is never rendered/presented. The flash while resizing is the Glass/GTK exposed-area handling and cannot be fixed from the application side.
|
All round‑5 items addressed in three commits: 1. Blank column next to the drawer toggles — turned out to be three stacked causes, all fixed in
Measured after the fix (pixel probes on the running app): the west strip is exactly toggle column + 6 px scrollbar (content area starts right at the strip's edge, previously ~16 px of blank), the east collapsed strip stays 22 px, no arrows, thumb derived from the key border. 2. Toggle look — the toggles are now flat: transparent background/insets/radius, hover derived from 3. Menu mnemonics — the five built‑in menus carry the Swing main window's mnemonics ( 4. Black window flash — 5. "TestGen extension is missing" — I could not reproduce this in the current state: the extension is registered ( |
JavaFX UI for KeY — feature-complete port + reviewer polish
This PR completes the JavaFX migration of the KeY UI (
key.ui.fx+keyext.*.fx) and incorporates the reviewer-visual-test feedback. All 11 work packages are merged; the latest 20 commits fix the CI gate and address the reviewer's issue list, one commit per item.Work packages (WP-1 … WP-11)
SWING-RETIREMENT.md), CI verify sweep (key.ui.fx/ci/verify-sweep.sh+ 44-job push matrix in.github/workflows/ui-verify.yml)Reviewer round (Oct 12–13)
spotlessCheckover all modules green again (the keyext.*.fx ports had missed the format gate).SplitPanes with draggable dividers; multi-panel proportions resizable; divider positions persisted inlayout.propertiesand restored at startup.SplitMenuButtons (SwingDropdownSelectionButtonparity: automation dropdown = the four proof macros, SMT dropdown = the usable solver unions; separate Start/Stop buttons removed, like Swing).DefaultProfileResolverservices).MaxRuleAppSliderparity), section separators, gear menu opens at the button (was: top-left corner of the desktop).ProofTreeFilterFinterface +ViewSettingsFilterF; new filter = new class + oneaddFilter(...)line in the constructor (context menu + exclusivity derived from the list).src/test:ProofTreeVerifyF,DialogsVerifyF,JoinMergeVerifyF,TacletMatchVerifyFand the four extension harnesses no longer ship insrc/main; the app dispatches them reflectively and theruntask carries the test outputs — allkey.fx.verify.*flags unchanged.Quality gates
:key.ui.fx:spotlessApply :key.ui.fx:compileJava :key.ui.fx:test(+ full-repospotlessCheck).CodeQuality(spotless),Tests(module tests), and the UI verify sweep (44 per-flag jobs on push,ubuntu-latest, artifacts per flag).CI sweep greenness (second round,
6469fa9e01)The push sweep surfaced six red flags. Compared against the previous run, five were already red before this round (red since WP-11); only
drawerlayoutwas a regression of the Loaded-Proofs-first order. Fixed one commit each, each verified locally through the real sweep runner first:dialogs— the contract e2e read the property as an example path while the recipes pass=1as a request for the default demo (→examples/1not found);=1/blank now selects the default demo, real paths still override.joinmerge-gcd— the recipe passesmaxsteps=empty, which crashedInteger.parseIntin the harness field initializer; blank/malformed values fall back to the default.proofmgmt-all— a proof load activates the proof before the Loaded Proofs view registers it, so the selection sync found no row and never retried ("highlighted row is not the selected proof");TaskTreeF.addProofre-syncs when the selected proof's row appears.drawerlayout— the reorder assertion used item 0 ("Loaded Proofs", collapsed by default — the content area only hosts expanded items); it now reorders the first expanded item.minimizeinteraction— the harness's flag change raced the worker'sselectedTaclet(the unarmed leg still ran armed) and the leg booleans were crossed; the legs now latch-join the FX-thread flag change and readarmed = no dialog && applied,unarmed = dialog && !applied. This exposed a product bug:WindowUserInterfaceControlF.completeAndApplyTacletMatchconstructed the taclet dialog Stage on the calling thread (a Stage cannot be built off the FX thread) — the construction now hops viaFxUtil.runAndWait(on-FX callers unchanged), and the harness dialog watcher pollsWindow.getWindows()throughcallAndWait(FX-restricted in JavaFX 25).loadingexit— the recipe never passed a demo sequent although the hook runs in the demo-load callback, so the app never reached the exit flow and the job ran into its 45-min timeout; the recipe passes the demo now (locally:exit-code=0, PASS).The windows
key.utilWeakValueInternerTestfailure is a pre-existing flaky concurrency test outside this port's scope (FX sources only); re-run on occurrence.