1 /*
   2  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  */
  24 package test.scenegraph.binding;
  25 
  26 import com.sun.javafx.collections.ImmutableObservableList;
  27 import java.lang.reflect.Constructor;
  28 import javafx.beans.property.SimpleStringProperty;
  29 import javafx.beans.property.StringProperty;
  30 import javafx.scene.control.*;
  31 import javafx.scene.text.Font;
  32 import javafx.scene.text.Text;
  33 import javafx.scene.image.Image;
  34 import javafx.scene.paint.CycleMethod;
  35 import javafx.scene.paint.LinearGradient;
  36 import javafx.scene.paint.Stop;
  37 import javafx.scene.Group;
  38 import javafx.scene.effect.*;
  39 import javafx.collections.FXCollections;
  40 import javafx.collections.ObservableList;
  41 import javafx.scene.Node;
  42 import javafx.scene.control.Labeled;
  43 import javafx.scene.control.cell.PropertyValueFactory;
  44 import javafx.scene.paint.Color;
  45 import javafx.scene.shape.*;
  46 import test.scenegraph.binding.BindingApp.Factory;
  47 import test.scenegraph.binding.BindingApp.NodeAndBindee;
  48 import static test.scenegraph.binding.Factories.Package.*;
  49 /**
  50  *
  51  * @author Sergey Grinev
  52  */
  53 public enum Factories implements Factory {
  54 
  55     // <editor-fold defaultstate="collapsed" desc="shapes">
  56     Rectangle(shapes, new DefaultFactory() {
  57 
  58         public NodeAndBindee create() {
  59             Rectangle rect = new Rectangle(100, 100, 100, 100);
  60             rect.setArcHeight(20);
  61             rect.setArcWidth(20);
  62             rect.setEffect(new Reflection());
  63             addStroke(rect);
  64             return new BindingApp.NodeAndBindee(rect, rect);
  65         }
  66     }),
  67     Circle(shapes, new DefaultFactory() {
  68 
  69         public NodeAndBindee create() {
  70             Circle node = new Circle(100,100,50);
  71             node.setEffect(new DropShadow());
  72             addStroke(node);
  73             return new BindingApp.NodeAndBindee(node, node);
  74         }
  75     }),
  76     Arc(shapes, new DefaultFactory() {
  77 
  78         public NodeAndBindee create() {
  79             Arc node = new Arc();
  80             node.setCenterX(50.0f);
  81             node.setCenterY(50.0f);
  82             node.setRadiusX(25.0f);
  83             node.setRadiusY(25.0f);
  84             node.setStartAngle(45.0f);
  85             node.setLength(270.0f);
  86             node.setType(ArcType.ROUND);
  87             addStroke(node);
  88             return new BindingApp.NodeAndBindee(node, node);
  89         }
  90     }),
  91     ArcTo(shapes, new DefaultFactory() {
  92 
  93         public NodeAndBindee create() {
  94             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
  95 
  96             ArcTo node = new ArcTo();
  97             node.setX(100.0f);
  98             node.setY(100.0f);
  99             node.setRadiusX(50.0f);
 100             node.setRadiusY(50.0f);
 101 
 102             Path path = PathBuilder.create().elements(moveTo, node).build();
 103             addStroke(path);
 104             return new BindingApp.NodeAndBindee(path, node);
 105         }
 106     }),
 107     CubicCurve(shapes, new DefaultFactory() {
 108 
 109         public NodeAndBindee create() {
 110             CubicCurve node = new CubicCurve();
 111             node.setStartX(0.0f);
 112             node.setStartY(50.0f);
 113 
 114             node.setControlX1(80.0f);
 115             node.setControlY1(250.0f);
 116 
 117             node.setControlX2(60.0f);
 118             node.setControlY2(-50.0f);
 119 
 120             node.setEndX(128.0f);
 121             node.setEndY(50.0f);
 122 
 123 
 124             addStroke(node);
 125             return new BindingApp.NodeAndBindee(node, node);
 126         }
 127     }),
 128 
 129 //    ClosePath(shapes, new DefaultFactory() {
 130 //
 131 //        public NodeAndBindee create() {
 132 //            ClosePath node = new ClosePath();
 133 //            addStroke(node);
 134 //            return new BindingApp.NodeAndBindee(node, node);
 135 //        }
 136 //    }),
 137     CubicCurveTo(shapes, new DefaultFactory() {
 138 
 139         public NodeAndBindee create() {
 140             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 141 
 142             CubicCurveTo node = new CubicCurveTo();
 143             node.setControlX1(80.0f);
 144             node.setControlY1(250.0f);
 145 
 146             node.setControlX2(60.0f);
 147             node.setControlY2(-50.0f);
 148 
 149             Path path = PathBuilder.create().elements(moveTo, node).build();
 150             addStroke(path);
 151             return new BindingApp.NodeAndBindee(path, node);
 152         }
 153     }),
 154     Ellipse(shapes, new DefaultFactory() {
 155 
 156         public NodeAndBindee create() {
 157             Ellipse node = new Ellipse();
 158             node.setCenterX(50.0f);
 159             node.setCenterY(50.0f);
 160             node.setRadiusX(20.0f);
 161             node.setRadiusY(40.0f);
 162             addStroke(node);
 163             return new BindingApp.NodeAndBindee(node, node);
 164         }
 165     }),
 166     HLineTo(shapes, new DefaultFactory() {
 167 
 168         public NodeAndBindee create() {
 169             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 170             HLineTo node = new HLineTo(100);
 171             Path path = PathBuilder.create().elements(moveTo, node).build();
 172             addStroke(path);
 173             return new BindingApp.NodeAndBindee(path, node);
 174         }
 175     }),
 176     Line(shapes, new DefaultFactory() {
 177 
 178         public NodeAndBindee create() {
 179             Line node = LineBuilder.create().startX(20).startY(20).endX(100).endY(50).build();
 180             addStroke(node);
 181             return new BindingApp.NodeAndBindee(node, node);
 182         }
 183     }),
 184     LineTo(shapes, new DefaultFactory() {
 185 
 186         public NodeAndBindee create() {
 187             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 188 
 189             LineTo node = new LineTo(100, 80);
 190 
 191             Path path = PathBuilder.create().elements(moveTo, node).build();
 192             addStroke(path);
 193             return new BindingApp.NodeAndBindee(path, node);
 194         }
 195     }),
 196     MoveTo(shapes, new DefaultFactory() {
 197 
 198         public NodeAndBindee create() {
 199             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 200 
 201             LineTo node = new LineTo(100, 80);
 202 
 203             Path path = PathBuilder.create().elements(moveTo, node).build();
 204             addStroke(path);
 205             return new BindingApp.NodeAndBindee(path, moveTo);
 206         }
 207     }),
 208     Path(shapes, new DefaultFactory() {
 209 
 210         public NodeAndBindee create() {
 211             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 212 
 213             LineTo node = new LineTo(100, 80);
 214             LineTo node2 = new LineTo(200, 180);
 215 
 216             Path path = PathBuilder.create().elements(moveTo, node, node2).build();
 217             addStroke(path);
 218             return new BindingApp.NodeAndBindee(path, path);
 219         }
 220     }),
 221 //    PathElement(shapes, new DefaultFactory() {
 222 //
 223 //        public NodeAndBindee create() {
 224 //            PathElement node = new PathElement();
 225 //            addStroke(node);
 226 //            return new BindingApp.NodeAndBindee(node, node);
 227 //        }
 228 //    }),
 229     Polygon(shapes, new DefaultFactory() {
 230 
 231         public NodeAndBindee create() {
 232             Polygon node = new Polygon();
 233             node.getPoints().addAll(new Double[]{
 234                                     0.0, 0.0,
 235                                     120.0, 10.0,
 236                                     10.0, 120.0});
 237             addStroke(node);
 238             return new BindingApp.NodeAndBindee(node, node);
 239         }
 240     }),
 241     Polyline(shapes, new DefaultFactory() {
 242 
 243         public NodeAndBindee create() {
 244             Polyline node = new Polyline(new double[]{10, 10, 30, 30, 40, 60, 50, 15});
 245             addStroke(node);
 246             return new BindingApp.NodeAndBindee(node, node);
 247         }
 248     }),
 249     QuadCurve(shapes, new DefaultFactory() {
 250 
 251         public NodeAndBindee create() {
 252             QuadCurve node = new QuadCurve();
 253 
 254             node.setStartX(0.0f);
 255             node.setStartY(10.0f);
 256             node.setEndX(12.0f);
 257             node.setEndY(120.0f);
 258             node.setControlX(125.0f);
 259             node.setControlY(0.0f);
 260             addStroke(node);
 261             return new BindingApp.NodeAndBindee(node, node);
 262         }
 263     }),
 264     QuadCurveTo(shapes, new DefaultFactory() {
 265 
 266         public NodeAndBindee create() {
 267             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 268             QuadCurveTo node = QuadCurveToBuilder.create().controlX(125).controlY(0).build();
 269             Path path = PathBuilder.create().elements(moveTo, node).build();
 270             addStroke(path);
 271             return new BindingApp.NodeAndBindee(path, path);        }
 272     }),
 273     SVGPath(shapes, new DefaultFactory() {
 274 
 275         public NodeAndBindee create() {
 276             SVGPath node = SVGPathBuilder.create().content("M40,60 C42,148 144,30 25,32").build();
 277             addStroke(node);
 278             return new BindingApp.NodeAndBindee(node, node);
 279         }
 280     }),
 281     VLineTo(shapes, new DefaultFactory() {
 282 
 283         public NodeAndBindee create() {
 284             MoveTo moveTo = MoveToBuilder.create().x(50).y(50).build();
 285             VLineTo node = new VLineTo(100);
 286             Path path = PathBuilder.create().elements(moveTo, node).build();
 287             addStroke(path);
 288             return new BindingApp.NodeAndBindee(path, node);
 289         }
 290     }),
 291     // </editor-fold>
 292 
 293     // <editor-fold defaultstate="collapsed" desc="effects">
 294     DropShadow(effects, new EffectFactory() {
 295             @Override
 296             public Effect getEffect() {
 297                 return new DropShadow();
 298             }
 299         })
 300     ,Shadow(effects, new EffectFactory() {
 301             @Override
 302             public Effect getEffect() {
 303                 return new Shadow();
 304             }
 305         })
 306     ,Reflection(effects, new EffectFactory() {
 307             @Override
 308             public Effect getEffect() {
 309                 return new Reflection();
 310             }
 311         })
 312     ,Blend(effects, new DefaultFactory() {
 313 
 314         public NodeAndBindee create() {
 315             Rectangle rect0 = new Rectangle(10, 10, 200, 200);
 316             rect0.setFill(new LinearGradient(0, 0, 0.25, 0.25, true, CycleMethod.REFLECT, new Stop[] { new Stop(0, Color.RED), new Stop(1, Color.YELLOW)} ));
 317 
 318             Rectangle rect = new Rectangle(50, 50, 100, 50);
 319             rect.setFill(Color.GREEN);
 320             Blend b = new Blend();
 321             b.setOpacity(0.7);
 322             b.setMode(BlendMode.ADD);
 323             b.setTopInput(ColorInputBuilder.create().paint(Color.BLUE).x(30).y(30).width(100).height(80).build());
 324             rect.setEffect(b);
 325             Group group = new Group(rect0,rect);
 326                 return new NodeAndBindee(group, b);
 327             }
 328         })
 329     ,Bloom(effects, new DefaultFactory() {
 330 
 331         public NodeAndBindee create() {
 332             Group group = new Group();
 333             Bloom bloom = new Bloom();
 334             group.setEffect(bloom);
 335             group.getChildren().add(RectangleBuilder.create().x(10).y(10).width(160).height(80).fill(Color.DARKBLUE).build());
 336             group.getChildren().add(RectangleBuilder.create().x(50).y(50).width(50).height(50).fill(Color.YELLOW).build());
 337             return new NodeAndBindee(group, bloom);
 338         }
 339         })
 340     ,BoxBlur(effects, new EffectFactory() {
 341             @Override
 342             public Effect getEffect() {
 343                 return new BoxBlur();
 344             }
 345         })
 346     ,ColorAdjust(effects, new EffectFactory() {
 347             @Override
 348             public Effect getEffect() {
 349                 return new ColorAdjust();
 350             }
 351         })
 352     ,DisplacementMap(effects, new DefaultFactory() {
 353 
 354         @Override
 355         public Constraint getConstraints(String name) {
 356             NumberConstraints nc = (NumberConstraints) super.getConstraints(name);
 357             switch(nc) {
 358                 case offsetX:
 359                 case offsetY:
 360                     return NumberConstraints.offsetForDisplacementMap;
 361                 default:
 362                     return nc;
 363             }
 364         }
 365 
 366         public NodeAndBindee create() {
 367             Group group = new Group();
 368             DisplacementMap dm = DisplacementMapBuilder.create().mapData(Consts.MAP_WAVES).build();
 369             group.setEffect(dm);
 370             group.getChildren().add(RectangleBuilder.create().x(50).y(50).width(200).height(80).fill(Color.DARKBLUE).build());
 371             group.getChildren().add(RectangleBuilder.create().x(0).y(0).width(250).height(200).fill(Color.TRANSPARENT).build());
 372             return new NodeAndBindee(group, dm);
 373         }
 374         })
 375 
 376     ,Flood(effects, new EffectFactory() {
 377             @Override
 378             public Effect getEffect() {
 379                 return ColorInputBuilder.create().x(0).y(0).width(50).height(50).build();
 380             }
 381         })
 382 
 383     ,GaussianBlur(effects, new EffectFactory() {
 384             @Override
 385             public Effect getEffect() {
 386                 return new GaussianBlur();
 387             }
 388         })
 389     ,Glow(effects, new EffectFactory() {
 390             @Override
 391             public Effect getEffect() {
 392                 return new Glow();
 393             }
 394         })
 395 
 396     ,Identity(effects, new EffectFactory() {
 397             @Override
 398             public Effect getEffect() {
 399                 return ImageInputBuilder.create().
 400                         source(new Image(Factories.class.getResourceAsStream("/test/scenegraph/resources/car.png"))).
 401                         build();
 402             }
 403         })
 404 
 405     ,InnerShadow(effects, new EffectFactory() {
 406             @Override
 407             public Effect getEffect() {
 408                 return new InnerShadow();
 409             }
 410         })
 411 
 412     // </editor-fold>
 413 
 414     // <editor-fold desc="Text">
 415     ,font(text, new DefaultFactory() {
 416 
 417         public NodeAndBindee create() {
 418             Text node = new Text("XO");
 419             node.setTranslateX(50);
 420             node.setTranslateY(150);
 421             node.setFont(Font.font("Arial", 60));
 422             addStroke(node);
 423             return new BindingApp.NodeAndBindee(node, node);
 424         }
 425     })
 426     // </editor-fold>
 427 
 428     // <editor-fold desc="Controls">
 429 
 430     ,button(controls, new DefaultFactory() {
 431 
 432         public NodeAndBindee create() {
 433             Button node = new Button();
 434             prepareControl(node);
 435             return new BindingApp.NodeAndBindee(node, node);
 436         }
 437     })
 438     ,buttonGraphic(controls, new DefaultFactory() {
 439 
 440         @Override
 441         public boolean verifyConstraint(String name) {
 442             return !name.startsWith("center") && !name.startsWith("layout");
 443         }
 444 
 445         public NodeAndBindee create() {
 446             Button node = new Button();
 447             prepareControl(node);
 448             return new BindingApp.NodeAndBindee(node, node.getGraphic());
 449         }
 450     })
 451     ,label(controls, new DefaultFactory() {
 452 
 453         public NodeAndBindee create() {
 454             Label node = new Label();
 455             prepareControl(node);
 456             return new BindingApp.NodeAndBindee(node, node);
 457         }
 458     })
 459     ,checkBox(controls, new DefaultFactory() {
 460 
 461         public NodeAndBindee create() {
 462             CheckBox node = new CheckBox();
 463             prepareControl(node);
 464             return new BindingApp.NodeAndBindee(node, node);
 465         }
 466     }),
 467     ChoiceBox(controls, new DefaultFactory() {
 468 
 469         public NodeAndBindee create() {
 470             ChoiceBox node = new ChoiceBox(defaultList);
 471             prepareControl(node);
 472             return new BindingApp.NodeAndBindee(node, node);
 473         }
 474     }),
 475     HtmlEditor(controls, new DefaultFactory() {
 476 
 477         public NodeAndBindee create() {
 478             Node node = null;
 479             try {
 480                 Class<?> htmlEditorCl = Class.forName("javafx.scene.web.HTMLEditor");
 481                 for(Constructor constructor : htmlEditorCl.getDeclaredConstructors()) {
 482                     if(constructor.getGenericParameterTypes().length == 0) {
 483                         constructor.setAccessible(true);
 484                         node = (Node) constructor.newInstance();
 485                         prepareControl((Control)node);
 486                     }
 487                 }
 488             } catch (Exception ignored) {
 489                 System.err.println("Warning: HtmlEditor is not currently supported in JavaFX Embedded");
 490             }
 491             return new BindingApp.NodeAndBindee(node, node);
 492         }
 493     }),
 494     Hyperlink(controls, new DefaultFactory() {
 495 
 496         public NodeAndBindee create() {
 497             Hyperlink node = new Hyperlink("http://javafx.com");
 498             prepareControl(node);
 499             return new BindingApp.NodeAndBindee(node, node);
 500         }
 501     }),
 502     ListView(controls, new DefaultFactory() {
 503 
 504         public NodeAndBindee create() {
 505             ListView node = new ListView(defaultList);
 506             prepareControl(node);
 507             return new BindingApp.NodeAndBindee(node, node);
 508         }
 509     }),
 510     MenuBar(controls, new DefaultFactory() {
 511 
 512         public NodeAndBindee create() {
 513             final Menu menu1 = new Menu("File");
 514             final Menu menu2 = new Menu("Options");
 515             final Menu menu3 = new Menu("Help");
 516 
 517             MenuBar node = new MenuBar();
 518             node.getMenus().addAll(menu1, menu2, menu3);
 519             prepareControl(node);
 520             return new BindingApp.NodeAndBindee(node, node);
 521         }
 522     }),
 523     MenuButton(controls, new DefaultFactory() {
 524 
 525         public NodeAndBindee create() {
 526             MenuButton node = new MenuButton();
 527             node.getItems().addAll(new MenuItem("Burger"), new MenuItem("Hot Dog"));
 528 
 529             prepareControl(node);
 530             return new BindingApp.NodeAndBindee(node, node);
 531         }
 532     }),
 533     PasswordBox(controls, new DefaultFactory() {
 534 
 535         public NodeAndBindee create() {
 536             PasswordField node = new PasswordField();
 537             node.setText("very weak password");
 538             prepareControl(node);
 539             return new BindingApp.NodeAndBindee(node, node);
 540         }
 541     }),
 542     ProgressBar(controls, new DefaultFactory() {
 543 
 544         public NodeAndBindee create() {
 545             ProgressBar node = new ProgressBar(.75);
 546             prepareControl(node);
 547             return new BindingApp.NodeAndBindee(node, node);
 548         }
 549     }),
 550     ProgressIndicator(controls, new DefaultFactory() {
 551 
 552         public NodeAndBindee create() {
 553             ProgressIndicator node = new ProgressIndicator(.45);
 554             prepareControl(node);
 555             return new BindingApp.NodeAndBindee(node, node);
 556         }
 557     }),
 558     RadioButton(controls, new DefaultFactory() {
 559 
 560         public NodeAndBindee create() {
 561             RadioButton node = new RadioButton();
 562             prepareControl(node);
 563             return new BindingApp.NodeAndBindee(node, node);
 564         }
 565     }),
 566     Separator(controls, new DefaultFactory() {
 567 
 568         public NodeAndBindee create() {
 569             Separator node = new Separator();
 570             ToolBar toolBar = new ToolBar(
 571                     new Button("New"),
 572                     node,
 573                     new Button("Open"));
 574             prepareControl(toolBar);
 575             return new BindingApp.NodeAndBindee(toolBar, node);
 576         }
 577     }),
 578     ScrollBar(controls, new DefaultFactory() {
 579 
 580         public NodeAndBindee create() {
 581             ScrollBar node = ScrollBarBuilder.create().min(0).max(100).value(50).build();
 582             prepareControl(node);
 583             return new BindingApp.NodeAndBindee(node, node);
 584         }
 585     }),
 586     Slider(controls, new DefaultFactory() {
 587 
 588         public NodeAndBindee create() {
 589             Slider node = new Slider(0,100,50);
 590             //TODO: after fix of RT-11969 consider returning this functionality
 591 //            node.setShowTickLabels(true);
 592 //            node.setShowTickMarks(true);
 593             prepareControl(node);
 594             return new BindingApp.NodeAndBindee(node, node);
 595         }
 596     }),
 597     TableView(controls, new DefaultFactory() {
 598 
 599         public NodeAndBindee create() {
 600             TableView<Person> node = new TableView<Person>();
 601 
 602             TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
 603             firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
 604             TableColumn<Person,String> lastNameCol = new TableColumn<Person,String>("Last Name");
 605             lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
 606 
 607             node.getColumns().setAll(firstNameCol, lastNameCol);
 608 
 609             ObservableList<Person> items = FXCollections.observableArrayList();
 610             items.add(new Person("First name", "Last name"));
 611             node.setItems(items);
 612 
 613             prepareControl(node);
 614             return new BindingApp.NodeAndBindee(node, node);
 615         }
 616     }),
 617     TextArea(controls, new DefaultFactory() {
 618 
 619         public NodeAndBindee create() {
 620             TextArea node = new TextArea();
 621             prepareControl(node);
 622             return new BindingApp.NodeAndBindee(node, node);
 623         }
 624     }),
 625     TextField(controls, new DefaultFactory() {
 626 
 627         public NodeAndBindee create() {
 628             TextField node = new TextField();
 629             prepareControl(node);
 630             return new BindingApp.NodeAndBindee(node, node);
 631         }
 632     }),
 633     ToggleButton(controls, new DefaultFactory() {
 634 
 635         public NodeAndBindee create() {
 636             ToggleButton node = new ToggleButton();
 637             prepareControl(node);
 638             return new BindingApp.NodeAndBindee(node, node);
 639         }
 640     }),
 641     ToggleButtonSelected(controls, new DefaultFactory() {
 642 
 643         public NodeAndBindee create() {
 644             ToggleButton node = new ToggleButton();
 645             node.selectedProperty().setValue(Boolean.TRUE);
 646             prepareControl(node);
 647             return new BindingApp.NodeAndBindee(node, node);
 648         }
 649     }),
 650     ToolBar(controls, new DefaultFactory() {
 651 
 652         public NodeAndBindee create() {
 653             ToolBar node = new ToolBar(
 654                     new Button("New"),
 655                     new Button("Open"),
 656                     new Button("Save"));
 657             prepareControl(node);
 658             return new BindingApp.NodeAndBindee(node, node);
 659         }
 660     }),
 661     TreeView(controls, new DefaultFactory(){
 662 
 663         public NodeAndBindee create() {
 664             TreeItem<String> root = new TreeItem<String>("Root Node");
 665             root.setExpanded(true);
 666             root.getChildren().addAll(
 667                     new TreeItem<String>("Item 1"),
 668                     new TreeItem<String>("Item 2"),
 669                     new TreeItem<String>("Item 3"));
 670             TreeView node = new TreeView(root);
 671             prepareControl(node);
 672             return new BindingApp.NodeAndBindee(node, node);
 673         }
 674     })// </editor-fold>
 675     ;
 676 
 677     public static void main(String[] args) { // for debug
 678         BindingApp.factory = Factories.Slider;
 679         BindingApp.main(null);
 680     }
 681 
 682     public enum Package {
 683         shapes("javafx.scene.shape"),
 684         effects("javafx.scene.effect"),
 685         text("javafx.scene.text"),
 686         controls("javafx.scene.control");
 687 
 688         public final String fullName;
 689 
 690         private Package(String fullName){
 691             this.fullName = fullName;
 692         }
 693     };
 694 
 695 
 696     // enum elements and mirror for Factory interface to simplify access
 697     private final Factory factory;
 698     public final Package packageName;
 699 
 700     private Factories(Package p, Factory factory) {
 701         this.factory = factory;
 702         this.packageName = p;
 703     }
 704 
 705     public NodeAndBindee create() {
 706         return factory.create();
 707     }
 708 
 709     public Constraint getConstraints(String name) {
 710         return factory.getConstraints(name);
 711     }
 712 
 713     public boolean verifyConstraint(String name) {
 714         return factory.verifyConstraint(name);
 715     }
 716 
 717     static abstract class DefaultFactory implements Factory {
 718         public Constraint getConstraints(String name) {
 719             NumberConstraints c = NumberConstraints._default;
 720             try {
 721                 c = NumberConstraints.valueOf(name);
 722             } catch (java.lang.IllegalArgumentException e) {
 723                 System.err.println("ERROR: model lacks constraints: " + name);
 724                 //use default for now
 725             }
 726             return c;
 727         }
 728 
 729         public boolean verifyConstraint(String name) {
 730             return true;
 731         }
 732 
 733     }
 734 
 735     //utility
 736     private static abstract class EffectFactory extends DefaultFactory {
 737 
 738         public abstract Effect getEffect();
 739 
 740         public NodeAndBindee create() {
 741                 Effect effect = getEffect();
 742                 Rectangle rect = RectangleBuilder.create().x(100).y(100).width(100).height(100).fill(Color.LIGHTGREEN).
 743                         stroke(Color.DARKGREEN).arcHeight(20).arcWidth(30).effect(effect).build();
 744                 return new NodeAndBindee(rect, effect);
 745         }
 746 
 747     }
 748 
 749     private static final ObservableList<String> defaultList = FXCollections.<String>observableArrayList("item 1", "item 2", "longlonglonglonglonglongitem");
 750 
 751     private static void addStroke(Shape shape) {
 752         shape.setFill(Color.LIGHTGREEN);
 753         shape.setStroke(Color.DARKGREEN);
 754         shape.getStrokeDashArray().add(10.);
 755         shape.getStrokeDashArray().add(8.);
 756     }
 757 
 758     private static void prepareControl(Control control) {
 759         control.setLayoutX(50);
 760         control.setLayoutY(50);
 761         control.setPrefSize(100, 50);
 762         control.setMinSize(100, 50);
 763         control.setMaxSize(100, 50);
 764         if (control instanceof Labeled) {
 765             Labeled l = (Labeled)control;
 766             Circle circle = new Circle(10);
 767             addStroke(circle);
 768             l.setGraphic(circle);
 769             l.setText("XO");
 770         }
 771     }
 772 
 773 
 774 
 775 
 776 }