Friday, December 5, 2014

Friday Fun Component XXI

And another little fun component I've created for you...
There was a request for a JavaFX version of my TrafficLight Swing control from November 2011 (Friday Fun Component XIII) and so I've created one.
The basic control was done within a couple of hours but after I finished the control I had the idea to add some kind of masks. The reason for that is simple, if you take a look at the traffic lights in Germany (and also in other countries) you will not only find the following ones...



but also the next ones...


The traffic light on the last picture is a special version that can only be found in the eastern part of Germany (to be honest I only saw them in Berlin). Long story short, I've added the possibility to the traffic light and my version now looks like this...



The default traffic light control will not show any overlay and will look like the right version on the picture above (except the color which is customizable).
For each light one can switch on the overlay by calling e.g. 

setLowerOverlayVisible(true);

If you switch the overlay on for all three lights you will see the version on the left side. One could also adjust the color for each light (available are RED, YELLOW and GREEN) by calling e.g. 

setMiddleColor(LightColor.RED);

To change the background color of the traffic light one could call the method

setBackgroundColor(Color.DARKORANGE);

To add a custom shape as a mask for one of the lights I've added a method that takes a SVG path as a string e.g.

setLowerOverlayShape("M 0 0 L 100 0 L 100 100 L 0 100 L 0 0 Z");

To get the result that you see in the middle traffic light I used the following picture...



Just to give you an idea how the SVG path looks like...here it is...


"M 444.1487 333.8626 C 447.1197 330.8951 467.811 303.5027 467.811 303.5027 C 480.0558 287.159 493.702 267.7863 500.3011 254.4572 C 502.1896 249.9297 499.5399 243.5141 499.2354 239.1369 C 496.9518 206.3077 520.3127 193.7116 518.638 169.6369 C 518.1813 163.0711 502.0916 119.2731 501.5223 113.6345 C 500.9133 104.8801 520.4972 101.339 520.4972 101.339 C 526.1451 100.8593 533.1181 103.7161 538.4975 106.7027 C 542.8953 109.53 555.9396 120.9555 558.1721 136.1411 C 558.8104 140.4826 557.045 151.6116 555.4609 160.5164 C 571.1158 163.8417 605.2333 153.1114 611.9586 180.8343 C 613.4196 186.8573 606.6897 192.1831 602.6084 196.8609 C 609.9099 200.4362 618.6461 203.292 619.4073 214.2351 C 620.0162 222.9896 617.8053 233.2108 602.7593 238.64 C 602.7593 238.64 608.3714 241.0195 609.7949 244.755 C 612.9094 260.9012 597.6304 265.3755 589.0836 263.7666 C 584.7628 262.9532 564.3526 256.6652 557.7737 257.116 C 553.3879 257.4165 545.4089 261.7291 538.8488 263.4755 C 531.9924 264.9642 523.1437 266.0862 516.4128 264.3484 C 503.1337 280.9753 462.3076 335.7824 456.0219 352.145 C 453.2868 360.8542 452.2284 372.3198 452.8953 381.9073 C 453.4083 389.2823 454.8527 399.3723 458.3469 406.9135 C 462.3386 416.2732 467.4324 425.4647 471.8194 435.1678 C 477.9149 448.0883 482.9688 460.7098 488.0074 474.4438 C 499.87 506.2356 507.7894 537.3713 512.2889 570.0383 C 512.3915 571.5132 513.5253 578.4752 513.6023 579.5815 C 513.6023 579.5815 515.4518 598.1653 515.725 603.4263 C 516.1483 609.5108 516.6034 622.7253 516.6034 622.7253 C 516.2285 652.021 516.7795 693.2949 476.5109 696.0544 C 474.2943 696.2062 471.8006 696.3771 469.1376 695.4482 C 460.4096 692.7115 452.0024 681.2462 446.738 674.9379 C 440.2371 666.8616 434.08 658.3914 427.2353 650.7092 C 417.1015 638.4359 400.6964 625.3881 388.5665 621.7734 C 381.3677 619.6731 373.7903 618.8029 367.1404 619.2586 C 312.8331 622.98 274.3401 697.9595 238.5047 700.4152 C 229.6382 701.0228 219.4004 697.9266 216.3502 686.0942 C 215.4992 682.7933 214.403 676.7796 214.3517 676.0421 L 213.3578 661.753 L 213.2979 628.8745 C 212.0343 630.7211 210.6707 636.4648 206.7095 638.2183 C 205.9962 638.6377 204.4261 638.7453 203.3178 638.8212 C 202.579 638.8719 199.3143 638.6324 198.1804 638.3395 C 195.9381 638.1227 192.811 637.2314 190.5261 636.3632 C 185.5695 634.4798 181.2518 629.7738 180.6861 625.6443 L 180.2629 619.5599 C 180.8222 616.9282 181.878 613.4286 183.5456 610.7207 C 188.5229 602.2285 195.0292 594.3724 200.0321 586.249 C 204.6655 578.1507 207.1042 569.1841 207.2787 561.0209 L 206.6721 550.9662 C 205.832 545.5587 204.1082 539.6839 202.352 534.2188 C 200.5754 528.6903 194.7133 517.7916 193.4692 506.5763 L 192.6702 493.7559 C 191.3877 475.3184 211.6659 454.6624 220.7277 435.5161 C 232.042 411.3987 237.2157 387.0538 237.0775 363.7213 C 237.36 341.1009 237.6964 317.9211 237.6094 295.3261 L 236.3541 259.936 C 235.6938 237.1024 231.6087 191.7172 230.9276 185.9284 C 228.3365 175.3612 228.5252 163.3994 223.692 152.6154 C 267.2558 174.5468 319.5998 222.6457 354.9832 261.7179 C 371.0688 279.5115 387.1455 298.5099 400.6452 316.4807 C 411.646 330.5472 414.7373 341.6358 428.776 340.6738 C 434.1322 340.3068 439.5791 337.8033 444.1487 333.8626 ZM 0 400 C 0 620.9167 179.0833 800 400 800 C 620.9167 800 800 620.9167 800 400 C 800 179.0833 620.9167 0 400 0 C 179.0833 0 0 179.0833 0 400 ZM 263.7735 377.8755 C 273.6586 401.374 304.4725 410.7581 332.5463 398.7737 C 360.5947 386.8002 375.15 358.0852 365.1104 334.6976 C 355.1044 311.3885 324.424 302.1593 296.5297 314.0223 C 268.6104 325.8959 253.9216 354.456 263.7735 377.8755 ZM 495.5976 571.5526 C 486.0958 493.656 440.4304 397.4891 386.9657 322.6052 C 382.9275 323.2525 378.7046 323.9123 374.6921 324.9283 C 376.1082 329.2774 377.5757 334.3639 378.5966 338.3696 L 379.3033 351.1962 C 377.2644 391.2582 342.251 414.8691 311.2182 416.9957 C 294.963 418.1096 274.077 412.6864 260.1412 395.116 L 254.8433 398.9988 C 254.8433 398.9988 247.5887 448.1252 247.2089 453.3383 C 246.5366 459.683 245.1768 466.8159 244.5046 473.1605 C 242.9805 483.2687 241.9028 494.4578 240.4044 504.9347 C 239.568 514.2547 238.362 523.6001 237.1305 532.5766 C 236.294 541.8967 235.0881 551.2419 234.2259 560.1932 C 232.9584 573.9888 231.9614 587.6735 230.6938 601.4691 C 229.7958 615.2394 229.3659 629.0703 229.2066 642.7899 L 230.1454 661.6215 C 230.6174 663.0712 230.8083 683.1582 240.7831 682.4747 C 253.8981 681.576 271.3069 661.024 282.385 649.52 C 293.4375 637.6475 306.958 625.2352 318.6877 617.7622 C 323.9984 614.0637 330.8083 610.2503 336.6492 607.8245 C 343.5941 604.9402 350.1053 602.8469 357.3865 601.7721 C 362.0713 601.0807 363.2719 600.9984 364.3802 600.9224 C 372.5078 600.3655 383.7705 602.187 390.9694 604.2874 C 405.7622 608.8312 424.9676 623.4471 437.8926 638.4932 C 443.5007 644.4075 448.8164 651.4534 453.7114 657.7871 C 459.371 664.439 464.9072 673.3223 472.5563 677.8926 C 474.1456 678.8422 477.0472 678.4185 477.7862 678.3678 C 481.4805 678.1146 485.7483 678.1001 489.6069 674.8716 C 491.3514 673.2701 492.4959 671.329 493.1525 669.8121 C 500.5082 652.8204 497.5635 607.8202 497.2482 593.9478 L 495.5976 571.5526 ZM 225.3195 474.8457 C 225.2169 473.3707 225.3041 469.2892 222.3486 469.4917 C 220.5014 469.6183 217.0379 473.1902 215.7397 475.8727 C 210.7881 484.7337 206.3855 496.1507 207.0268 505.3694 C 207.7963 516.4319 213.6097 525.2963 218.8638 536.7924 L 225.3195 474.8457 Z"

