Animate cell#14
Merged
Merged
Conversation
Update readme
Closed
…rid centering Replace the hand-rolled AnimatableService/ServiceState orchestration with a javafx.concurrent.Worker-based service layer, and center the grid with equal left/right margins. New package org.mahefa.service.concurrent: - AnimationWorker<T>: implements Worker<T>, driving an AnimationTimer on the FX thread (READY -> SCHEDULED -> RUNNING -> SUCCEEDED/CANCELLED), with bindable state/running/value, cancel(), and setCurrentSpeed/onSpeedChanged for live speed changes. - PathfindingWorker / MazeGeneratorWorker: reuse AStar/Solver and AldousBroder/MazeGenerator unchanged. Wiring: GridService and MainWindowController use the workers; isReady binds to runningProperty().not(). Old RouteFinderService/MazeService paths are commented out, not deleted (project still in progress). Grid centering: signed padding + drop the +5 canvas inflation so left/right margins are equal (was left-heavy, occasionally flipping to the right). Refs #15 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…x-worker Migrate maze/pathfinding services to javafx.concurrent.Worker + fix grid centering
Infra-only migration to unblock native CSS animations; no behaviour change.
- JavaFX 20.0.2 -> 23 (via javafx.version property); Java baseline -> 21.
- Spring Boot parent 2.1.3.RELEASE -> 3.5.0 (Spring 6 / jakarta). The old
spring-boot-maven-plugin could not process Java 21 classfiles that JavaFX 23
ships as ("Unsupported class file major version 65"). No javax.* usage in
source, so the jakarta move needs no code changes.
- Drop jfoenix (0 usages in source/FXML) and the stale explicit junit 4.11.
- Add org.mahefa.Launcher (does not extend Application) and point the
spring-boot / exec plugins at it, avoiding the "JavaFX runtime components are
missing" launcher guard for both forked run and fat-jar.
- Drop the redundant maven-compiler-plugin source/target (java.version drives it).
jfxanimation is kept for now; it's removed in PR 2 with the CSS-transition rewrite.
Verified: mvn compile clean; app boots via spring-boot:run through the launcher
(Spring Boot 3.5.0, Java 21), UI renders, ikonli 12.3.1 FontIcons render, no
runtime exceptions.
Closes #17
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Migrate to JavaFX 23 + Spring Boot 3.5.0 (infra) [1/2]
The sass-maven-plugin (3.7.2) runs SCSS compilation through embedded JRuby, whose
FilenoUtil reflects into java.base/sun.nio.ch. On Java 17+ that prints an
IllegalCallerException + stack trace during `mvn clean install`
(sass:update-stylesheets). It is non-fatal (CSS still compiles) and pre-existing
(unrelated to the JavaFX 23 / Spring Boot upgrade), just noisy.
Fix: open the package to the unnamed module for the Maven JVM itself (where the
plugin's JRuby runs) via .mvn/jvm.config:
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
Verified: `mvn clean install` now completes with BUILD SUCCESS and no
FilenoUtil/IllegalCallerException output.
Closes #19
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fix 'sun.nio.ch is not open to unnamed module' during the build
- Console shows only an INFO-level narrative: message-only %highlight pattern + logging.threshold.console=INFO (the key that keeps per-cell DEBUG off the terminal); framework logs quieted to WARN. - New service.concurrent.progress package: Narrative (symbols + human()), ProgressReporter (daemon-ticker braille spinner, committed checkmark/cross line + summary), LogCleaner (Clear buttons reset the log; console WIPE|MARKER and file WIPE|APPEND|NEW_FILE handled independently). - Workers own a ProgressReporter and drive it via new AnimationWorker hooks onSucceeded()/onCancelled()/updateMessage(); Solver/MazeGenerator expose search counters. A* logs cursor + frontier push/relax detail at DEBUG. - Optional, opt-in per-session file log: LogFileInitializer attaches a timestamped Logback FileAppender (logs/pathfinding-fx-<timestamp>.log, TRACE threshold so it keeps the DEBUG detail the console drops). NEW_FILE rolls to a fresh timestamped file on clear. - App-owned config namespaced under app.* and bound by AppProperties (@ConfigurationProperties, @ConfigurationPropertiesScan); clear modes bind directly as enums; AppProperties.Narrative#newLogCleaner() is the factory. Convert application.properties to application.yml. - Remove the dead AnimatableService/MazeService/RouteFinderService/ServiceState service layer; add Heap.size() and enum getLabel(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Worker narrative logging + quiet console
Pure moves, no behavior change. Rename the base package/groupId org.mahefa -> com.mahefa.pathfindingfx (reverse-domain) and regroup by concern: - ui.component / ui.controller / ui.event / ui.animation / ui.style - domain (Location, RouteNode, Cost) + domain.enumerator - algorithm (State) + algorithm.pathfinding + algorithm.maze + algorithm.collection - util, exception, config, service (+ service.concurrent[.progress]) Breaks up the old 'common' catch-all and separates JavaFX widgets from the model that were both under 'component'. Updates the 3 FXML files (Navbar/MenuBar imports + fx:controller), pom.xml (groupId + mainClass x2) and application.yml (logging.level). Spring component scan is unaffected (entry point stays the base package). Adds explicit imports where the component split crossed a same-package reference (Cell/Grid -> domain.Location; RouteNode -> ui.component.Cell). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RouteNode now stores a domain Location for current/previous instead of a UI Cell, so the whole com.mahefa.pathfindingfx.domain package is free of JavaFX and ui imports. Solver's node map is keyed by Location; AStar resolves a Cell from the grid where it needs to mutate the view (grid.getCellAt(row, col)). Behavior is unchanged: the grid holds one Cell per location, so value-equality keying by Location is equivalent to the previous identity keying by Cell. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refactor: package architecture (com.mahefa.pathfindingfx) + decouple RouteNode
Replace the per-algorithm AnimationTimer approach with a record/replay design reusable across both algorithm categories: - algorithm.step: Step / StepType / Stepper + AbstractStepper (shared superclass holding the pure GridModel and the lazy step buffer; subclasses implement only advance()/isComplete()). - algorithm.grid: pure JavaFX-free GridModel snapshot + Moves (neighbours + A* turn cost, ported from GridUtils to operate on Location only). - Steppers: AStarStepper (search + PATH steps carrying the arrow angle), AldousBroderStepper, RandomizedStepper — pure, reuse RouteNode/MinHeap/Cost. - service.concurrent: StepPlayer (speed-controlled, testable pulse(now)); one reusable StepWorker driving any Stepper; GridSnapshot (UI→model boundary); StepTally + RunNarrative so the worker logs the ▶/live/✓ narrative for any run. - ui.component.GridStepRenderer: the only UI-touching piece — StepType→Cell flag, and a faithful port of the A* "drawback" arrow that walks to the target. - GridService.generateMaze/findPath flow through the single StepWorker; controller rewired accordingly. Fixes / fidelity: - Aldous-Broder start/target were left as walls — now opened (Flag NONE) up front; NodeType (START/TARGET) is never touched, so it is preserved. - Restores the moving shortest-path arrow and the worker narrative log. - PATH steps animate at a fixed interval (LaunchAnimationSpeed.SHORTEST_PATH), independent of the search-speed slider — matching the original drawback, which stayed fast even on SLOW. Old algorithm classes and workers are @deprecated(forRemoval = true), not modified. Tests: StepPlayerSpeedTest, StepPlayerPathSpeedTest, AStarStepperTest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reusable Stepper/StepPlayer pipeline for maze + pathfinding
JavaFX CSS has no @Keyframes, so the original web keyframe animations are reproduced natively (no jfxanimation): - ui.animation.NodeAnimations (javafx.animation only): - pop(Node): ScaleTransition for start/target icon appearance. - visited(Region): Timeline pulse (scale 0.3→1.2→1.0) + background morph dark-blue → blue → green → cyan, ending filled cyan (1.5s, ease-out). - shortestPath(Region): Timeline scale pulse 0.6→1.2→1.0 (1.5s, linear); yellow fill/border from CSS. - MainWindowController flag listener: WALL→pop, VISITED→visited, SHORTEST_PATH→ shortestPath; other flags (NONE/CURRENT) release the programmatic background and reset scale so CSS applies. Fixes the old missing-break/commented-CURRENT bug. - cell.scss: base `.cell` gets `-fx-background-color: transparent` + a `transition` for the simple colour states (wall/current/shortest-path); `:visited` keeps only its border (background is animated by the Timeline). - Deleted CellAnimation; removed the de.schlegel11:jfxanimation dependency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reveal animations (NodeAnimations, cell.scss, controller): - Run the visited/shortest-path scale+colour pulse on a transient overlay tile instead of the cell, so a cell's border (which doubles as the shared gridline) no longer ripples/collapses when the pulse shrinks it. The tile is created per reveal and removed on finish/interruption — no permanent per-cell node. - Track the running reveal per node and stop it before starting a new one, so fast VISITED -> SHORTEST_PATH transitions can't fight over the same background/scale (fixes the colour overlap) or leak a tile. - Restore the pop overshoot bounce (0.3 -> 1.2 -> 1.0): walls at 0.3s, start/target icons at 2s. Shortest-path pop now rides on the travelling arrow (0.6 -> 1.2 -> 1.0) so it stays cohesive without scaling the cell. - Grid draws only top+left cell borders (last row/col add the outer edges) so shared gridlines aren't doubled into a bold 2px line. Path arrow (GridStepRenderer, Grid): - Remove the arrow from its previous cell by reference, not index 0, so the reveal tile isn't deleted instead and the arrow isn't stranded at the end. - Clear stray arrows defensively on board clear. Target node lifecycle (AStarStepper, GridStepRenderer): - Don't mark the target CURRENT on arrival (pointer/shortest-path colours are identical, so it read as an early path cell); mark it VISITED, then SHORTEST_PATH only when the drawback arrow lands on it. Basic random maze (StepPlayer, StepWorker, GridService, RandomizedStepper): - Place all walls at once, independent of the speed slider, matching the original; Aldous-Broder stays paced. StepPlayer treats a non-positive interval as instant; StepWorker.runInstant drives it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cell animation via native CSS transitions (drop jfxanimation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Update readme