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 = new MoveTo(50, 50);
  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 = new Path(moveTo, node);
 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 = new MoveTo(50, 50);
 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 = new Path(moveTo, node);
 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 = new MoveTo(50, 50);
 170             HLineTo node = new HLineTo(100);
 171             Path path = new Path(moveTo, node);
 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 = new Line(20, 20, 100, 50);
 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 = new MoveTo(50, 50);
 188 
 189             LineTo node = new LineTo(100, 80);
 190 
 191             Path path = new Path(moveTo, node);
 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 = new MoveTo(50, 50);
 200 
 201             LineTo node = new LineTo(100, 80);
 202 
 203             Path path = new Path(moveTo, node);
 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 = new MoveTo(50, 50);
 212 
 213             LineTo node = new LineTo(100, 80);
 214             LineTo node2 = new LineTo(200, 180);
 215 
 216             Path path = new Path(moveTo, node, node2);
 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 = new MoveTo(50, 50);
 268             QuadCurveTo node = new QuadCurveTo();
 269             node.setControlX(125);
 270             node.setControlY(0);
 271             Path path = new Path(moveTo, node);
 272             addStroke(path);
 273             return new BindingApp.NodeAndBindee(path, path);        }
 274     }),
 275     SVGPath(shapes, new DefaultFactory() {
 276 
 277         public NodeAndBindee create() {
 278             SVGPath node = new SVGPath();
 279             node.setContent("M40,60 C42,148 144,30 25,32");
 280             addStroke(node);
 281             return new BindingApp.NodeAndBindee(node, node);
 282         }
 283     }),
 284     VLineTo(shapes, new DefaultFactory() {
 285 
 286         public NodeAndBindee create() {
 287             MoveTo moveTo = new MoveTo(50, 50);
 288             VLineTo node = new VLineTo(100);
 289             Path path = new Path(moveTo, node);
 290             addStroke(path);
 291             return new BindingApp.NodeAndBindee(path, node);
 292         }
 293     }),
 294     // </editor-fold>
 295 
 296     // <editor-fold defaultstate="collapsed" desc="effects">
 297     DropShadow(effects, new EffectFactory() {
 298             @Override
 299             public Effect getEffect() {
 300                 return new DropShadow();
 301             }
 302         })
 303     ,Shadow(effects, new EffectFactory() {
 304             @Override
 305             public Effect getEffect() {
 306                 return new Shadow();
 307             }
 308         })
 309     ,Reflection(effects, new EffectFactory() {
 310             @Override
 311             public Effect getEffect() {
 312                 return new Reflection();
 313             }
 314         })
 315     ,Blend(effects, new DefaultFactory() {
 316 
 317         public NodeAndBindee create() {
 318             Rectangle rect0 = new Rectangle(10, 10, 200, 200);
 319             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)} ));
 320 
 321             Rectangle rect = new Rectangle(50, 50, 100, 50);
 322             rect.setFill(Color.GREEN);
 323             Blend b = new Blend();
 324             b.setOpacity(0.7);
 325             b.setMode(BlendMode.ADD);
 326             b.setTopInput(new ColorInput(30, 30, 100, 80, Color.BLUE));
 327             rect.setEffect(b);
 328             Group group = new Group(rect0,rect);
 329                 return new NodeAndBindee(group, b);
 330             }
 331         })
 332     ,Bloom(effects, new DefaultFactory() {
 333 
 334         public NodeAndBindee create() {
 335             Group group = new Group();
 336             Bloom bloom = new Bloom();
 337             group.setEffect(bloom);
 338             Rectangle r1 = new Rectangle (10, 10, 160, 80);
 339             r1.setFill(Color.DARKBLUE);
 340             Rectangle r2 = new Rectangle (50, 50, 50, 50);
 341             r1.setFill(Color.YELLOW);
 342             group.getChildren().add(r1);
 343             group.getChildren().add(r2);
 344             return new NodeAndBindee(group, bloom);
 345         }
 346         })
 347     ,BoxBlur(effects, new EffectFactory() {
 348             @Override
 349             public Effect getEffect() {
 350                 return new BoxBlur();
 351             }
 352         })
 353     ,ColorAdjust(effects, new EffectFactory() {
 354             @Override
 355             public Effect getEffect() {
 356                 return new ColorAdjust();
 357             }
 358         })
 359     ,DisplacementMap(effects, new DefaultFactory() {
 360 
 361         @Override
 362         public Constraint getConstraints(String name) {
 363             NumberConstraints nc = (NumberConstraints) super.getConstraints(name);
 364             switch(nc) {
 365                 case offsetX:
 366                 case offsetY:
 367                     return NumberConstraints.offsetForDisplacementMap;
 368                 default:
 369                     return nc;
 370             }
 371         }
 372 
 373         public NodeAndBindee create() {
 374             Group group = new Group();
 375             DisplacementMap dm = new DisplacementMap(Consts.MAP_WAVES);
 376             group.setEffect(dm);
 377             Rectangle r1 = new Rectangle (50, 50, 200, 80);
 378             r1.setFill(Color.DARKBLUE);
 379             Rectangle r2 = new Rectangle (0, 0, 250, 200);
 380             r1.setFill(Color.TRANSPARENT);
 381             group.getChildren().add(r1);
 382             group.getChildren().add(r2);
 383             return new NodeAndBindee(group, dm);
 384         }
 385         })
 386 
 387     ,Flood(effects, new EffectFactory() {
 388             @Override
 389             public Effect getEffect() {
 390                 ColorInput temp = new ColorInput();
 391                 temp.setX(0);
 392                 temp.setY(0);
 393                 temp.setWidth(50);
 394                 temp.setHeight(50);
 395                 return temp;
 396             }
 397         })
 398 
 399     ,GaussianBlur(effects, new EffectFactory() {
 400             @Override
 401             public Effect getEffect() {
 402                 return new GaussianBlur();
 403             }
 404         })
 405     ,Glow(effects, new EffectFactory() {
 406             @Override
 407             public Effect getEffect() {
 408                 return new Glow();
 409             }
 410         })
 411 
 412     ,Identity(effects, new EffectFactory() {
 413             @Override
 414             public Effect getEffect() {
 415                 return new ImageInput(new Image(Factories.class.getResourceAsStream("/test/scenegraph/resources/car.png")));
 416             }
 417         })
 418 
 419     ,InnerShadow(effects, new EffectFactory() {
 420             @Override
 421             public Effect getEffect() {
 422                 return new InnerShadow();
 423             }
 424         })
 425 
 426     // </editor-fold>
 427 
 428     // <editor-fold desc="Text">
 429     ,font(text, new DefaultFactory() {
 430 
 431         public NodeAndBindee create() {
 432             Text node = new Text("XO");
 433             node.setTranslateX(50);
 434             node.setTranslateY(150);
 435             node.setFont(Font.font("Arial", 60));
 436             addStroke(node);
 437             return new BindingApp.NodeAndBindee(node, node);
 438         }
 439     })
 440     // </editor-fold>
 441 
 442     // <editor-fold desc="Controls">
 443 
 444     ,button(controls, new DefaultFactory() {
 445 
 446         public NodeAndBindee create() {
 447             Button node = new Button();
 448             prepareControl(node);
 449             return new BindingApp.NodeAndBindee(node, node);
 450         }
 451     })
 452     ,buttonGraphic(controls, new DefaultFactory() {
 453 
 454         @Override
 455         public boolean verifyConstraint(String name) {
 456             return !name.startsWith("center") && !name.startsWith("layout");
 457         }
 458 
 459         public NodeAndBindee create() {
 460             Button node = new Button();
 461             prepareControl(node);
 462             return new BindingApp.NodeAndBindee(node, node.getGraphic());
 463         }
 464     })
 465     ,label(controls, new DefaultFactory() {
 466 
 467         public NodeAndBindee create() {
 468             Label node = new Label();
 469             prepareControl(node);
 470             return new BindingApp.NodeAndBindee(node, node);
 471         }
 472     })
 473     ,checkBox(controls, new DefaultFactory() {
 474 
 475         public NodeAndBindee create() {
 476             CheckBox node = new CheckBox();
 477             prepareControl(node);
 478             return new BindingApp.NodeAndBindee(node, node);
 479         }
 480     }),
 481     ChoiceBox(controls, new DefaultFactory() {
 482 
 483         public NodeAndBindee create() {
 484             ChoiceBox node = new ChoiceBox(defaultList);
 485             prepareControl(node);
 486             return new BindingApp.NodeAndBindee(node, node);
 487         }
 488     }),
 489     HtmlEditor(controls, new DefaultFactory() {
 490 
 491         public NodeAndBindee create() {
 492             Node node = null;
 493             try {
 494                 Class<?> htmlEditorCl = Class.forName("javafx.scene.web.HTMLEditor");
 495                 for(Constructor constructor : htmlEditorCl.getDeclaredConstructors()) {
 496                     if(constructor.getGenericParameterTypes().length == 0) {
 497                         constructor.setAccessible(true);
 498                         node = (Node) constructor.newInstance();
 499                         prepareControl((Control)node);
 500                     }
 501                 }
 502             } catch (Exception ignored) {
 503                 System.err.println("Warning: HtmlEditor is not currently supported in JavaFX Embedded");
 504             }
 505             return new BindingApp.NodeAndBindee(node, node);
 506         }
 507     }),
 508     Hyperlink(controls, new DefaultFactory() {
 509 
 510         public NodeAndBindee create() {
 511             Hyperlink node = new Hyperlink("http://javafx.com");
 512             prepareControl(node);
 513             return new BindingApp.NodeAndBindee(node, node);
 514         }
 515     }),
 516     ListView(controls, new DefaultFactory() {
 517 
 518         public NodeAndBindee create() {
 519             ListView node = new ListView(defaultList);
 520             prepareControl(node);
 521             return new BindingApp.NodeAndBindee(node, node);
 522         }
 523     }),
 524     MenuBar(controls, new DefaultFactory() {
 525 
 526         public NodeAndBindee create() {
 527             final Menu menu1 = new Menu("File");
 528             final Menu menu2 = new Menu("Options");
 529             final Menu menu3 = new Menu("Help");
 530 
 531             MenuBar node = new MenuBar();
 532             node.getMenus().addAll(menu1, menu2, menu3);
 533             prepareControl(node);
 534             return new BindingApp.NodeAndBindee(node, node);
 535         }
 536     }),
 537     MenuButton(controls, new DefaultFactory() {
 538 
 539         public NodeAndBindee create() {
 540             MenuButton node = new MenuButton();
 541             node.getItems().addAll(new MenuItem("Burger"), new MenuItem("Hot Dog"));
 542 
 543             prepareControl(node);
 544             return new BindingApp.NodeAndBindee(node, node);
 545         }
 546     }),
 547     PasswordBox(controls, new DefaultFactory() {
 548 
 549         public NodeAndBindee create() {
 550             PasswordField node = new PasswordField();
 551             node.setText("very weak password");
 552             prepareControl(node);
 553             return new BindingApp.NodeAndBindee(node, node);
 554         }
 555     }),
 556     ProgressBar(controls, new DefaultFactory() {
 557 
 558         public NodeAndBindee create() {
 559             ProgressBar node = new ProgressBar(.75);
 560             prepareControl(node);
 561             return new BindingApp.NodeAndBindee(node, node);
 562         }
 563     }),
 564     ProgressIndicator(controls, new DefaultFactory() {
 565 
 566         public NodeAndBindee create() {
 567             ProgressIndicator node = new ProgressIndicator(.45);
 568             prepareControl(node);
 569             return new BindingApp.NodeAndBindee(node, node);
 570         }
 571     }),
 572     RadioButton(controls, new DefaultFactory() {
 573 
 574         public NodeAndBindee create() {
 575             RadioButton node = new RadioButton();
 576             prepareControl(node);
 577             return new BindingApp.NodeAndBindee(node, node);
 578         }
 579     }),
 580     Separator(controls, new DefaultFactory() {
 581 
 582         public NodeAndBindee create() {
 583             Separator node = new Separator();
 584             ToolBar toolBar = new ToolBar(
 585                     new Button("New"),
 586                     node,
 587                     new Button("Open"));
 588             prepareControl(toolBar);
 589             return new BindingApp.NodeAndBindee(toolBar, node);
 590         }
 591     }),
 592     ScrollBar(controls, new DefaultFactory() {
 593 
 594         public NodeAndBindee create() {
 595             ScrollBar node = new ScrollBar();
 596             node.setMin(0);
 597             node.setMax(100);
 598             node.setValue(50);
 599             prepareControl(node);
 600             return new BindingApp.NodeAndBindee(node, node);
 601         }
 602     }),
 603     Slider(controls, new DefaultFactory() {
 604 
 605         public NodeAndBindee create() {
 606             Slider node = new Slider(0,100,50);
 607             //TODO: after fix of RT-11969 consider returning this functionality
 608 //            node.setShowTickLabels(true);
 609 //            node.setShowTickMarks(true);
 610             prepareControl(node);
 611             return new BindingApp.NodeAndBindee(node, node);
 612         }
 613     }),
 614     TableView(controls, new DefaultFactory() {
 615 
 616         public NodeAndBindee create() {
 617             TableView<Person> node = new TableView<Person>();
 618 
 619             TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
 620             firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
 621             TableColumn<Person,String> lastNameCol = new TableColumn<Person,String>("Last Name");
 622             lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
 623 
 624             node.getColumns().setAll(firstNameCol, lastNameCol);
 625 
 626             ObservableList<Person> items = FXCollections.observableArrayList();
 627             items.add(new Person("First name", "Last name"));
 628             node.setItems(items);
 629 
 630             prepareControl(node);
 631             return new BindingApp.NodeAndBindee(node, node);
 632         }
 633     }),
 634     TextArea(controls, new DefaultFactory() {
 635 
 636         public NodeAndBindee create() {
 637             TextArea node = new TextArea();
 638             prepareControl(node);
 639             return new BindingApp.NodeAndBindee(node, node);
 640         }
 641     }),
 642     TextField(controls, new DefaultFactory() {
 643 
 644         public NodeAndBindee create() {
 645             TextField node = new TextField();
 646             prepareControl(node);
 647             return new BindingApp.NodeAndBindee(node, node);
 648         }
 649     }),
 650     ToggleButton(controls, new DefaultFactory() {
 651 
 652         public NodeAndBindee create() {
 653             ToggleButton node = new ToggleButton();
 654             prepareControl(node);
 655             return new BindingApp.NodeAndBindee(node, node);
 656         }
 657     }),
 658     ToggleButtonSelected(controls, new DefaultFactory() {
 659 
 660         public NodeAndBindee create() {
 661             ToggleButton node = new ToggleButton();
 662             node.selectedProperty().setValue(Boolean.TRUE);
 663             prepareControl(node);
 664             return new BindingApp.NodeAndBindee(node, node);
 665         }
 666     }),
 667     ToolBar(controls, new DefaultFactory() {
 668 
 669         public NodeAndBindee create() {
 670             ToolBar node = new ToolBar(
 671                     new Button("New"),
 672                     new Button("Open"),
 673                     new Button("Save"));
 674             prepareControl(node);
 675             return new BindingApp.NodeAndBindee(node, node);
 676         }
 677     }),
 678     TreeView(controls, new DefaultFactory(){
 679 
 680         public NodeAndBindee create() {
 681             TreeItem<String> root = new TreeItem<String>("Root Node");
 682             root.setExpanded(true);
 683             root.getChildren().addAll(
 684                     new TreeItem<String>("Item 1"),
 685                     new TreeItem<String>("Item 2"),
 686                     new TreeItem<String>("Item 3"));
 687             TreeView node = new TreeView(root);
 688             prepareControl(node);
 689             return new BindingApp.NodeAndBindee(node, node);
 690         }
 691     })// </editor-fold>
 692     ;
 693 
 694     public static void main(String[] args) { // for debug
 695         BindingApp.factory = Factories.Slider;
 696         BindingApp.main(null);
 697     }
 698 
 699     public enum Package {
 700         shapes("javafx.scene.shape"),
 701         effects("javafx.scene.effect"),
 702         text("javafx.scene.text"),
 703         controls("javafx.scene.control");
 704 
 705         public final String fullName;
 706 
 707         private Package(String fullName){
 708             this.fullName = fullName;
 709         }
 710     };
 711 
 712 
 713     // enum elements and mirror for Factory interface to simplify access
 714     private final Factory factory;
 715     public final Package packageName;
 716 
 717     private Factories(Package p, Factory factory) {
 718         this.factory = factory;
 719         this.packageName = p;
 720     }
 721 
 722     public NodeAndBindee create() {
 723         return factory.create();
 724     }
 725 
 726     public Constraint getConstraints(String name) {
 727         return factory.getConstraints(name);
 728     }
 729 
 730     public boolean verifyConstraint(String name) {
 731         return factory.verifyConstraint(name);
 732     }
 733 
 734     static abstract class DefaultFactory implements Factory {
 735         public Constraint getConstraints(String name) {
 736             NumberConstraints c = NumberConstraints._default;
 737             try {
 738                 c = NumberConstraints.valueOf(name);
 739             } catch (java.lang.IllegalArgumentException e) {
 740                 System.err.println("ERROR: model lacks constraints: " + name);
 741                 //use default for now
 742             }
 743             return c;
 744         }
 745 
 746         public boolean verifyConstraint(String name) {
 747             return true;
 748         }
 749 
 750     }
 751 
 752     //utility
 753     private static abstract class EffectFactory extends DefaultFactory {
 754 
 755         public abstract Effect getEffect();
 756 
 757         public NodeAndBindee create() {
 758                 Effect effect = getEffect();
 759                 Rectangle rect = new Rectangle(100, 100, 100, 100);
 760                 rect.setFill(Color.LIGHTGREEN);
 761                 rect.setStroke(Color.DARKGREEN);
 762                 rect.setArcHeight(20);
 763                 rect.setArcWidth(30);
 764                 rect.setEffect(effect);
 765                 return new NodeAndBindee(rect, effect);
 766         }
 767 
 768     }
 769 
 770     private static final ObservableList<String> defaultList = FXCollections.<String>observableArrayList("item 1", "item 2", "longlonglonglonglonglongitem");
 771 
 772     private static void addStroke(Shape shape) {
 773         shape.setFill(Color.LIGHTGREEN);
 774         shape.setStroke(Color.DARKGREEN);
 775         shape.getStrokeDashArray().add(10.);
 776         shape.getStrokeDashArray().add(8.);
 777     }
 778 
 779     private static void prepareControl(Control control) {
 780         control.setLayoutX(50);
 781         control.setLayoutY(50);
 782         control.setPrefSize(100, 50);
 783         control.setMinSize(100, 50);
 784         control.setMaxSize(100, 50);
 785         if (control instanceof Labeled) {
 786             Labeled l = (Labeled)control;
 787             Circle circle = new Circle(10);
 788             addStroke(circle);
 789             l.setGraphic(circle);
 790             l.setText("XO");
 791         }
 792     }
 793 
 794 
 795 
 796 
 797 }