As you can see that's a looooong string and the question is now...how can I apply this string to a node in the scene graph???

Well first I thought I should use a SVGPath() node and set the string as the content of the node but to be honest the SVGPath() node is a bit special in the way that it doesn't support methods like setPrefSize(w,h) etc. but only setScaleX(n), setScaleY(n) which means I would have to calculate the scaling correctly for each SVG path string.
So I decided to go in another direction and simply parse the string and create a JavaFX Path from the SVG path string.
Therefor I've created a little class named SVGPathParser which only has one method that parses SVG path string and returns a JavaFX Path from it. Just to make that clear, this is NOT an SVG parser but only a parser for SVG paths.
Why I did this you ask ???
Well in JavaFX I can set a Shape to a Region by calling setShape(Shape) and for that Region I can call setPrefSize(w,h) etc. which makes it very handy.
So with this approach I'm able to set custom shapes as a mask (keep in mind that the shapes have to have a square form factor) and I can scale them very easily.
This approach might also be useful for other things...

I guess that's all I have to say...if you like it you can fork the project on bitbucket.

Keep coding...

1 comment:

  1. Wow! Thank you so much for the quick implementation. It looks awesome. And adding a shape is a great touch. I think I'll extend it in a way that it's more than just a traffic light. I'm thinking about your gauges. eg you could have a boolean indicator red/green with just 1 light. Or you could have a horizontal array of n lights which all show some boolean value. That combined with various shapes for each light would give an instant information what the light stands for. Now I have to study your code. Thanks a lot! :-)

    ReplyDelete