88import javafx .animation .AnimationTimer ;
99import javafx .application .Application ;
1010import javafx .geometry .Insets ;
11+ import javafx .geometry .Pos ;
1112import javafx .scene .Node ;
1213import javafx .scene .Scene ;
1314import javafx .scene .canvas .Canvas ;
1415import javafx .scene .canvas .GraphicsContext ;
1516import javafx .scene .control .Button ;
1617import javafx .scene .control .ChoiceBox ;
1718import javafx .scene .control .Label ;
19+ import javafx .scene .control .ProgressBar ;
1820import javafx .scene .control .Menu ;
1921import javafx .scene .control .MenuBar ;
2022import javafx .scene .control .MenuItem ;
2527import javafx .scene .control .ToggleGroup ;
2628import javafx .scene .layout .BorderPane ;
2729import javafx .scene .layout .HBox ;
30+ import javafx .scene .layout .Priority ;
31+ import javafx .scene .layout .Region ;
2832import javafx .scene .layout .StackPane ;
2933import javafx .scene .layout .VBox ;
3034import javafx .scene .paint .Color ;
@@ -40,10 +44,10 @@ public class Main extends Application {
4044 long lastTick = 0 ;
4145 double acc = 0 ;
4246 Theme theme = Theme .DARK ;
43- Accent accent = new Accent ("Amber " , Color .web ("#c49a6c " ));
47+ Accent accent = new Accent ("Green " , Color .web ("#7fb069 " ));
4448 String fontFamily = "Monospaced" ;
4549 BarMode barMode = BarMode .RAINBOW ;
46- Color barColor = Color .web ("#c49a6c " );
50+ Color barColor = Color .web ("#7fb069 " );
4751
4852 Canvas canvas ;
4953 Slider speed ;
@@ -53,9 +57,11 @@ public class Main extends Application {
5357 ChoiceBox <SortAlgo > alg ;
5458 TextField algFilter ;
5559 Label status ;
60+ ProgressBar statusBar ;
5661 BorderPane root ;
5762 MenuBar menuBar ;
5863 HBox controlBar ;
64+ Region accentBar ;
5965 ChoiceBox <ThemeOption > themeChoice ;
6066 ChoiceBox <Accent > accentChoice ;
6167 ChoiceBox <String > fontChoice ;
@@ -80,6 +86,8 @@ public void start(Stage stage) {
8086 Button shuffle = new Button ("Shuffle" );
8187 Button run = new Button ("Run" );
8288 status = new Label ();
89+ statusBar = new ProgressBar (0 );
90+ statusBar .setPrefWidth (140 );
8391
8492 algFilter = new TextField ();
8593 algFilter .setPromptText ("Search..." );
@@ -96,8 +104,8 @@ public void start(Stage stage) {
96104
97105 accentChoice = new ChoiceBox <>();
98106 accentChoice .getItems ().addAll (
99- new Accent ("Amber" , Color .web ("#c49a6c" )),
100107 new Accent ("Green" , Color .web ("#7fb069" )),
108+ new Accent ("Amber" , Color .web ("#c49a6c" )),
101109 new Accent ("Orange" , Color .web ("#d38b5d" )),
102110 new Accent ("Cyan" , Color .web ("#6ea7b8" )),
103111 new Accent ("Red" , Color .web ("#b86e6e" )),
@@ -124,7 +132,9 @@ public void start(Stage stage) {
124132 controlBar = buildControlBar (shuffle , run );
125133 root = new BorderPane ();
126134 menuBar = buildMenu (stage );
127- VBox header = new VBox (menuBar , controlBar );
135+ accentBar = new Region ();
136+ accentBar .setPrefHeight (3 );
137+ VBox header = new VBox (accentBar , menuBar , controlBar );
128138 root .setTop (header );
129139 StackPane center = new StackPane (canvas );
130140 root .setCenter (center );
@@ -139,6 +149,7 @@ public void start(Stage stage) {
139149 if (!running ) {
140150 viz .init (c .intValue ());
141151 status .setText ("" );
152+ statusBar .setProgress (0 );
142153 draw ();
143154 }
144155 if (!sizeField .isFocused ()) sizeField .setText (String .valueOf (c .intValue ()));
@@ -184,6 +195,7 @@ public void start(Stage stage) {
184195 if (!running ) {
185196 viz .shuffle ();
186197 status .setText ("Shuffled" );
198+ statusBar .setProgress (0 );
187199 draw ();
188200 }
189201 });
@@ -193,6 +205,7 @@ public void start(Stage stage) {
193205 running = false ;
194206 resetTimer ();
195207 status .setText ("Paused" );
208+ updateStatus ();
196209 run .setText ("Run" );
197210 return ;
198211 }
@@ -207,6 +220,7 @@ public void start(Stage stage) {
207220 resetTimer ();
208221 running = true ;
209222 status .setText ("Running" );
223+ statusBar .setProgress (0 );
210224 run .setText ("Pause" );
211225 });
212226
@@ -226,9 +240,11 @@ public void handle(long now) {
226240 acc -= steps ;
227241 if (steps > 0 ) {
228242 boolean done = viz .step (steps );
243+ updateStatus ();
229244 if (done ) {
230245 running = false ;
231246 status .setText ("Done" );
247+ statusBar .setProgress (1 );
232248 run .setText ("Run" );
233249 }
234250 }
@@ -255,9 +271,12 @@ void applyTheme() {
255271 root .setStyle ("-fx-background-color:" + bg + "; -fx-base:" + panel + "; -fx-control-inner-background:" + panel + "; -fx-text-fill:" + text + "; -fx-accent:" + acc + "; -fx-focus-color:" + acc + "; -fx-faint-focus-color:" + acc + "33; -fx-font-family: " + fontFamily + "; -fx-font-size: 12px;" );
256272 menuBar .setStyle ("-fx-background-color:" + panel + "; -fx-text-fill:" + text + ";" );
257273 controlBar .setStyle ("-fx-background-color:" + panel + "; -fx-border-color:" + acc + "; -fx-border-width:0 0 1 0;" );
274+ accentBar .setStyle ("-fx-background-color:" + acc + ";" );
258275 for (Node n : controlBar .getChildren ()) {
259276 if (n instanceof Label l ) l .setTextFill (theme .text ());
260277 }
278+ status .setTextFill (accent .color ());
279+ statusBar .setStyle ("-fx-accent:" + acc + ";" );
261280 for (Node n : menuBar .getChildrenUnmodifiable ()) {
262281 if (n instanceof MenuBar mb ) mb .setStyle ("-fx-background-color:" + panel + ";" );
263282 }
@@ -291,6 +310,19 @@ void applyAlgoFilter() {
291310 }
292311 }
293312
313+ void updateStatus () {
314+ int total = viz .opTotal ();
315+ int idx = viz .opIndex ();
316+ if (total <= 0 ) {
317+ statusBar .setProgress (0 );
318+ return ;
319+ }
320+ double p = Math .min (1.0 , Math .max (0.0 , idx / (double ) total ));
321+ statusBar .setProgress (p );
322+ int pct = (int ) Math .round (p * 100 );
323+ status .setText ((running ? "Running " : "" ) + idx + "/" + total + " (" + pct + "%)" );
324+ }
325+
294326 void draw () {
295327 GraphicsContext g = canvas .getGraphicsContext2D ();
296328 double w = canvas .getWidth ();
@@ -472,17 +504,42 @@ void openAbout(Stage owner) {
472504 }
473505
474506 HBox buildControlBar (Button shuffle , Button run ) {
475- HBox box = new HBox (10 ,
476- label ("Algorithm" ), algFilter , alg ,
477- label ("Size" ), size , sizeField ,
478- label ("Speed" ), speed , speedField ,
479- shuffle , run ,
480- label ("Status" ), status
507+ size .setPrefWidth (160 );
508+ speed .setPrefWidth (160 );
509+
510+ HBox algoRow = new HBox (6 , algFilter , alg );
511+ HBox sizeRow = new HBox (6 , size , sizeField );
512+ HBox speedRow = new HBox (6 , speed , speedField );
513+ HBox runRow = new HBox (6 , shuffle , run );
514+ HBox statusRow = new HBox (6 , statusBar , status );
515+ algoRow .setAlignment (Pos .CENTER_LEFT );
516+ sizeRow .setAlignment (Pos .CENTER_LEFT );
517+ speedRow .setAlignment (Pos .CENTER_LEFT );
518+ runRow .setAlignment (Pos .CENTER_LEFT );
519+ statusRow .setAlignment (Pos .CENTER_LEFT );
520+ HBox .setHgrow (alg , Priority .NEVER );
521+ HBox .setHgrow (algFilter , Priority .NEVER );
522+ HBox .setHgrow (size , Priority .NEVER );
523+ HBox .setHgrow (speed , Priority .NEVER );
524+
525+ HBox box = new HBox (14 ,
526+ group ("Algorithm" , algoRow ),
527+ group ("Size" , sizeRow ),
528+ group ("Speed" , speedRow ),
529+ group ("Controls" , runRow ),
530+ group ("Status" , statusRow )
481531 );
532+ box .setAlignment (Pos .CENTER_LEFT );
482533 box .setPadding (new Insets (6 , 8 , 6 , 8 ));
483534 return box ;
484535 }
485536
537+ VBox group (String title , HBox row ) {
538+ VBox box = new VBox (4 , label (title ), row );
539+ box .setAlignment (Pos .CENTER_LEFT );
540+ return box ;
541+ }
542+
486543 Label label (String t ) {
487544 Label l = new Label (t );
488545 return l ;
0 commit comments