changeset 2201:d4a7662633a2

Merge
author nam
date Wed, 16 Jan 2013 11:42:20 -0800
parents 086018f02968 7411d3b17dcb
children 9e9934bc1a8c
files javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PopupControlSkin.java
diffstat 109 files changed, 6695 insertions(+), 2826 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Jan 10 10:01:15 2013 -0800
+++ b/.hgtags	Wed Jan 16 11:42:20 2013 -0800
@@ -59,3 +59,4 @@
 81dc4ec05f628f1cf925f2b08eb66ba96ae40573 8.0-b69
 cb178c197204c27013eb658d80dbb0f4e17ca1fb 8.0-b70
 c80842bf169ab1d4d2232069dfed37f016bdb239 8.0-b71
+3819833c0c51b638a5d4a3c35016636786b1c60a 8.0-b72
--- a/apps/experiments/Modena/nbproject/project.properties	Thu Jan 10 10:01:15 2013 -0800
+++ b/apps/experiments/Modena/nbproject/project.properties	Wed Jan 16 11:42:20 2013 -0800
@@ -112,7 +112,6 @@
     ${dist.jar}:\
     ${javac.classpath}:\
     ${build.classes.dir}
-run.jvmargs=-Dprism.disableRegionCaching=true
 run.test.classpath=\
     ${javac.test.classpath}:\
     ${build.test.classes.dir}
--- a/apps/experiments/Modena/src/modena/Modena.css	Thu Jan 10 10:01:15 2013 -0800
+++ b/apps/experiments/Modena/src/modena/Modena.css	Wed Jan 16 11:42:20 2013 -0800
@@ -32,8 +32,8 @@
 
 /*******************************************************************************
  *                                                                             *
- * CSS Styles for core infrastructure bits.  The .root section provides the   *
- * overall default font and colors used by the rest of the sections.           *
+ * CSS Styles for core infrastructure bits.  The .root section provides the    *
+ * overall default colors used by the rest of the sections.                    *
  *                                                                             *
  ******************************************************************************/
 
@@ -47,7 +47,6 @@
     /* A light grey that is the base color for objects.  Instead of using
      * -fx-base directly, the sections in this file will typically use -fx-color.
      */
-    /*-fx-base: #d0d0d0;*/
     -fx-base: #ececec;
 
     /* A very light grey used for the background of windows.  See also
@@ -61,7 +60,9 @@
      * -fx-text-fill value for text painted on top of backgrounds colored
      * with -fx-control-inner-background.
      */
-    -fx-control-inner-background: white;
+    -fx-control-inner-background: derive(-fx-base,80%);
+    /* Version of -fx-control-inner-background for alternative rows */
+    -fx-control-inner-background-alt: derive(-fx-control-inner-background,-2%);
 
     /* One of these colors will be chosen based upon a ladder calculation
      * that uses the brightness of a background color.  Instead of using these
@@ -81,8 +82,8 @@
      * text; selected items in menus, lists, trees, and tables; progress bars;
      * default buttons.
      */
-    /*-fx-accent: #a3daee;*/
-    -fx-accent: #4fb6d6;
+    /*-fx-accent: #4fb6d6;*/
+    -fx-accent: #0096C9;
 
     /* A bright blue for the focus indicator of objects. Typically used as the
      * first color in -fx-background-color for the "focused" pseudo-class. Also
@@ -159,7 +160,7 @@
     -fx-box-border: ladder(
         -fx-color,
         black 20%,
-        derive(-fx-color,-30%) 30%
+        derive(-fx-color,-15%) 30%
     );
 
     /* Darker than -fx-background and used to draw boxes around text boxes and
@@ -170,50 +171,20 @@
         black 10%,
         derive(-fx-background, -15%) 30%
     );
-
-    /* Typically lighter than -fx-background and used to provide a small
-     * highlight under controls and tick marks for checkboxes and radio buttons.
-     * Often used with an insets of 0 0 -1 0, and is also often the first
-     * color in a -fx-background-color list.  Also is typically replaced by
-     * -fx-focus-color with an insets of -1.4 in the "focused" pseudoclass.
-     */
-/*    -fx-shadow-highlight-color: ladder(
-        -fx-background,
-        transparent 0%,
-        derive(-fx-background,40%)   5%,
-        derive(-fx-background,60%)  70%,
-        derive(-fx-background,100%) 85%,
-        derive(-fx-background,100%) 97%,
-        derive(-fx-background,-10%) 97.5%
-      );*/
-
+    
     /* A gradient that goes from a little darker than -fx-color on the top to
      * even more darker than -fx-color on the bottom.  Typically is the second
      * color in the -fx-background-color list as the small thin border around
      * a control. It is typically the same size as the control (i.e., insets
      * are 0).
      */
-    -fx-outer-border: derive(-fx-color,-20%);
-/*    -fx-outer-border: linear-gradient(
-        to bottom,
-        derive(-fx-color,-9%) 0%, 
-        derive(-fx-color,-33%) 100%
-    );*/
+    -fx-outer-border: derive(-fx-color,-23%);
 
     /* A gradient that goes from a bit lighter than -fx-color on the top to
      * a little darker at the bottom.  Typically is the third color in the
      * -fx-background-color list as a thin highlight inside the outer border.
      * Insets are typically 1.
      */
-/*    -fx-inner-border: linear-gradient(
-        to bottom,
-        ladder(-fx-color, 
-               derive(-fx-color,80%) 60%, 
-               white 82%) 0%,
-        ladder(-fx-color, 
-               derive(-fx-color,20%) 10%, 
-               derive(-fx-color,-10%) 80%) 100%
-    );*/
     -fx-inner-border: linear-gradient(to bottom, 
         derive(-fx-color,75%), 
         derive(-fx-color,2%));
@@ -243,18 +214,9 @@
      * in the -fx-background-color list and represents main body of the control.
      * Insets are typically 2.
      */
-/*    -fx-body-color: linear-gradient(
-        to bottom,
-        derive(-fx-color,34%) 0%,
-        derive(-fx-color,-18%) 100%
-    );*/
     -fx-body-color: linear-gradient(to bottom, derive(-fx-color,10%) ,derive(-fx-color,-6%));
-        
-    -fx-body-color-bottomup:  linear-gradient(
-        to top,
-        derive(-fx-color,34%) 0%,
-        derive(-fx-color,-18%) 100%
-    );
+    -fx-body-color-bottomup: linear-gradient(to top, derive(-fx-color,10%) ,derive(-fx-color,-6%));
+    -fx-body-color-to-right: linear-gradient(to right, derive(-fx-color,10%) ,derive(-fx-color,-6%));
 
     /* The color to use as -fx-text-fill when painting text on top of
      * backgrounds filled with -fx-base, -fx-color, and -fx-body-color.
@@ -303,11 +265,7 @@
      * remove the setting -fx-background in all the sections that use
      * -fx-selection-bar.
      */
-    -fx-selection-bar: linear-gradient(
-        to bottom,
-        derive(-fx-background,-7%) 0%,
-        derive(-fx-background,-34%) 100%
-    );
+    -fx-selection-bar: -fx-accent;
 
     /* The color to use as -fx-text-fill when painting text on top of
      * backgrounds filled with -fx-selection-bar.
@@ -351,128 +309,226 @@
     -fx-background-color: -fx-background;
 }
 
-/* ====   LABEL   =========================================================== */
+/*******************************************************************************
+ *                                                                             *
+ * Common Styles                                                               *
+ *                                                                             *
+ * These are styles that give a standard look to a whole range of controls     *
+ *                                                                             *
+ ******************************************************************************/
 
-.label {
-    -fx-text-fill: -fx-text-background-color;
-}
+/* ====   BUTTON LIKE THINGS   ============================================== */
 
-/* ====   BUTTON   ========================================================== */
-
-.button {
+.button,
+.toggle-button,
+.radio-button > .radio,
+.check-box > .box,
+.menu-button,
+.split-menu-button > .arrow-button,
+.choice-box,
+.combo-box-base {
     -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
     -fx-background-insets: 0, 1, 2;
     -fx-background-radius: 5, 4, 3;
     -fx-padding: 0.333333em 1em 0.416667em 1em;
     -fx-text-fill: -fx-text-base-color;
 }
-.button:hover {
+.button:hover,
+.toggle-button:hover,
+.radio-button:hover > .radio,
+.check-box:hover > .box,
+.menu-button:hover,
+.split-menu-button > .label:hover,
+.split-menu-button > .arrow-button:hover,
+.slider .thumb:hover,
+.scroll-bar > .thumb:hover,
+.scroll-bar > .increment-button:hover, 
+.scroll-bar > .decrement-button:hover,
+.choice-box:hover,
+.combo-box-base:hover{
     -fx-color: -fx-hover-base;
 }
-.button:armed {
+.button:armed,
+.toggle-button:armed,
+.radio-button:armed > .radio,
+.check-box:armed .box,
+.menu-button:armed,
+.split-menu-button:armed > .label,
+.split-menu-button > .arrow-button:pressed,
+.slider .thumb:pressed,
+.scroll-bar > .thumb:pressed,
+.scroll-bar > .increment-button:pressed, 
+.scroll-bar > .decrement-button:pressed,
+.choice-box:showing,
+.combo-box-base:showing {
     -fx-color: -fx-pressed-base;
 }
-.button:default {
-    -fx-base: -fx-accent;
-}
-.button:focused {
+.button:focused,
+.toggle-button:focused,
+.radio-button:focused > .radio,
+.check-box:focused > .box,
+.menu-button:focused,
+.choice-box:focused,
+.combo-box-base:focused {
+    /*-fx-color: -fx-focused-base; TODO do we want this? */
     -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
     -fx-background-insets: -2, -0.3, 1, 2;
     -fx-background-radius: 7, 6, 4, 3;
 }
-.button:disabled {
+
+/* ====   DISABLED THINGS   ================================================= */
+
+.button:disabled,
+.toggle-button:disabled,
+.radio-button:disabled,
+.check-box:disabled,
+.hyperlink:disabled,
+.menu-button:disabled,
+.split-menu-button:disabled,
+.slider:disabled,
+.scroll-pane:disabled,
+.progress-bar:disabled,
+.progress-indicator:disabled,
+.text-input:disabled,
+.choice-box:disabled,
+.combo-box-base:disabled,
+.list-view:disabled,
+.tree-view:disabled,
+.table-view:disabled,
+.tree-table-view:disabled {
     -fx-opacity: -fx-disabled-opacity;
 }
-.button:show-mnemonics .mnemonic-underline {
-    -fx-stroke: -fx-text-fill;
+
+/* ====   MNEMONIC THINGS   ================================================= */
+
+.button:show-mnemonics .mnemonic-underline,
+.toggle-button:show-mnemonics .mnemonic-underline,
+.radio-button:show-mnemonics .mnemonic-underline,
+.check-box:show-mnemonics .mnemonic-underline,
+.hyperlink:show-mnemonics > .mnemonic-underline,
+.split-menu-button:show-mnemonics > .mnemonic-underline,
+.menu-button:show-mnemonics > .mnemonic-underline {
+    -fx-stroke: -fx-text-base-color;
 } 
 
-/* ====   TOGGLE BUTTON   =================================================== */
+/* ====   MARKS   =========================================================== */
 
-.toggle-button {
-    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
-    -fx-background-insets: 0, 1, 2;
-    -fx-background-radius: 5, 4, 3;
-    -fx-padding: 0.333333em 1em 0.416667em 1em;
-    -fx-text-fill: -fx-text-base-color;
-}
+.radio-button:selected > .radio > .dot,
+.check-box:selected > .box > .mark {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color !important;
+    -fx-background-insets: 0 0 -1 0, 0;
+}
+
+/* ====   ARROWS   ========================================================== */
+
+.menu-button > .arrow-button > .arrow,
+.split-menu-button > .arrow-button > .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 0 0 -1 0, 0;
+    /*-fx-padding: 0.25em;  3 */
+    -fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z";
+}
+.menu-button:openvertically > .arrow-button > .arrow,
+.split-menu-button:openvertically > .arrow-button > .arrow {
+    -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+
+/* ====   BOX LIKE THINGS   ================================================= */
+
+.scroll-pane,
+.split-pane,
+.list-view,
+.tree-view,
+.table-view, 
+.tree-table-view {
+    -fx-background-color: -fx-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-padding: 1;
+}
+.scroll-pane:focused,
+.split-pane:focused,
+.list-view:focused,
+.tree-view:focused,
+.tree-table-view:focused {
+    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-background; 
+    -fx-background-insets: -2, -0.3, 1;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Label                                                                       *
+ *                                                                             *
+ ******************************************************************************/
+
+.label {
+    -fx-text-fill: -fx-text-background-color;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Button & ToogleButton                                                       *
+ *                                                                             *
+ ******************************************************************************/
+
+/* ====   DEFAULT   ========================================================= */
+
+.button:default {
+    -fx-base: -fx-accent;
+}
+
+/* ====   PILL BUTTONS   ==================================================== */
+
+.button.left-pill,
 .toggle-button.left-pill {
     -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3;
     -fx-background-insets: 0, 1 0 1 1, 2 1 2 2;
 }
+.button.center-pill,
 .toggle-button.center-pill {
     -fx-background-radius: 0;
     -fx-background-insets: 0, 1 0 1 1, 2 1 2 2;
 }
+.button.right-pill,
 .toggle-button.right-pill {
     -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
 }
+.button.left-pill:focused,
 .toggle-button.left-pill:focused {
     -fx-background-radius: 7 0 0 7, 6 0 0 6, 4 0 0 4, 3 0 0 3;
     -fx-background-insets: -2 0 -2 -2, -0.3 0 -0.3 -0.3, 1, 2;
 }
+.button.center-pill:focused,
 .toggle-button.center-pill:focused {
     -fx-background-radius: 0;
     -fx-background-insets: -2 0 -1 0, -0.3 0 -0.3 0, 1, 2;
 }
+.button.right-pill:focused,
 .toggle-button.right-pill:focused {
     -fx-background-radius: 0 7 7 0, 0 6 6 0, 0 4 4 0, 0 3 3 0;
     -fx-background-insets: -2 -2 -2 0, -0.3 -0.3 -0.3 0, 1, 2;
 }
-.toggle-button:focused {
-    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
-    -fx-background-insets: -2, -0.3, 1, 2;
-    -fx-background-radius: 7, 6, 4, 3;
-}
-.toggle-button:hover {
-    -fx-color: -fx-hover-base;
-}
-.toggle-button:armed {
-    -fx-color: -fx-pressed-base;
-}
+
+/* ====   SELECTED TOGGLE   ================================================= */
+
 .toggle-button:selected {
-/*    -fx-background-color:
-        linear-gradient(to bottom, derive(-fx-color,-90%) 0%, derive(-fx-color,-60%) 100%),
-        linear-gradient(to bottom, derive(-fx-color,-60%) 0%, derive(-fx-color,-35%) 50%, derive(-fx-color,-30%) 98%, derive(-fx-color,-50%) 100%),
-        linear-gradient(to right, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 90%, rgba(0,0,0,0.3) 100%);*/
-/*    -fx-background-color:
-        linear-gradient(to bottom, 5b656f 0%, derive(-fx-color,-60%) 100%),
-        #5b656f,
-        linear-gradient(to bottom, #646e78 0%, #77848d 100%);*/
     -fx-background-color: 
-        /*-fx-outer-border,*/ 
-        /*linear-gradient(to bottom, derive(-fx-color,75%), derive(-fx-color,2%)),*/ 
         linear-gradient(to bottom, derive(-fx-color,-65.1%) 0%, derive(-fx-color,-50.2%) 90%, derive(-fx-color,-45.1%) 100%), 
         linear-gradient(to bottom, derive(-fx-color,-52.8%) 0%, derive(-fx-color,-40.8%) 90%, derive(-fx-color,-35.7%) 100%),
         linear-gradient(to bottom, derive(-fx-color,-44.3%) 0%, derive(-fx-color,-41.7%) 2% ,derive(-fx-color,-33.6%) 98%, derive(-fx-color,-35.7%) 100%); 
-    -fx-background-insets: 0, 1, 2;
     /* TODO: -fx-text-fill should be derived */
     -fx-text-fill: -fx-light-text-color;
 }
 
 .toggle-button:selected:focused {
-/*    -fx-background-color:
-        -fx-focus-color,
-        linear-gradient(to bottom, derive(-fx-color,-90%) 0%, derive(-fx-color,-60%) 100%),
-        linear-gradient(to bottom, derive(-fx-color,-60%) 0%, derive(-fx-color,-35%) 50%, derive(-fx-color,-30%) 98%, derive(-fx-color,-50%) 100%),
-        linear-gradient(to right, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 90%, rgba(0,0,0,0.3) 100%);*/
     -fx-background-color: 
         -fx-faint-focus-color, -fx-focus-color, 
         linear-gradient(to bottom, derive(-fx-color,-52.8%) 0%, derive(-fx-color,-40.8%) 90%, derive(-fx-color,-35.7%) 100%),
         linear-gradient(to bottom, derive(-fx-color,-44.3%) 0%, derive(-fx-color,-41.7%) 2% ,derive(-fx-color,-33.6%) 98%, derive(-fx-color,-35.7%) 100%); 
-    -fx-background-insets: -2, -0.3, 1, 2;
-    -fx-background-radius: 7, 6, 4, 3;
-    /*-fx-background-insets: -1.4, 0, 1, 1;*/
-}
-.toggle-button:selected .text {
+}
+.toggle-button:selected > .text {
     -fx-effect: dropshadow(one-pass-box,derive(-fx-color,-90%),1,0,0,1);
-} 
-.toggle-button:disabled {
-    -fx-opacity: -fx-disabled-opacity;
-}
-.toggle-button:show-mnemonics .mnemonic-underline {
-    -fx-stroke: -fx-text-fill;
-} 
+}
 
 /*******************************************************************************
  *                                                                             *
@@ -484,51 +540,16 @@
     -fx-label-padding: 0.0em 0.0em 0.0em 0.416667em; /* 0 0 0 5 */
     -fx-text-fill: -fx-text-background-color;
 }
-
-.radio-button:focused {
-    -fx-color: -fx-focused-base;
-}
-
-.radio-button .radio  {
-   -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
-   -fx-background-insets: 0,  1,  2;
+.radio-button > .radio  {
    -fx-background-radius: 1.0em; /* large value to make sure this remains circular */
    -fx-padding: 0.333333em; /* 4 -- padding from outside edge to the inner black dot */
 }
-
-.radio-button:focused .radio {
-    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
-    -fx-background-radius: 1.0em; /* large value to make sure this remains circular */
-    -fx-background-insets: -2, -0.3, 1, 2;
-}
-
-.radio-button:hover .radio {
-    -fx-color: -fx-hover-base;
-}
-.radio-button:armed .radio {
-    -fx-color: -fx-pressed-base;
-}
-
-.radio-button .dot {
+.radio-button > .radio > .dot {
    -fx-background-color: transparent;
-   -fx-background-insets: 0;
    -fx-background-radius: 1.0em; /* large value to make sure this remains circular */
    -fx-padding: 0.25em; /* 3 -- radius of the inner black dot when selected */
 }
 
-.radio-button:selected .dot {
-   -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-   -fx-background-insets: 0 0 -1 0, 0;
-}
-
-.radio-button:disabled {
-    -fx-opacity: -fx-disabled-opacity;
-}
-
-.radio-button:show-mnemonics .mnemonic-underline {
-    -fx-stroke: -fx-text-fill;
-} 
-
 /*******************************************************************************
  *                                                                             *
  * CheckBox                                                                    *
@@ -539,89 +560,141 @@
     -fx-label-padding: 0.0em 0.0em 0.0em 0.416667em; /* 0 0 0 5 */
     -fx-text-fill: -fx-text-background-color;
 }
-
-.check-box:focused {
-    -fx-color: -fx-focused-base;
-}
-
-.check-box .box {
-    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
-    -fx-background-insets: 0, 1, 2;
+.check-box > .box {
     -fx-background-radius: 3, 2, 1;
-    /*-fx-padding: 0.25em;  3 -- padding from the outside edge to the mark */
     -fx-padding: -2 0 3 3;
 }
-
-.check-box:focused .box {
-    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
-    -fx-background-insets: -2, -0.3, 1, 2;
+.check-box:focused > .box {
     -fx-background-radius: 3.4, 3, 2, 1;
 }
-
-.check-box:hover .box {
-    -fx-color: -fx-hover-base;
-}
-
-.check-box:armed .box {
-    -fx-color: -fx-pressed-base;
-}
-
-.check-box .mark {
+.check-box > .box > .mark {
     -fx-background-color: transparent;
-    -fx-background-insets: 1 0 -1 0, 0;
-    /*-fx-padding: 0.333333em;  4 -- this is half the size of the mark */
     -fx-padding: 8 7 8 7; /* 4 -- this is half the size of the mark */
-    /*-fx-shape: "M0,4H2L3,6L6,0H8L4,8H2Z";*/
     -fx-shape: "M-0.25,6.083c0.843-0.758,4.583,4.833,5.75,4.833S14.5-1.5,15.917-0.917c1.292,0.532-8.75,17.083-10.5,17.083C3,16.167-1.083,6.833-0.25,6.083z";
 }
-
-.check-box:indeterminate .box {
+.check-box:indeterminate > .box {
     -fx-padding: 7 3 7 3;
 }
-.check-box:indeterminate .mark {
+.check-box:indeterminate  > .box > .mark {
     -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
     -fx-shape: "M0,0H8V2H0Z";
     -fx-padding: 2 6 1 5;
-    /*-fx-scale-shape: false;*/
 }
 
-.check-box:selected .mark {
-    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-}
+/*******************************************************************************
+ *                                                                             *
+ * Hyperlink                                                                   *
+ *                                                                             *
+ ******************************************************************************/
 
-.check-box:disabled {
-    -fx-opacity: -fx-disabled-opacity;
-}
-
-.check-box:show-mnemonics .mnemonic-underline {
+.hyperlink {
+    -fx-padding: 0.166667em; /* 2 */
+    -fx-cursor: hand;
+    -fx-content-display: LEFT;
+    -fx-text-fill: -fx-text-background-color;
+    -fx-border-color: transparent;
+    -fx-border-width: 1px;
+}
+.hyperlink:visited {
+    -fx-text-fill: -fx-accent;
+}
+.hyperlink:focused {
+    -fx-border-color: -fx-focus-color;
+    -fx-border-style: dotted;
+    -fx-border-width: 1px;
+}
+.hyperlink:hover {
+    -fx-underline: true;
+}
+.hyperlink:show-mnemonics > .mnemonic-underline {
     -fx-stroke: -fx-text-fill;
 } 
 
+/*******************************************************************************
+ *                                                                             *
+ * MenuButton                                                                  *
+ *                                                                             *
+ ******************************************************************************/
+
+.menu-button {
+    -fx-padding: 0;
+}
+.menu-button > .label {
+    /* The MenuButton skin uses an inner Label part */
+    -fx-padding: 0.166667em 1.5em 0.25em 0.833333em; /* 2 18 3 10 */
+}
+.menu-button > .arrow-button {
+    -fx-background-insets: 0;
+    -fx-background-radius: 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.0em; /* 6 5 6 0 */
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * SplitMenuButton                                                             *
+ *                                                                             *
+ ******************************************************************************/
+.split-menu-button {
+    -fx-padding: 0.0em; /* 0 */
+    -fx-text-fill: -fx-text-base-color;
+}
+.split-menu-button:focused {
+    -fx-background-color: -fx-focus-color;
+    -fx-background-insets: -2;
+    -fx-background-radius: 7;
+}
+/* The SplitMenuButton skin uses an inner Label part */
+.split-menu-button > .label {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
+    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2;
+    -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3;
+    -fx-padding: 0.166667em 1.5em 0.25em 0.833333em; /* 2 18 3 10 */
+}
+
+.split-menu-button > .arrow-button {
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
+}
+
+.split-menu-button > .arrow-button > .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.25em;
+    -fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z";
+}
+.split-menu-button:openvertically > .arrow-button > .arrow {
+    -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em;
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+
 /* ====   TOOLBAR   ========================================================= */
 
 .tool-bar:vertical {
     -fx-background: derive(-fx-base,-20%);
     -fx-background-color:
-        linear-gradient(to right, derive(-fx-base,-30%), derive(-fx-base,-60%)),
-        linear-gradient(to right, derive(-fx-base,65%) 2%, derive(-fx-base,-20%) 95%);
-    -fx-background-insets: 0, 0 1 0 1;
+        linear-gradient(to right, derive(-fx-base,0%) 0%, derive(-fx-base,10%) 50%, derive(-fx-base,0%) 100%);
+    -fx-background-insets: 0;
     -fx-background-radius: 0 ;
     -fx-padding: 0.833em 0.416667em 0.833em 0.416667em; /* 10 5 10 5 */
     -fx-spacing: 0.333em; /* 4 */
     -fx-alignment: TOP_LEFT;
 }
 .tool-bar:horizontal {
-    /*-fx-background: derive(-fx-base,-30%);*/
     -fx-background-color:
-        linear-gradient(to bottom, derive(-fx-base,75%) 0%, derive(-fx-base,-26.0%) 90%, derive(-fx-base,-7.0%) 93%, -fx-background 100%),
+        linear-gradient(to bottom, derive(-fx-base,75%) 0%, derive(-fx-base,-26.0%) 90%),
         linear-gradient(to bottom, derive(-fx-base,46.9%) 2%, derive(-fx-base,-2.1%) 95%);
-    -fx-background-insets: 0 0 0 0, 1 0 4 0;
+    -fx-background-insets: 0 0 0 0, 1 0 0 0;
     -fx-background-radius: 0, 0 ;
-    -fx-padding: 0.416667em 0.833em 8px 0.833em; /* 5 10 5 10 */
+    -fx-padding: 0.416667em 0.833em 0.416667em 0.833em; /* 5 10 5 10 */
     -fx-spacing: 0.333em; /* 4 */
     -fx-alignment: CENTER_LEFT;
 }
-
+.tool-bar:horizontal > .container > .separator {
+    -fx-orientation: vertical;
+}
+.tool-bar:vertical > .container > .separator {
+    -fx-orientation: horizontal;    
+}
 /*
 .tool-bar .separator:vertical .line {
     -fx-border-style: solid;
@@ -666,187 +739,120 @@
     -fx-background-insets: -1.4, 0, 1, 2;
     -fx-background-radius: 1.0em; /* makes sure this remains circular */
 }
-
-.slider .thumb:hover {
-    -fx-color: -fx-hover-base;
-}
-
-.slider .thumb:pressed {
-    -fx-color: -fx-pressed-base;
-}
-
-.slider .track {
-    -fx-background-color:
-        derive(-fx-color,-22%),
-        linear-gradient(to bottom, derive(-fx-color,-15.5%), derive(-fx-color,34%) 30%, derive(-fx-color,68%));
-    -fx-background-insets: 0, 1;
-    -fx-background-radius: 2.5, 1.5;
-    -fx-padding: 0.208333em; /* 2.5 */
-}
-
-.slider:vertical .track {
-    -fx-background-color:
-        derive(-fx-color,-22%),
-        linear-gradient(to right, derive(-fx-color,-15.5%), derive(-fx-color,34%) 30%, derive(-fx-color,68%));
-    -fx-background-insets: 0, 1;
-}
-
+.slider .track, .slider:vertical .track {
+    -fx-background-color:  derive(-fx-box-border, 20%), derive(-fx-background, -5%), -fx-background;
+    -fx-background-insets: 0, 1, 2 1 1 1;
+    -fx-background-radius: 2.5, 1.5, 1.5;
+    -fx-padding: 2;
+}
 .slider .axis {
     -fx-tick-mark-stroke: ladder(-fx-background, derive(-fx-background,30%) 40%, derive(-fx-background,-30%) 41%);
     -fx-tick-label-font: 0.833333em System; 
     -fx-tick-label-fill: -fx-text-background-color;
 }
 
-.slider:disabled {
-    -fx-opacity: -fx-disabled-opacity;
-}
-
 /*******************************************************************************
  *                                                                             *
  * ScrollBar                                                                   *
  *                                                                             *
  ******************************************************************************/
-
 .scroll-bar:horizontal {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%) 100%);
-    -fx-background-insets: 0, 1;
-}
-
-.scroll-bar:horizontal:focused {
-    -fx-background-color:
-        -fx-focus-color,
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%) 100%);
-    -fx-background-insets: -1.4, 0, 1;
-}
-
+    -fx-background-color: linear-gradient(to bottom, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%));
+}
 .scroll-bar:vertical {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to top, derive(-fx-color,30%) 5%, derive(-fx-color,-17%) 100%);
-    -fx-background-insets: 0, 1;
-}
-
-.scroll-bar:vertical:focused {
-    -fx-background-color:
-        -fx-focus-color,
-        -fx-box-border,
-        linear-gradient(to top, derive(-fx-color,30%) 5%, derive(-fx-color,-17%) 100%);
-    -fx-background-insets: -1.4, 0, 1;
-}
-
-.scroll-bar:horizontal > .thumb {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-color,95%), derive(-fx-color,10%)),
-        linear-gradient(to bottom, derive(-fx-color,38%), derive(-fx-color,-16%));
-    -fx-background-insets: 0, 1, 2;
-    -fx-background-radius: 0.5em; /* makes sure this remains circular */
-}
-
-.scroll-bar:vertical > .thumb {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to right, derive(-fx-color,95%), derive(-fx-color,10%)),
-        linear-gradient(to right, derive(-fx-color,38%), derive(-fx-color,-16%));
-    -fx-background-insets: 0, 1, 2;
-    -fx-background-radius: 0.5em; /* makes sure this remains circular */
-}
-
-.scroll-bar:focused > .thumb {
-    -fx-color: -fx-focused-base;
-}
-
-.scroll-bar > .thumb:hover {
-    -fx-color: -fx-hover-base;
-}
-
-.scroll-bar .thumb:pressed {
-    -fx-color: -fx-pressed-base;
-}
-
-
-.scroll-bar:horizontal > .track {
-     -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-    -fx-background-insets:  0, 1;
-    -fx-background-radius: 0.5em; /* makes sure this remains circular */
-}
-.scroll-bar:horizontal > .track-background {
-     -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to top, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-    -fx-background-insets:  0, 1;
-}
-
-.scroll-bar:vertical > .track {
-     -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to right, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-    -fx-background-insets:  0, 1;
-    -fx-background-radius: 0.5em; /* makes sure this remains circular */
-}
-
-.scroll-bar:vertical > .track-background {
-     -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to left, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-    -fx-background-insets:  0, 1;
-}
-
-.scroll-bar > .increment-button {
-    -fx-background-color: transparent;
-    -fx-background-insets:  0;
-    -fx-padding: 0.25em; /* 3 */
-}
-
-.scroll-bar > .decrement-button {
-    -fx-background-color: transparent;
-    -fx-background-insets:  0;
-    -fx-padding: 0.25em; /* 3 */
-}
-
-.scroll-bar:horizontal > .increment-button > .increment-arrow {
-    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-    -fx-background-insets: 1 0 -1 0, 0;
-    -fx-padding: 0.5em 0.333333em 0.0em 0.0em; /* 6 4 0 0 */
-    -fx-shape: "M 4 0 L 0 -3 L 0 3 z";
-}
-
-.scroll-bar:vertical > .increment-button > .increment-arrow {
-    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-    -fx-background-insets: 1 0 -1 0, 0;
-    -fx-padding: 0.333333em 0.5em 0.0em 0.0em; /* 4 6 0 0 */
-    -fx-shape: "M -3 0 L 0 4 L 3 0 z";
-}
-
-.scroll-bar:horizontal > .decrement-button > .decrement-arrow {
-    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-    -fx-background-insets: 1 0 -1 0, 0;
-    -fx-padding: 0.5em 0.333333em 0.0em 0.0em; /* 6 4 0 0 */
-    -fx-shape: "M 0 0 L 4 -3 L 4 3 z";
-}
-
-.scroll-bar:vertical > .decrement-button > .decrement-arrow {
-    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-    -fx-background-insets: 1 0 -1 0, 0;
-    -fx-padding: 0.333333em 0.5em 0.0em 0.0em; /* 4 6 0 0 */
-    -fx-shape: "M -3 0 L 0 -4 L 3 0 z";
-}
-
+    -fx-background-color: linear-gradient(to right, derive(-fx-base,-3%), derive(-fx-base,5%) 50%, derive(-fx-base,-3%));
+}
 .scroll-bar:disabled {
     -fx-opacity: -fx-disabled-opacity;
 }
+.scroll-bar > .thumb {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
+    -fx-background-insets: 1, 2, 3;
+    -fx-background-radius: 5, 4, 3;
+}
+.scroll-bar:vertical > .thumb {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color-to-right; 
+}
+.scroll-bar > .increment-button, 
+.scroll-bar > .decrement-button {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
+    -fx-background-insets: 0, 1, 2;
+    -fx-color: transparent;
+    -fx-padding: 3px;
+}
+.scroll-bar > .increment-button > .increment-arrow,
+.scroll-bar > .decrement-button > .decrement-arrow {
+    -fx-background-color: derive(-fx-base,-35%);
+}
+.scroll-bar > .increment-button:hover > .increment-arrow,
+.scroll-bar > .decrement-button:hover > .decrement-arrow {
+    -fx-background-color: derive(-fx-base,-40%);
+}
+.scroll-bar > .increment-button:pressed > .increment-arrow,
+.scroll-bar > .decrement-button:pressed > .decrement-arrow {
+    -fx-background-color: derive(-fx-base,-45%);
+}
+.scroll-bar:horizontal > .increment-button > .increment-arrow {
+    -fx-padding: 7 5 0 0;
+    -fx-shape: "M0.315,1.457l1.414-1.414L5.686,4L1.729,7.957L0.315,6.543L2.857,4L0.315,1.457z";
+}
+.scroll-bar:vertical > .increment-button > .increment-arrow {
+    -fx-padding: 5 7 0 0 ;
+    -fx-shape: "M6.543,0.315l1.414,1.414L4,5.686L0.043,1.729l1.414-1.414L4,2.858L6.543,0.315z";
+}
+.scroll-bar:horizontal > .decrement-button > .decrement-arrow {
+    -fx-padding: 7 5 0 0;
+    -fx-shape: "M5.686,6.543L4.271,7.957L0.314,4l3.957-3.957l1.414,1.414L3.143,4L5.686,6.543z";
+}
+.scroll-bar:vertical > .decrement-button > .decrement-arrow {
+    -fx-padding: 5 7 0 0;
+    -fx-shape: "M1.457,5.563L0.042,4.149L4,0.193l3.957,3.957L6.543,5.563L4,3.021L1.457,5.563z";
+}
 
-/* The opacity of the parent is applied to the children.  So we make the
- * opacity 1.0 here to avoid double translucency.
- */
-/*:disabled > * > .scroll-bar {
-    -fx-opacity: 1.0;
-}*/
+/*******************************************************************************
+ *                                                                             *
+ * ScrollPane                                                                  *
+ *                                                                             *
+ ******************************************************************************/
+
+.scroll-pane > .scroll-bar:horizontal {
+    -fx-background-insets: 0 1 1 1;
+    -fx-padding: 0 1 1 1;
+}
+.scroll-pane > .scroll-bar:horizontal > .increment-button, 
+.scroll-pane > .scroll-bar:horizontal > .decrement-button {
+    -fx-padding: 3 3 2 3;
+}
+.scroll-pane > .scroll-bar:vertical > .increment-button, 
+.scroll-pane > .scroll-bar:vertical > .decrement-button {
+    -fx-padding: 3 2 3 3;
+}
+.scroll-pane > .scroll-bar:vertical {
+    -fx-background-insets: 1 1 1 0;
+    -fx-padding: 1 1 1 0;
+}
+.scroll-pane > .corner {
+    -fx-background-color: derive(-fx-base,-1%);
+    -fx-background-insets: 0 1 1 0;
+}
+/* new styleclass for edge to edge scrollpanes that don't want to draw a border */
+.scroll-pane.edge-to-edge,
+.tab-pane > * > .scroll-pane {
+    -fx-background-color: -fx-background;
+    -fx-background-insets: 0;
+    -fx-padding: 0;
+}
+.scroll-pane.edge-to-edge > .scroll-bar,
+.tab-pane > * > .scroll-pane > .scroll-bar {
+    -fx-background-insets: 0;
+    -fx-padding: 0;
+}
+.scroll-pane.edge-to-edge > .scroll-bar > .increment-button, 
+.scroll-pane.edge-to-edge > .scroll-bar > .decrement-button,
+.tab-pane > * > .scroll-pane > .scroll-bar > .increment-button, 
+.tab-pane > * > .scroll-pane > .scroll-bar > .decrement-button {
+    -fx-padding: 3px;
+}
 
 /*******************************************************************************
  *                                                                             *
@@ -858,13 +864,11 @@
     -fx-border-style: segments(0.166667em, 0.166667em);
     -fx-border-width: 0.083333em; /* 1 */
 }
-
 .separator:horizontal .line {
     -fx-background-color: null;
     -fx-padding: 0.083333em 0.0em 0.0em 0.0em; /* 1 0 0 0 */
     -fx-border-color: derive(-fx-background,-20%) transparent transparent transparent;
 }
-
 .separator:vertical .line {
     -fx-background-color: null;
     -fx-padding: 0.0em 0.083333em 0.0em 0.0em; /* 0 1 0 0 */
@@ -878,36 +882,2048 @@
  ******************************************************************************/
 
 .progress-bar {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%));
-    -fx-background-insets: 0, 1;
     -fx-indeterminate-bar-length: 60;
     -fx-indeterminate-bar-escape: true;
     -fx-indeterminate-bar-flip: true;
     -fx-indeterminate-bar-animation-time: 2;
 }
-
 .progress-bar > .bar {
-    -fx-background-color:
-        -fx-box-border,
-        linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
-        linear-gradient(to bottom, derive(-fx-accent,38%), -fx-accent);
-    -fx-background-insets: 0, 1, 2;
+    -fx-background-color: -fx-box-border,-fx-accent;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 0.416667em, 0.416667em;
     -fx-padding: 0.416667em; /* 5 */
 }
-
 .progress-bar:indeterminate > .bar {
     -fx-background-color: linear-gradient(to left, transparent, -fx-accent);
 }
-
 .progress-bar > .track {
      -fx-background-color:
         -fx-box-border,
         linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
     -fx-background-insets:  0, 1;
+    -fx-background-radius: 0.416667em, 0.416667em;
 }
 
-.progress-bar:disabled {
+/*******************************************************************************
+ *                                                                             *
+ * ProgressIndicator                                                           *
+ *                                                                             *
+ ******************************************************************************/
+.progress-indicator {
+    -fx-indeterminate-segment-count: 12;
+    -fx-spin-enabled: true;
+}
+.progress-indicator > .determinate-indicator > .indicator {
+    -fx-background-color: -fx-box-border, derive( -fx-background, -10%);
+    -fx-background-insets: 0, 1;
+    -fx-padding: 1;
+}
+.progress-indicator > .determinate-indicator > .progress {
+    -fx-background-color: -fx-accent;
+    -fx-background-insets: 0;
+    -fx-padding: 1em; /* 9 */
+}
+/* TODO: scaling the shape seems to make it disappear */
+.progress-indicator > .determinate-indicator > .tick {
+    -fx-background-color: white;
+    -fx-background-insets: 0;
+    -fx-padding: 0.416667em; /* 5 */
+    -fx-shape: "M-0.25,6.083c0.843-0.758,4.583,4.833,5.75,4.833S14.5-1.5,15.917-0.917c1.292,0.532-8.75,17.083-10.5,17.083C3,16.167-1.083,6.833-0.25,6.083z";
+    -fx-scale-shape: false;
+}
+.progress-indicator:indeterminate > .spinner {
+    -fx-padding: 0.833333em; /* 10 */
+}
+.progress-indicator > .percentage {
+    -fx-font-size: 0.916667em; /* 11pt - 1 less than the default font */
+    -fx-fill: -fx-text-background-color;
+}
+.progress-indicator:indeterminate .segment {
+    -fx-background-color: -fx-accent;
+}
+.progress-indicator:indeterminate .segment0 {
+    -fx-shape:"M10,0C9.998,0,9.995,0,9.992,0C9.991,0,9.991,0,9.99,0C9.988,0,9.986,0,9.985,0S9.982,0,9.981,0S9.979,0,9.978,0S9.975,0,9.974,0S9.972,0,9.971,0C9.969,0,9.968,0,9.966,0H9.965c-0.007,0-0.014,0-0.02,0C9.944,0,9.944,0,9.944,0C9.941,0,9.939,0,9.937,0c-0.77,0.007-1.389,0.634-1.384,1.404C8.557,2.176,9.185,2.8,9.956,2.8c0.001,0,0.003,0,0.004,0H10c0.773-0.002,1.4-0.63,1.4-1.404c0-0.77-0.622-1.393-1.392-1.396C10.006,0,10.003,0,10,0L10,0z";
+}
+.progress-indicator:indeterminate .segment1 {
+    -fx-shape:"M5.688,1.156c-0.236,0-0.476,0.06-0.696,0.187C4.98,1.349,4.969,1.356,4.958,1.363c0,0-0.001,0-0.001,0C4.955,1.364,4.954,1.365,4.952,1.366c-0.001,0-0.002,0.001-0.004,0.002c0,0,0,0-0.001,0C4.944,1.371,4.94,1.373,4.936,1.375c0,0,0,0-0.001,0C4.933,1.377,4.931,1.378,4.929,1.38C4.267,1.772,4.046,2.624,4.438,3.288c0.261,0.444,0.73,0.692,1.212,0.692c0.24,0,0.484-0.062,0.706-0.192l0.034-0.02C7.058,3.378,7.283,2.52,6.896,1.851C6.636,1.405,6.168,1.156,5.688,1.156L5.688,1.156z";
+}
+.progress-indicator:indeterminate .segment2 {
+    -fx-shape:"M2.534,4.326c-0.482,0-0.951,0.25-1.209,0.697C1.323,5.027,1.321,5.029,1.32,5.031l0,0C1.319,5.033,1.318,5.034,1.317,5.036S1.315,5.039,1.314,5.04c0,0.001,0,0.002-0.001,0.002C1.312,5.044,1.311,5.046,1.31,5.048c0,0,0,0,0,0.001C1.309,5.051,1.308,5.053,1.307,5.055C1.302,5.063,1.297,5.071,1.292,5.079l0,0C1.291,5.082,1.29,5.084,1.288,5.087c-0.376,0.67-0.141,1.519,0.529,1.898c0.218,0.123,0.456,0.182,0.69,0.182c0.488,0,0.963-0.255,1.222-0.708l0.02-0.035c0.383-0.671,0.149-1.527-0.521-1.912C3.008,4.386,2.769,4.326,2.534,4.326L2.534,4.326z";
+}
+.progress-indicator:indeterminate .segment3 {
+    -fx-shape:"M1.396,8.648c-0.002,0-0.005,0-0.008,0C0.619,8.652-0.001,9.278,0,10.047c0,0.002,0,0.006,0,0.008l0,0c0,0.019,0,0.037,0,0.056c0,0.001,0,0.002,0,0.003s0,0.003,0,0.004c0.01,0.765,0.632,1.378,1.396,1.378c0.005,0,0.01,0,0.015,0c0.773-0.009,1.395-0.642,1.389-1.415v-0.04C2.794,9.27,2.166,8.648,1.396,8.648L1.396,8.648z";
+}
+.progress-indicator:indeterminate .segment4 {
+    -fx-shape:"M2.579,12.955c-0.242,0-0.487,0.062-0.71,0.194c-0.664,0.391-0.885,1.242-0.499,1.906c0.013,0.021,0.025,0.043,0.038,0.063c0.262,0.436,0.724,0.678,1.197,0.678c0.243,0,0.49-0.063,0.714-0.197c0.665-0.396,0.883-1.257,0.489-1.922l-0.02-0.034C3.526,13.201,3.059,12.955,2.579,12.955L2.579,12.955z";
+}
+.progress-indicator:indeterminate .segment5 {
+    -fx-shape:"M5.772,16.09c-0.489,0-0.965,0.257-1.223,0.712c-0.38,0.671-0.146,1.52,0.523,1.901c0.002,0.001,0.004,0.002,0.007,0.004h0c0.004,0.002,0.008,0.004,0.012,0.007c0,0,0,0,0.001,0c0.001,0.001,0.002,0.002,0.004,0.002c0.001,0.001,0.003,0.002,0.004,0.003c0,0,0.001,0,0.001,0.001c0.012,0.006,0.023,0.013,0.035,0.019c0.214,0.119,0.446,0.176,0.675,0.176c0.489,0,0.963-0.258,1.22-0.716c0.377-0.675,0.137-1.529-0.537-1.908l-0.035-0.02C6.242,16.149,6.006,16.09,5.772,16.09L5.772,16.09z";
+}
+.progress-indicator:indeterminate .segment6 {
+    -fx-shape:"M10.14,17.198c-0.006,0-0.013,0-0.02,0h-0.039c-0.773,0.011-1.394,0.646-1.385,1.419c0.008,0.767,0.631,1.382,1.396,1.382c0.003,0,0.006,0,0.009-0.001c0.024,0,0.051,0,0.075-0.001c0.769-0.016,1.38-0.648,1.367-1.418C11.53,17.813,10.904,17.198,10.14,17.198L10.14,17.198z";
+}
+.progress-indicator:indeterminate .segment7 {
+    -fx-shape:"M14.433,15.97c-0.245,0-0.494,0.064-0.72,0.2l-0.034,0.021c-0.663,0.397-0.88,1.258-0.483,1.922c0.261,0.439,0.725,0.683,1.2,0.683c0.24,0,0.484-0.062,0.707-0.194c0.022-0.013,0.044-0.025,0.065-0.039c0.656-0.399,0.866-1.254,0.469-1.913C15.373,16.212,14.909,15.97,14.433,15.97L14.433,15.97z";
+}
+.progress-indicator:indeterminate .segment8 {
+    -fx-shape:"M17.539,12.748c-0.493,0-0.973,0.261-1.229,0.723l-0.02,0.034c-0.376,0.676-0.133,1.53,0.542,1.907c0.216,0.121,0.45,0.178,0.681,0.178c0.487,0,0.96-0.256,1.217-0.71c0.003-0.006,0.007-0.012,0.01-0.019c0.007-0.013,0.015-0.025,0.021-0.038l0,0c0.002-0.003,0.003-0.005,0.004-0.008c0.369-0.675,0.124-1.521-0.55-1.893C18.001,12.805,17.769,12.748,17.539,12.748L17.539,12.748z";
+}
+.progress-indicator:indeterminate .segment9 {
+    -fx-shape:"M18.603,8.408c-0.011,0-0.021,0-0.031,0c-0.773,0.018-1.388,0.657-1.373,1.431l0.001,0.04c0.015,0.765,0.641,1.377,1.403,1.377c0.008,0,0.016,0,0.023,0c0.77-0.013,1.383-0.646,1.373-1.414c0-0.003,0-0.006,0-0.009l0,0c-0.001-0.019-0.001-0.037-0.001-0.055c0-0.001,0-0.001-0.001-0.002c0-0.002,0-0.004,0-0.006C19.979,9.012,19.358,8.408,18.603,8.408L18.603,8.408z";
+}
+.progress-indicator:indeterminate .segment10 {
+    -fx-shape:"M17.345,4.121c-0.248,0-0.5,0.066-0.728,0.205c-0.659,0.403-0.869,1.266-0.468,1.927l0.021,0.034c0.265,0.435,0.728,0.675,1.202,0.675c0.247,0,0.497-0.065,0.724-0.202c0.659-0.397,0.871-1.252,0.477-1.912c-0.007-0.011-0.013-0.021-0.02-0.032c-0.001-0.002-0.002-0.003-0.002-0.004c-0.001,0-0.001-0.001-0.001-0.002c-0.004-0.005-0.008-0.011-0.011-0.017c0-0.001,0-0.001-0.001-0.001c-0.001-0.002-0.002-0.004-0.004-0.007C18.271,4.358,17.813,4.121,17.345,4.121L17.345,4.121z";
+}
+.progress-indicator:indeterminate .segment11 {
+    -fx-shape:"M14.104,1.039c-0.494,0-0.974,0.264-1.227,0.729c-0.37,0.679-0.12,1.531,0.559,1.903l0.034,0.019c0.214,0.117,0.445,0.173,0.673,0.173c0.495,0,0.976-0.262,1.231-0.726c0.371-0.674,0.129-1.519-0.542-1.894c-0.012-0.006-0.024-0.013-0.036-0.02c-0.007-0.004-0.014-0.008-0.021-0.012c-0.003-0.001-0.006-0.003-0.009-0.005C14.556,1.094,14.329,1.039,14.104,1.039L14.104,1.039z";
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Text COMMON                                                                 *
+ *                                                                             *
+ ******************************************************************************/
+
+.text-input {
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-highlight-fill: derive(-fx-control-inner-background,-20%);
+    -fx-highlight-text-fill: -fx-text-inner-color;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 2, 2;
+    -fx-cursor: text;
+}
+.text-input:focused {
+    -fx-highlight-fill: -fx-accent;
+    -fx-highlight-text-fill: white;
+    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-control-inner-background; 
+    -fx-background-insets: -2, -0.3, 1;
+    -fx-background-radius: 6, 3.4, 2, 2;
+    -fx-prompt-text-fill: transparent;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TextField                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.text-field {
+    -fx-padding: 3 5 3 5;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TextArea                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.text-area {
+    -fx-padding: 0;
+    -fx-cursor: default;
+}
+.text-area > .scroll-pane {
+    -fx-background-color: transparent;
+}
+.text-area .content {
+    -fx-padding: 3 5 3 5; 
+    -fx-cursor: text;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * PopupMenu                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.context-menu {
+    -fx-background-color:
+        -fx-box-border,
+        -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-padding: 0.333333em 0.083333em 0.333333em 0.083333em; /* 4 1 8 1 */
+    /*-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 8, 0.0 , 0 , 8 );*/
+}
+.context-menu > .separator {
+    -fx-padding: 0.0em 0.333333em 0.0em 0.333333em; /* 0 4 0 4 */
+}
+.context-menu > .scroll-arrow {
+    -fx-padding: 0.416667em 0.416667em 0.416667em 0.416667em; /* 5 */
+    -fx-background-color: transparent;
+}
+.context-menu > .scroll-arrow:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.context-menu:show-mnemonics > .mnemonic-underline {
+    -fx-stroke: -fx-text-fill;
+} 
+
+/*******************************************************************************
+ *                                                                             *
+ * Menu                                                                        *
+ *                                                                             *
+ ******************************************************************************/
+
+.menu {
+    -fx-background-color: transparent;
+    -fx-padding: 0.333333em 0.666667em 0.333333em 0.666667em; /* 4 8 4 8 */
+}
+.menu:disabled {
     -fx-opacity: -fx-disabled-opacity;
+}
+.menu:show-mnemonics > .mnemonic-underline {
+    -fx-stroke: -fx-text-fill;
+}
+/* This hides the down arrow that would show on a menu placed in a menubar */
+.menu-bar > .container > .menu > .arrow-button > .arrow {
+    -fx-padding: 0;
+    -fx-background-color: transparent;
+    -fx-shape: null;
+}
+.menu-bar > .container > .menu > .arrow-button {
+    -fx-padding: 0;
+}
+.menu > .arrow {
+    -fx-background-color: -fx-mark-color;
+    -fx-shape: "M0,-4L4,0L0,4Z";
+    -fx-scale-shape: false;
+}
+.menu:focused:showing > .arrow, .menu:hover:showing > .arrow, .menu:focused > .arrow, .menu:showing > .arrow {
+    -fx-background-color: white;
+}
+.menu-up-arrow {
+    -fx-padding: 0.666667em 0.416667em 0.0em 0.416667em;  /* 8 5 0 5 */
+    -fx-background-color: derive(-fx-color,-2%);
+    -fx-shape: "M0 1 L1 1 L.5 0 Z";
+    -fx-effect: innershadow( two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 1 );
+}
+.menu-down-arrow {
+    -fx-background-color: derive(-fx-color,-2%);
+    -fx-padding: 0.666667em 0.416667em 0.0em 0.416667em;  /* 8 5 0 5 */
+    -fx-shape: "M0 0 L1 0 L.5 1 Z";
+    -fx-effect: innershadow( two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 1 );
+}
+
+
+/*******************************************************************************
+ *                                                                             *
+ * MenuBar                                                                     *
+ *                                                                             *
+ ******************************************************************************/
+
+/* Corresponding hex values for the color derivations used below are: *
+ * derive(-fx-base,-30%); #929292                                     *
+ * derive(-fx-base,-50%); #686868                                     *
+ * derive(-fx-base,-70%); #3e3e3e                                     */
+.menu-bar {
+    -fx-padding: 0.0em 0.666667em 0.0em 0.666667em; /* 0 8 0 8 */
+    -fx-spacing: 0.166667em; /* 2 */
+    -fx-base: derive(#d0d0d0,-70%);
+    -fx-background-color: linear-gradient(to bottom, derive(-fx-color,50%), derive(-fx-color,-30%)), -fx-body-color;
+    -fx-background-insets: 0, 1 0 1 0;
+    -fx-background-radius: 0, 0 ;
+}
+/* Show nothing for background of normal menu button in a menu bar */
+.menu-bar > .container > .menu-button {
+    -fx-background-radius: 0;
+    -fx-background-color: transparent;
+    -fx-background-insets: 0; 
+}
+/* Change padding of menu buttons when in menu bar */
+.menu-bar > .container > .menu-button > .label {
+    -fx-padding: 0.333em 0.5em 0.333em 0.5em; /* 4 6 4 6*/
+}
+.menu-bar > .container > .menu-button:hover, .menu-bar > .container > .menu-button:focused, .menu-bar > .container > .menu-button:showing {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.menu-bar > .container > .menu-button:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.menu-bar:show-mnemonics > .mnemonic-underline {
+    -fx-stroke: -fx-text-fill;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * MenuItem                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.menu-item {
+    -fx-background-color: transparent;
+    -fx-padding: 0.333333em 0.41777em 0.333333em 0.41777em;  /* 4 5 4 5 */
+}
+.menu-item > .left-container {
+    -fx-padding: 0.458em 0.791em 0.458em 0.458em;
+}
+.menu-item > .graphic-container {
+    -fx-padding: 0em 0.333em 0em 0em;
+}
+.menu-item >.label {
+    -fx-padding: 0em 0.5em 0em 0em;
+    -fx-text-fill: -fx-text-base-color;
+}
+.menu-item:disabled > .label {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.menu-item:focused {
+     -fx-background: -fx-accent;
+     -fx-background-color: -fx-selection-bar;
+     -fx-text-fill: -fx-selection-bar-text;
+}
+.menu-item:focused > .label {
+    -fx-text-fill: white;
+}
+.menu-item > .right-container {
+    -fx-padding: 0em 0em 0em 0.5em;
+}
+.menu-item:show-mnemonics > .mnemonic-underline {
+    -fx-stroke: -fx-text-fill;
+} 
+.radio-menu-item:checked > .left-container > .radio {
+    -fx-background-color: -fx-mark-color;
+    -fx-shape: "M0,5H2L4,8L8,0H10L5,10H3Z";
+    -fx-scale-shape: false;
+}
+.radio-menu-item:focused:checked > .left-container > .radio {
+    -fx-background-color: white;
+}
+.check-menu-item:checked > .left-container > .check {
+    -fx-background-color: -fx-mark-color;
+    -fx-shape: "M0,5H2L4,8L8,0H10L5,10H3Z";
+    -fx-scale-shape: false;
+}
+.check-menu-item:focused:checked > .left-container > .check {
+    -fx-background-color: white;
+}
+.menu > .right-container > .arrow {
+    -fx-padding: 0.458em 0.167em 0.458em 0.167em; /* 4.5 2 4.5 2 */
+    -fx-background-color: -fx-mark-color;
+    -fx-shape: "M0,-4L4,0L0,4Z";
+    -fx-scale-shape: false;
+}
+.menu:selected > .right-container > .arrow {
+    -fx-background-color: white;
+}
+.menu-item:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * ChoiceBox                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.choice-box {
+    -fx-padding: 0.0em 0.5em 0.0em 0.0em; /* 0 6 0 0 */
+    -fx-alignment: CENTER;
+    -fx-content-display: LEFT;
+}
+.choice-box > .label {
+    -fx-padding: 0.166667em 0.333333em 0.25em 0.5em; /* 2 4 3 6 */
+    -fx-text-fill: -fx-text-base-color;
+}
+
+.choice-box > .open-button {
+    -fx-background-color: null;
+    -fx-padding: 0.083333em 0.0em 0.0em 0.666667em; /* 1 0 0 8 */
+}
+.choice-box > .open-button > .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    /* padding determines the size of the arrow;
+       this should match the design size in the SVG */
+    -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 3.5 2 3.5 */
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+.choice-box > .context-menu {
+    -fx-background-radius: 6, 5, 4;
+}
+
+/*.choice-box > .context-menu > .menu-item {
+    -fx-accelerator-gutter: 0;
+}*/
+
+/* TODO: need to use the ID here.  For some reason, the other form does not
+ * work.  This might be related to popup issues.
+ */
+/*.choice-box > * > .menu-item-radio {*/
+#choice-box-menu-item > * > .menu-item-radio {
+    /* When we show RadioMenuItems in ChoiceBox, we replace the radio shape with
+       a check mark, which looks much better */
+    -fx-shape: "M0,5H2L4,8L8,0H10L5,10H3Z";
+    -fx-scale-shape: false;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TabPane                                                                     *
+ *                                                                             *
+ ******************************************************************************/
+
+.tab-pane {
+    /* -fx-tab-min-width: 4.583em;  55 */
+    /* -fx-tab-max-width: 4.583em; 55 */
+    -fx-tab-min-height: 2em; /* 24 */
+    -fx-tab-max-height: 2em; /* 24 */
+}
+.tab-pane:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-label {
+    -fx-background-color: transparent;    
+    -fx-alignment: CENTER;
+    -fx-text-fill: -fx-text-base-color;
+}
+/*
+.tab *.tab-label Text {
+    -fx-effect: dropshadow(two-pass-box , rgba(255, 255, 255, 0.4), 1, 0.0 , 0, 1);
+}*/
+.tab-pane > .tab-content-area {
+    -fx-background-color: -fx-control-inner-background;
+    -fx-padding: 0.0em; /* 0 */
+}
+.tab-pane > .tab-header-area > .headers-region > .tab {
+    /* This is how it is done in Button, but the -1 inset caused a white line  */
+    /* to appear beneath the tab, which looks bad, so it's taken out below.    */
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+    -fx-padding: 0.083333em 0.5em 0.083333em 0.5em; /* 1 6 1 6 */
+/*    -fx-text-fill: -fx-text-base-color;*/
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:top {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:right {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border-bottomup, -fx-body-color-bottomup;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:bottom {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border-bottomup, -fx-body-color-bottomup;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:left {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:hover {
+    -fx-color: -fx-hover-base;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:selected {
+/*    -fx-background-color: white;*/
+
+/*    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+    -fx-background-insets: 0, 1 1 0 1, 2 2 0 2;*/
+    -fx-background-color: -fx-tab-border-color, -fx-background;
+    -fx-background-insets: 0, 1 1 0 1;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.tab-pane > .tab-header-area > .headers-region > .tab:disabled:hover {
+    -fx-color: -fx-base;
+    -fx-opacity: -fx-disabled-opacity;
+}
+.tab-pane > .tab-header-area > .tab-header-background {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, derive(-fx-color, -20%);
+    -fx-effect: innershadow(two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0 , 0);
+}
+/*.tab-pane *.tab-header-area {*/
+    /* I would like to use -fx-tab-border-color here, but for some reason it */
+    /* just isn't the correct color, even though it works in :top above */
+/*    -fx-background-color: -fx-tab-border-color, lightgray;*/
+/*}*/
+.tab-pane:top > .tab-header-area {
+    -fx-background-insets: 0, 0 0 1 0;
+    -fx-padding: 0.416667em 0.166667em 0.0em 0.833em; /* 5 2 0 10 */
+}
+.tab-pane:bottom > .tab-header-area {
+    -fx-background-insets: 0, 1 0 0 0;
+    -fx-padding: 0 0.166667em 0.416667em 0.833em; /* 0 2 5 0 */
+}
+.tab-pane:left > .tab-header-area {
+    -fx-background-insets: 0, 0 1 0 0;
+    -fx-padding: 0.833em 0.0em 0.166667em 0.416667em; /* 10 0 2 5 */
+}
+.tab-pane:right > .tab-header-area {
+    -fx-background-insets: 0, 0 0 0 1;
+    -fx-padding: 0.833em 0.416667em 0.166667em 0.0em; /* 10 5 2 0 */
+}
+/*.tab-pane > .tab-header-area > .headers-region {
+    -fx-effect: dropshadow(two-pass-box , rgba(0,0,0,0.6) , 4, 0.0 , 0, 0);
+}*/
+/* TODO: scaling the shape seems to make it way too large */
+.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button {
+    -fx-background-color: -fx-mark-color;
+    -fx-shape: "M 0,0 H1 L 4,3 7,0 H8 V1 L 5,4 8,7 V8 H7 L 4,5 1,8 H0 V7 L 3,4 0,1 Z";
+    -fx-scale-shape: false;
+    -fx-effect: dropshadow(two-pass-box , rgba(255, 255, 255, 0.4), 1, 0.0 , 0, 1);
+}
+.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button:hover {
+    -fx-background-color: derive(-fx-mark-color, -30%);
+}
+/* CONTROL BUTTONS */
+.tab-pane > .tab-header-area > .control-buttons-tab {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+    -fx-padding: 0.083333em 0.25em 0.083333em 0.25em; /* 1 3 1 3 */
+}
+.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button {
+    -fx-background-color: transparent;
+    -fx-padding: 0.0em 0.416667em 0.0em 0.416667em; /* 0 5 0 5 */
+}
+.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button:hover {
+    -fx-background-color: -fx-body-color;
+    -fx-color: -fx-hover-base;
+}
+.tab-pane > .tab-header-area > .control-buttons-tab > .container > .tab-down-button .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.238083em 0.416667em 0.238083em 0.416667em; /* 2.857 5 2.857 5 */
+    -fx-shape: "M 0 0 H 7 L 3.5 4 z";
+}
+/* FLOATING TABS CUSTOMISATION */
+.tab-pane.floating > .tab-header-area > .tab-header-background {
+    -fx-background-color: null;
+}
+.tab-pane.floating > .tab-header-area {
+    -fx-background-color: null;
+}
+.tab-pane.floating > .tab-content-area {
+    -fx-background-color: -fx-tab-border-color, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 5, 4;
+    -fx-padding: 2;
+}
+.tab-pane.floating > .tab-header-area > .headers-region > .tab {
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+}
+.tab-pane.floating  > .tab-header-area > .headers-region > .tab:selected {
+    -fx-background-color: -fx-tab-border-color, -fx-control-inner-background;
+    -fx-background-insets: 0 0 -1 0, 1 1 -1 1;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0;
+}
+/*.tab-pane:floating *.control-buttons-tab {
+    -fx-padding: 0.083333em 0.25em 0.083333em 0.25em;
+    -fx-background-color: -fx-tab-border-color, -fx-inner-border, -fx-body-color;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+    -fx-background-insets: 0, 1 1 0 1, 2 2 0 2;
+}*/
+
+/*******************************************************************************
+ *                                                                             *
+ * ComboBox                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+/* ------- MAIN BUTTON ------- */
+.combo-box-base  {
+    -fx-padding: 0;
+}
+/* ------- OPEN BUTTON ------- */
+.combo-box-base > .arrow-button {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5  */
+}
+.combo-box-base:focused > .arrow-button {
+    -fx-background-color: -fx-focus-color, -fx-inner-border, -fx-body-color; 
+}
+/*    -fx-background-color: null;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em;  6 5 6 5 
+}*/
+/*.combo-box-base.split-button .arrow-button {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em;  6 5 6 5 
+}*/
+/* ------- ARROW* ------- */
+.combo-box-base > .arrow-button > .arrow,
+.web-view .form-select-button .arrow {
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+.web-view .form-select-button {
+    -fx-background-radius: 2, 2, 1, 0;
+    -fx-background-insets: 2 2 1 2, 2, 3, 4;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Editable ComboBox                                                           *
+ *                                                                             *
+ * The editable ComboBox TextBox inherits its properties from the TextBox      *
+ * Control. Only the properties with values that are different from the        *
+ * TextBox are specified here.                                                 *
+ *                                                                             *
+ ******************************************************************************/
+
+.combo-box-base:editable > .text-field {
+    -fx-padding: 3 5 2 5;
+    -fx-background-radius: 3 4 4 3, 2 3 3 2;
+    -fx-background-insets: 0, 1;
+    -fx-vpos: CENTER;
+    -fx-content-display: LEFT;
+}
+.combo-box-base:editable > .text-field:focused {
+/*    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-control-inner-background; 
+    -fx-background-insets: -2, -0.3, 1;
+    -fx-background-radius: 6, 3.4, 2, 2;*/
+    -fx-background-color: -fx-focus-color, -fx-control-inner-background; 
+    -fx-background-insets: -0.3, 1;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.combo-box-base:editable:focused  > .text-field {
+    -fx-background-color: -fx-focus-color, -fx-control-inner-background; 
+    -fx-background-insets: -0.3, 1;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.combo-box-base:editable:focused {
+    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color; 
+    -fx-background-insets: -2, -0.3, 1, 2;
+    -fx-background-radius: 7, 6, 4, 3;
+}
+
+/* -------------- STYLES FOR THE DEFAULT LISTVIEW-BASED COMBOBOX ------------- */
+
+/* Customie the ListCell that appears in the ComboBox button itself */
+.combo-box > .list-cell {
+    -fx-background: transparent;
+    -fx-background-color: transparent;
+    -fx-text-fill: -fx-text-base-color;
+    -fx-padding: 3 0 2 7;
+    -fx-cell-size: 1.7500em; /* 21 */
+}
+.combo-box-popup > .list-view {
+    -fx-background-color: -fx-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 8, 0.0 , 0 , 0 );
+}
+.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell {
+    -fx-padding: 4 0 4 5;   
+    /* No alternate highlighting */
+    -fx-background-color: -fx-control-inner-background;
+}
+.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected, 
+.combo-box-popup  > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.combo-box-popup  > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:hover {
+    -fx-background-color: -fx-cell-hover-color;
+    -fx-text-fill: -fx-text-inner-color;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TitledPane                                                                  *
+ *                                                                             *
+ ******************************************************************************/
+
+.titled-pane {
+    -fx-text-fill: -fx-text-base-color;
+}
+.titled-pane:focused {
+    -fx-text-fill: white;
+}
+.titled-pane > .title {
+    -fx-background-color: -fx-box-border, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+    -fx-padding: 0.166667em 0.833333em 0.25em 0.833333em; /* 2 10 3 10 */
+}
+.titled-pane:focused > .title {
+    -fx-color: -fx-focus-color;
+}
+.titled-pane > .title > .arrow-button {
+    -fx-background-color: null;
+    -fx-background-insets: 0;
+    -fx-background-radius: 0;
+    -fx-padding: 0.0em 0.25em 0.0em 0.0em; /* 0 3 0 0 */
+}
+.titled-pane > .title > .arrow-button > .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+.titled-pane:collapsed > .title > .arrow-button > .arrow {
+    -fx-rotate: -90;
+}
+.titled-pane > *.content {
+    -fx-background-color:
+        -fx-box-border,
+        linear-gradient(to bottom, derive(-fx-color,-02%), derive(-fx-color,65%) 12%, derive(-fx-color,23%) 88%, derive(-fx-color,50%) 99%, -fx-box-border);
+    -fx-background-insets: 0, 0 1 1 1;
+    -fx-padding: 0.167em;
+}
+.titled-pane:focused > .title > .arrow-button > .arrow {
+    -fx-background-color: white;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Accordion                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.accordion > .titled-pane > .title {
+    -fx-background-color:
+        -fx-box-border,
+        -fx-inner-border,
+        -fx-body-color;
+    -fx-background-insets: -1 0 0 0, 0 1 1 1, 1 2 2 2;
+    -fx-background-radius: 0, 0, 0;
+}
+.accordion > .first-titled-pane > .title {
+    -fx-background-insets: 0, 1, 2;
+}
+.accordion > .titled-pane:focused > .title {
+    -fx-color: -fx-focus-color;
+}
+.accordion > .titled-pane:focused {
+    -fx-text-fill: white;
+}
+.accordion > .titled-pane:focused > .title > .arrow-button > .arrow {
+    -fx-background-color: white;
+}
+.accordion > .titled-pane:focused > .titled-pane:collapsed > .title > .arrow-button > .arrow {
+    -fx-background-color: white;
+}
+.accordion > .titled-pane:collapsed:focused > .title {
+    -fx-color: -fx-focus-color;
+}
+.accordion > .titled-pane:expanded:focused > .title {
+    -fx-color: -fx-focus-color;
+}
+.accordion > .titled-pane:hover > .title {
+    -fx-color: -fx-hover-base;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * SplitPane                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.split-pane > * > * > .table-view { -fx-padding: 0px; }
+.split-pane > * > * > .list-view { -fx-padding: 0px; }
+.split-pane > * > * > .tree-view { -fx-padding: 0px; }
+.split-pane > * > * > .scroll-pane { -fx-padding: 0px; }
+.split-pane > * > * > .split-pane {
+    -fx-background-insets: 0, 0;
+    -fx-padding: 0;
+ }
+.split-pane > .split-pane-divider {
+    -fx-padding: 0 2 0 2; /* 0 3 0 3 */
+}
+/* horizontal the two nodes are placed to the left/right of each other. */
+.split-pane:horizontal > .split-pane-divider {
+   -fx-border-color: transparent -fx-box-border transparent #BBBBBB;
+   -fx-background-color: transparent, -fx-inner-border-horizontal;
+   -fx-background-insets: 0, 0 1 0 1;
+}
+/* vertical the two nodes are placed on top of each other. */
+.split-pane:vertical > .split-pane-divider {
+   -fx-border-color:  #BBBBBB transparent -fx-box-border transparent;
+   -fx-background-color: transparent, -fx-inner-border;
+   -fx-background-insets: 0, 1 0 1 0;
+}
+.split-pane > .split-pane-divider > .horizontal-grabber {
+    -fx-padding: 5 1 5 1;
+    -fx-background-color: #FFFFFF, -fx-box-border;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-shape: "M0 0 L0 0 L2 0 L2 2 L0 2 Z M0 4 L0 4 L2 4 L2 6 L0 6 Z M0 8 L0 8 L2 8 L2 10 L0 10 Z";
+}
+.split-pane > .split-pane-divider > .vertical-grabber {
+    -fx-padding: 1 5 1 5;
+    -fx-background-color: #FFFFFF, -fx-box-border;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-shape: "M0 0 L0 0 L2 0 L2 2 L0 2 Z M4 0 L4 0 L4 2 L6 2 L6 0 Z M8 0 L8 0 L8 2 L10 2 L10 0 Z";
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * ColorPicker                                                                 *
+ *                                                                             *
+ ******************************************************************************/
+
+.color-picker > .arrow-button {
+    -fx-background-color: null;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
+}
+.color-picker > .color-picker-label > .text {
+    -fx-padding: 0.0em 0.833333em 0.0em 0.0em;  /* 0 10 0 0 */
+}
+.color-picker > .split-button > .arrow-button {
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
+}
+.color-picker > .split-button > .arrow-button:hover {
+    -fx-color: -fx-hover-base;
+}
+.color-picker > .split-button > .color-picker-label:hover {
+     -fx-color: -fx-hover-base;
+}
+.color-picker > .color-picker-label > .picker-color {
+    -fx-padding: 4;
+    -fx-background-color: null;
+}
+.color-picker > .color-picker-label > .picker-color > .picker-color-rect {
+    -fx-stroke: -fx-pressed-base;
+}
+.color-palette {
+     -fx-background-color:
+        derive(-fx-color,-40%),
+        derive(-fx-color,100%),
+        linear-gradient(to bottom, 
+        derive(-fx-color,100%) 0%, 
+        derive(-fx-color,50%) 12%, 
+        derive(-fx-color,65%) 88%, 
+        derive(-fx-color,23%) 100%);
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 0 6 6 6, 0 5 5 5, 0 4 4 4;
+    -fx-padding: 15 15 15 15;
+    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 8, 0.0 , 0 , 0 );
+}
+.color-palette > .color-picker-grid > .color-square > .color-rect {
+    -fx-stroke: black;
+    -fx-stroke-width: 0.4;
+    -fx-border-color: black;
+}
+.color-palette > .color-picker-grid {
+    -fx-border-color: black;
+}
+.color-palette > .color-picker-grid > .color-square {
+    -fx-background-color: transparent;
+    -fx-background-insets: -1, 0;   
+    -fx-padding: 0.5;
+    -fx-border: black;
+}
+/* the color over which the user is hovering */
+.color-palette > .color-picker-grid > .color-square:focused, 
+.color-palette > .color-picker-grid > .color-square:selected:focused {
+    -fx-background-color: -fx-focus-color;
+}
+/* the currently selected color */
+.color-palette > .color-picker-grid > .color-square:selected {
+/*    -fx-background-color: derive(-fx-base, -27%)  #989898 , white, derive(-fx-base, -59%)  #555555 ;*/
+    -fx-background-color: black;
+} 
+.color-palette > .separator > .line {
+    -fx-background-color: -fx-pressed-base;
+/*    -fx-background-color: white;*/
+    -fx-padding: 6 0 0 0;
+    -fx-background-insets: 4 -10 0 -10,5 -10 0 -10;
+    -fx-border-style: none;
+    -fx-border-color: null;
+}
+.custom-color-dialog > .color-rect-pane {
+    -fx-padding: 15 8 15 15;
+/*    -fx-background-color: -fx-background;*/
+}
+.custom-color-dialog > .controls-pane {
+    -fx-padding: 15 15 15 0;
+/*    -fx-background-color: -fx-background;*/
+}
+.custom-color-dialog  {
+    -fx-background-color: -fx-background;
+}
+/* -------- Toggle Button ---------------- */
+.custom-color-dialog .controls-pane .toggle-button {
+    -fx-background-radius: 4, 4, 3, 2;
+    -fx-padding: 3 6 3 6;
+}
+.custom-color-dialog .controls-pane .toggle-button:focused {
+    -fx-background-color:
+        rgba(23,134,248,0.2),
+        -fx-focus-color,
+        -fx-inner-border,
+        -fx-body-color;
+}
+.custom-color-dialog .controls-pane .toggle-button:selected Text {
+    -fx-effect: dropshadow( one-pass-box , rgba(0,0,0,0.9) , 2, 0.0 , 0 , 1 );
+}
+.custom-color-dialog .controls-pane .toggle-button:selected {
+    -fx-background-color:
+        linear-gradient( to bottom, derive(-fx-color,-90%) 0%, derive(-fx-color,-60%) 100% ),        
+        linear-gradient( to bottom, derive(-fx-color,-60%) 0%, derive(-fx-color,-35%) 50%, derive(-fx-color,-30%) 98%, derive(-fx-color,-50%) 100% ),    
+        linear-gradient( to right, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 10%, rgba(0,0,0,0) 90%, rgba(0,0,0,0.3) 100% );
+    -fx-background-insets: 0, 1, 1;
+    /* TODO: -fx-text-fill should be derived */
+    -fx-text-fill: -fx-light-text-color;
+}
+.custom-color-dialog .controls-pane #toggle-button-left {
+    -fx-background-radius: 3 0 0 3;
+    -fx-background-insets: 0 0 -1 0, 0, 1 0 1 1, 2 0 2 2;
+    -fx-border-color: transparent -fx-outer-border transparent transparent;
+    -fx-border-insets: 4 0 4 0;
+    -fx-padding: -2 8 -2 8;
+}
+.custom-color-dialog .controls-pane #toggle-button-left:focused {
+	-fx-background-radius: 3 0 0 3;
+	-fx-background-insets: -1.4 0 -1.4 -1.4, 0 0 0 0, 1, 2;
+	-fx-border-color: transparent;
+}
+.custom-color-dialog .controls-pane #toggle-button-left:selected, .controls-pane #toggle-button-left:selected:focused {
+        -fx-background-insets: 0 0 -1 0, 0, 1 0 1 1, 1 0 1 1;
+	-fx-border-color: transparent;
+}
+.custom-color-dialog .controls-pane #toggle-button-center {
+	-fx-background-radius: 0;
+        -fx-background-insets: 0;
+	-fx-background-insets: 0 0 -1 0, 0, 1 0 1 0, 2 0 2 0;
+	-fx-border-color: transparent -fx-outer-border transparent transparent;
+        -fx-border-insets: 4 0 4 0;
+	-fx-padding: -2 8 -2 8;
+}
+.custom-color-dialog .controls-pane #toggle-button-center:focused {
+	-fx-background-radius: 0;
+	-fx-background-insets: -1.4 0 -1.4 -1, 0 0 0 -1, 1 1 1 0, 2 2 2 1;
+	-fx-border-color: transparent;
+}
+.custom-color-dialog .controls-pane #toggle-button-center:selected, .controls-pane #toggle-button-center:selected:focused {
+	-fx-background-insets: -1.4 0 -1.4 -1, 0 0 0 -1, 1 1 1 0, 1 1 1 0;
+	-fx-border-color: transparent;
+}
+.custom-color-dialog .controls-pane #toggle-button-right {
+	-fx-background-radius: 0 3 3 0;
+    -fx-background-insets: 0 0 -1 0, 0, 1 1 1 0, 2 2 2 0;
+	-fx-padding: 3 8 3 8;
+}
+.custom-color-dialog .controls-pane #toggle-button-right:focused {
+	-fx-background-radius: 0 3 3 0;
+	-fx-background-insets: -1.4 -1.4 -1.4 -1, 0 0 0 -1, 1 1 1 0, 2 2 2 1;
+}
+.custom-color-dialog .controls-pane #toggle-button-right:selected, .controls-pane #toggle-button-right:selected:focused {
+	-fx-background-insets: -1.4 -1.4 -1.4 -1, 0 0 0 -1, 1 1 1 0, 1 1 1 0;
+}
+.custom-color-dialog .controls-pane .current-new-color-grid #transparent-current, .controls-pane .current-new-color-grid #transparent-new {
+    -fx-background-image: url("pattern-transparent.png"); 
+    -fx-background-repeat: repeat;
+    -fx-background-size: auto;
+    -fx-padding: 9 64 9 64;
+}
+.custom-color-dialog .controls-pane .customcolor-controls-background {
+    -fx-background-color: -fx-text-box-border, -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background-radius: 3, 2, 2;
+    -fx-padding: 3 5 3 5;
+}
+.custom-color-dialog .controls-pane .alpha-settings .text-field {
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 3, 2;
+    -fx-padding: 3 5 3 5;
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-cursor: text;
+}
+.custom-color-dialog .controls-pane .current-new-color-grid .label {
+    -fx-padding: 0 0 0 5;
+}
+.custom-color-dialog .input-field {
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 2, 2;
+    -fx-padding: 3 5 3 5;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-cursor: text;
+}
+.custom-color-dialog .input-field:focused {
+    -fx-background-color: -fx-focus-color, -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: -0.4, 1, 2;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.custom-color-dialog .input-field:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.custom-color-dialog .integer-field {
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 2, 2;
+    -fx-padding: 3 5 3 5;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-cursor: text;
+}
+.custom-color-dialog .integer-field:focused {
+    -fx-background-color: -fx-focus-color, -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: -0.4, 1, 2;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.custom-color-dialog .double-field {
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 2, 2;
+    -fx-padding: 3 5 3 5;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-cursor: text;
+}
+.custom-color-dialog .double-field:focused {
+    -fx-background-color: -fx-focus-color, -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: -0.4, 1, 2;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.custom-color-dialog .double-field:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.custom-color-dialog .webcolor-field {
+    -fx-background-color: -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 2, 2;
+    -fx-padding: 3 5 3 5;
+    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
+    -fx-cursor: text;
+}
+.custom-color-dialog .webcolor-field:focused {
+    -fx-background-color: -fx-focus-color, -fx-text-box-border, -fx-control-inner-background;
+    -fx-background-insets: -0.4, 1, 2;
+    -fx-background-radius: 3.4, 2, 2;
+}
+.custom-color-dialog .webcolor-field:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Pagination                                                                  *
+ *                                                                             *
+ ******************************************************************************/
+
+.pagination {
+    -fx-padding: 0;        
+    -fx-arrows-visible: true;
+    -fx-tooltip-visible: true;
+    -fx-page-information-visible: true;
+    -fx-page-information-alignment: bottom;        
+}
+.pagination > .page {
+    -fx-background-color: transparent;
+}
+.pagination > .pagination-control {
+    -fx-background-color: transparent;    
+    -fx-padding: 0.833333em 0em 0.833333em 0em;
+}
+.pagination > .pagination-control > .control-box {
+    -fx-spacing: 4;
+    -fx-alignment: center;
+}
+.pagination > .pagination-control > .control-box > .left-arrow-button{
+    -fx-background-radius: 0;
+    -fx-padding: 0.166667em 0.416em 0.25em 0.333em;
+}
+.pagination > .pagination-control > .control-box > .right-arrow-button {
+    -fx-background-radius: 0;
+    -fx-padding: 0.166667em 0.333em 0.25em 0.416em;
+}
+.pagination > .pagination-control .left-arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.375em 0.291em 0.375em 0.291em;
+    -fx-shape: "M 0 0 L -13 7 L 0 13 z";
+    -fx-scale-shape: true;
+}
+.pagination > .pagination-control .right-arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.375em 0.291em 0.375em 0.291em;
+    -fx-shape: "M 0 0 L 13 7 L 0 13 z";
+    -fx-scale-shape: true;
+}
+.pagination > .pagination-control > .control-box > .bullet-button {   
+   -fx-background-radius: 0, 4em, 4em, 4em, 4em;
+   -fx-padding: 0.333em;  
+   -fx-background-color: transparent, -fx-outer-border, -fx-inner-border, -fx-body-color;
+   -fx-background-insets: 0, 5,  6,  7;
+}
+.pagination > .pagination-control > .control-box > .bullet-button:selected {   
+    -fx-base: -fx-accent;
+}
+.pagination.bullet > .pagination-control > .control-box > .left-arrow-button, 
+.pagination.bullet > .pagination-control > .control-box > .right-arrow-button {
+    -fx-background-radius: 4em;
+}
+.pagination > .pagination-control > .control-box > .number-button {
+    -fx-background-radius: 0;
+    -fx-padding: 0.166667em 0.25em 0.25em 0.333em;
+    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
+}
+.pagination > .pagination-control > .control-box > .number-button:selected {   
+    -fx-base: -fx-accent;
+}
+.pagination > .pagination-control > .page-information {   
+    -fx-padding: 0.416em 0 0 0;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Customised CSS for controls placed directly within cells                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.cell > .choice-box {
+    -fx-background-color: transparent;
+    -fx-background-insets: 0;
+    -fx-background-radius: 0;
+    -fx-padding: 0.0em 0.5em 0.0em 0.0em; /* 0 6 0 0 */
+    -fx-alignment: CENTER_LEFT;
+    -fx-content-display: LEFT;
+}
+.cell > .choice-box > .label {
+    -fx-padding: 0em 0.333333em 0.0em 0.333333; /* 2 4 3 6 */
+}
+.cell:focused:selected > .choice-box > .label {
+    -fx-text-fill: white;
+}
+.cell:focused:selected > .choice-box > .open-button > .arrow {
+    -fx-background-color: -fx-mark-highlight-color, white;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * ListView and ListCell                                                       *
+ *                                                                             *
+ ******************************************************************************/
+
+.list-view > .virtual-flow > .scroll-bar:vertical{
+    -fx-background-insets: 0, 0 0 0 1;
+    -fx-padding: -1 -1 -1 0;
+}
+.list-view > .virtual-flow > .scroll-bar:horizontal{
+    -fx-background-insets: 0, 1 0 0 0;
+    -fx-padding: 0 -1 -1 -1;
+}
+.list-view > .virtual-flow > .corner {
+    -fx-background-color: -fx-box-border, -fx-base;
+    -fx-background-insets: 0, 1 0 0 1;
+}
+.list-cell {
+    -fx-background-color: -fx-control-inner-background;
+    -fx-padding: 0.25em; /* 3 */
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-opacity: 1;
+}
+.list-cell:odd {
+    -fx-background-color: -fx-control-inner-background-alt;
+}
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+}
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:focused:odd {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background-alt;
+    -fx-background-insets: 0, 1, 2;
+}
+/* When the list-cell is selected and focused */
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected, 
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:focused:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+/* When the ListView is _not_ focused, we show alternate selection colors */
+.list-cell:filled:selected:focused,
+.list-cell:filled:selected,
+.list-view:horizontal > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected {
+    -fx-background-color: lightgray;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.list-cell:filled:selected:focused:disabled, 
+.list-cell:filled:selected:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.list-cell:filled:hover {
+    -fx-background-color: -fx-cell-hover-color;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:focused:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.list-view:horizontal > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected,
+.list-view:horizontal > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover {
+    -fx-background-color: -fx-selection-bar;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TreeView and TreeCell                                                       *
+ *                                                                             *
+ ******************************************************************************/
+
+.tree-view > .virtual-flow > .scroll-bar:vertical{
+    -fx-background-insets: 0, 0 0 0 1;
+    -fx-padding: -1 -1 -1 0;
+}
+.tree-view > .virtual-flow > .scroll-bar:horizontal{
+    -fx-background-insets: 0, 1 0 0 0;
+    -fx-padding: 0 -1 -1 -1;
+}
+.tree-view > .virtual-flow > .corner {
+    -fx-background-color: -fx-box-border, -fx-base;
+    -fx-background-insets: 0, 1 0 0 1;
+}
+.tree-cell {
+    -fx-background-color: -fx-control-inner-background;
+    -fx-padding: 0.25em; /* 3 */
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-indent: 80;
+}
+.tree-cell .label {
+    -fx-padding: 0.0em 0.0em 0.0em 0.25em; /* 0 0 0 3 */
+}
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+}
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:selected, 
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:selected:hover {
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:focused:selected:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+/* When the TreeView is _not_ focused, we show alternate selection colors */
+.tree-cell:filled:selected:focused, 
+.tree-cell:filled:selected {
+    -fx-background-color: lightgray;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.tree-cell:filled:selected:focused:disabled, 
+.tree-cell:filled:selected:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.tree-cell > .tree-disclosure-node,
+.tree-table-row-cell > .tree-disclosure-node {
+    /** put a bit of padding around the disclosure node to make the clicking region larger */
+    -fx-padding: 4 2 4 8;
+    -fx-background-color: transparent;
+}
+.tree-cell > .tree-disclosure-node:disabled,
+.tree-table-row-cell > .tree-disclosure-node:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.tree-cell > .tree-disclosure-node > .arrow,
+.tree-table-row-cell > .tree-disclosure-node > .arrow {
+    -fx-background-color: -fx-mark-color;
+    -fx-padding: 0.333333em; /* 4 */
+    -fx-shape: "M 0 -4 L 8 0 L 0 4 z";
+}
+.tree-cell:expanded > .tree-disclosure-node > .arrow,
+.tree-table-row-cell:expanded > .tree-disclosure-node > .arrow {
+    -fx-rotate: 90;
+}
+.tree-cell:filled:selected > .tree-disclosure-node > .arrow,
+.tree-table-row-cell:filled:selected > .tree-disclosure-node > .arrow {
+    -fx-background-color: -fx-selection-bar-text;
+}
+.tree-cell:filled:hover,
+.tree-table-row-cell:filled:hover {
+    -fx-background-color: -fx-cell-hover-color;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.tree-cell:filled:hover > .tree-disclosure-node > .arrow,
+.tree-table-row-cell:filled:hover > .tree-disclosure-node > .arrow {
+    -fx-background-color: -fx-mark-color;
+}
+.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:focused:hover,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.tree-cell:filled:selected:hover > .tree-disclosure-node > .arrow,
+.tree-table-row-cell:filled:selected:hover > .tree-disclosure-node > .arrow {
+    -fx-background-color: -fx-selection-bar-text;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TableView                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.table-view,
+.tree-table-view {
+    /* Constants used throughout the tableview. */
+    -fx-table-header-border-color: -fx-box-border;
+    -fx-table-cell-border-color: -fx-box-border;
+}
+/** Draws focus border around tableview */
+.table-view:focused,
+.tree-table-view:focused {
+    -fx-background-color: -fx-faint-focus-color, -fx-focus-color,-fx-control-inner-background;
+    -fx-background-insets: -2, -0.3, 1;
+    -fx-background-radius: 2, 0, 0;
+}
+.table-view > .virtual-flow > .scroll-bar:vertical,
+.tree-table-view > .virtual-flow > .scroll-bar:vertical {
+    -fx-background-insets: 0, 0 0 0 1;
+    -fx-padding: -1 -1 -1 0;
+}
+.table-view > .virtual-flow > .scroll-bar:horizontal,
+.tree-table-view > .virtual-flow > .scroll-bar:horizontal {
+    -fx-background-insets: 0, 1 0 0 0;
+    -fx-padding: 0 -1 -1 -1;
+}
+.table-view > .virtual-flow > .corner,
+.tree-table-view > .virtual-flow > .corner {
+    -fx-background-color: -fx-box-border, -fx-base;
+    -fx-background-insets: 0, 1 0 0 1;
+}
+/* Each row in the table is a table-row-cell. Inside a table-row-cell is any
+   number of table-cell. */
+.table-row-cell {
+    -fx-background-color: -fx-table-cell-border-color, -fx-control-inner-background;
+    -fx-background-insets: 0, 0 0 1 0;
+    -fx-padding: 0.0em; /* 0 */
+    -fx-text-fill: -fx-text-inner-color;
+}
+.table-row-cell:odd {
+    -fx-background-color: -fx-table-cell-border-color, -fx-control-inner-background-alt;
+    -fx-background-insets: 0, 0 0 1 0;
+}
+.table-row-cell:focused,
+.tree-table-row-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+}
+.table-row-cell:focused:odd {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background-alt;
+    -fx-background-insets: 0, 1, 2;
+}
+/* When the table-row-cell is selected and focused */
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:focused:selected,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected > .table-cell,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected > .tree-table-cell {
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected, 
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-view:row-selection:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:focused:selected:hover,
+.tree-table-view:row-selection:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:selected:hover{
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+/* When the TableView is _not_ focused, we show alternate selection colors */
+.table-row-cell:filled:selected:focused, 
+.table-row-cell:filled:selected,
+.tree-table-row-cell:filled:selected:focused, 
+.tree-table-row-cell:filled:selected {
+    -fx-background-color: lightgray;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-row-cell:selected:disabled,
+.tree-table-row-cell:selected:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:hover { 
+    -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color;
+    -fx-background-insets: 0, 0 0 1 0;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:hover {
+    /* No 1-pixel bottom border for the TreeTableView (unlike the TableView above) */
+    -fx-background-color: -fx-cell-hover-color;
+    -fx-background-insets: 0;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:focused:hover,
+.tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:hover { 
+    -fx-background-color: -fx-table-cell-border-color, -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 0 0 1 0, 1 1 2 1, 2 2 3 2, 3 3 4 3;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.table-cell {
+    -fx-padding: 0.166667em; /* 2px, plus border adds 1px */
+    -fx-background-color: transparent;
+    -fx-border-color: transparent -fx-table-cell-border-color transparent transparent;
+    -fx-border-width: 0.083333em; /* 1 */
+    -fx-cell-size: 2.0em; /* 24 */
+    -fx-text-fill: -fx-text-inner-color;
+}
+/* When in constrained resize mode, the right-most visible cell should not have
+   a right-border, as it is not possible to get this cleanly out of view without
+   introducing horizontal scrollbars (see RT-14886). */
+.table-view:constrained-resize > .virtual-flow > .clipped-container > .sheet > .table-row-cell > .table-cell:last-visible,
+.tree-table-view:constrained-resize > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:last-visible {
+    -fx-border-color: transparent;
+}
+.table-view:constrained-resize > .column-header:last-visible,
+.tree-table-view:constrained-resize > .column-header:last-visible {
+    -fx-border-width: 0.083333em 0.0em 0.083333em 0.083333em, 0.083333em 0.0em 0.083333em 0.083333em;
+}
+.table-view:constrained-resize .filler,
+.tree-table-view:constrained-resize .filler {
+    -fx-border-color: 
+        derive(-fx-base, 80%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%)
+        derive(-fx-base, 10%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%),
+        /* Outer border: */
+        transparent -fx-table-header-border-color -fx-table-header-border-color -fx-table-header-border-color;
+    -fx-border-insets: 0 1 1 1, 0 0 0 0;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell > .table-cell:focused,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled .table-cell:focused:selected,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled .tree-table-cell:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:selected, 
+.table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:hover:selected,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:selected, 
+.tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:hover:selected {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-text-fill: -fx-selection-bar-text;
+    -fx-background-insets: 0 0 1 0;
+}
+.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:selected:hover,
+.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:focused:selected:hover{
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+/* When the TableView is _not_ focused, we show alternate selection colors */
+.table-row-cell:filled > .table-cell:selected:focused, 
+.table-row-cell:filled > .table-cell:selected,
+.tree-table-row-cell:filled > .tree-table-cell:selected:focused, 
+.tree-table-row-cell:filled > .tree-table-cell:selected {
+    -fx-background-color: lightgray;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+.table-cell:selected:disabled,
+.tree-table-cell:selected:disabled {
+    -fx-opacity: -fx-disabled-opacity;
+}
+.table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:hover,
+.tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:hover {
+    -fx-background-color: -fx-cell-hover-color;
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-background-insets: 0 0 1 0;
+}
+.table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:hover,
+.tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:focused:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-text-fill: -fx-text-inner-color;
+}
+/* The column-resize-line is shown when the user is attempting to resize a column. */
+.table-view .column-resize-line,
+.tree-table-view .column-resize-line {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-padding: 0.0em 0.0416667em 0.0em 0.0416667em; /* 0 0.571429 0 0.571429 */
+}
+/* This is the area behind the column headers. An ideal place to specify background
+   and border colors for the whole area (not individual column-header's). */
+.table-view .column-header-background,
+.tree-table-view .column-header-background {
+    -fx-background-color: -fx-body-color;
+    -fx-padding: 0;
+}
+/* The column header row is made up of a number of column-header, one for each
+   TableColumn, and a 'filler' area that extends from the right-most column
+   to the edge of the tableview, or up to the 'column control' button. */
+.table-view .column-header,
+.tree-table-view .column-header {
+    -fx-text-fill: -fx-selection-bar-text;
+    /* TODO: for some reason, this doesn't scale. */
+    -fx-font-size: 1.083333em; /* 13pt - 1 more than the default font */
+    -fx-size: 25;
+    -fx-border-style: solid;
+    -fx-border-color: 
+        /* 
+          Inner border: we have different colours along the top, right, bottom and left.
+          Refer to RT-12298 for the spec.
+        */
+        derive(-fx-base, 80%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%)
+        derive(-fx-base, 10%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%),
+        /* Outer border: */
+        transparent -fx-table-header-border-color -fx-table-header-border-color transparent;
+    -fx-border-insets: 0 1 1 0, 0 0 0 0;
+    -fx-border-width: 0.083333em, 0.083333em;
+}
+.table-view .filler,
+.tree-table-view .filler {
+    -fx-size: 25;
+    -fx-border-style: solid;
+    -fx-border-color: 
+        /* 
+          Inner border: we have different colours along the top, right, bottom and left.
+          Refer to RT-12298 for the spec.
+        */
+        derive(-fx-base, 80%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%)
+        derive(-fx-base, 10%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%),
+        /* Outer border: */
+        transparent transparent -fx-table-header-border-color transparent;
+    -fx-border-insets: 0 0 1 0, 0 0 0 0;
+    -fx-border-width: 0.083333em, 0.083333em 0 0.083333em 0.083333em;
+}
+.table-view .column-header .sort-order,
+.tree-table-view .column-header .sort-order{
+    -fx-font-size: 0.916667em; /* 11pt - 1 less than the default font */
+}
+.table-view > .column-header-background > .show-hide-columns-button,
+.tree-table-view > .column-header-background > .show-hide-columns-button{
+    -fx-background-color: -fx-body-color;
+
+    -fx-border-color:
+        /* inner border: A copy of the inner border used above in the general column header area. */
+        derive(-fx-base, 80%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%),
+        derive(-fx-base, 10%) 
+        linear-gradient(to bottom, derive(-fx-base,80%) 20%, derive(-fx-base,-10%) 90%),
+        /* outer border: Slightly different to the above*/
+        transparent transparent -fx-table-header-border-color -fx-table-header-border-color;
+    -fx-border-insets: 0 0 0 1, 0 0 0 0;
+}
+.table-view .show-hide-column-image,
+.tree-table-view .show-hide-column-image {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+
+    -fx-padding: 0.25em; /* 3px */
+    -fx-shape: "M398.902,298.045c0.667,0,1.333,0,2,0c0,0.667,0,1.333,0,2c0.667,0,1.333,0,2,0c0,0.667,0,1.333,0,2c-0.667,0-1.333,0-2,0c0,0.666,0,1.332,0,1.999c-0.667,0-1.333,0-2,0c0-0.667,0-1.333,0-1.999c-0.666,0-1.333,0-1.999,0c0-0.667,0-1.334,0-2c0.666,0,1.333,0,1.999,0C398.902,299.378,398.902,298.711,398.902,298.045z"; 
+}
+/*.nested-column-header .column-header {
+    -fx-background-color: transparent;
+}*/
+/* When a column is being 'dragged' to be placed in a different position, there
+   is a region that follows along the column header area to indicate where the
+   column will be dropped. This region can be styled using the .column-drag-header
+   name. */
+.table-view .column-drag-header,
+.tree-table-view .column-drag-header {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+    -fx-border-color: transparent;
+    -fx-opacity: 0.6;
+}
+/* Semi-transparent overlay to indicate the column that is currently being moved */
+.table-view .column-overlay,
+.tree-table-view .column-overlay {
+    -fx-background-color: darkgray;
+    -fx-opacity: 0.3;
+}
+.table-view /*> column-header-background > nested-column-header >*/ .arrow,
+.tree-table-view /*> column-header-background > nested-column-header >*/ .arrow {
+    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
+    -fx-background-insets: 1 0 -1 0, 0;
+    -fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */
+    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+/* This is shown when the table has no rows and/or no columns. */
+.table-view .empty-table,
+.tree-table-view .empty-table {
+    -fx-background-color: white;
+    -fx-font-size: 1.166667em; /* 14pt - 2 more than the default font */
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Table Cells                                                                 *
+ *                                                                             *
+ ******************************************************************************/
+.check-box-table-cell {
+    -fx-alignment: center;
+}
+.check-box-table-cell > .check-box {
+    -fx-opacity: 1;
+}   
+.check-box-table-cell > .check-box > .box {
+    -fx-background-color: null;
+    -fx-background-insets: 0;
+    -fx-border-color: -fx-outer-border;
+    -fx-border-radius: 3;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TreeTableView                                                               *
+ *                                                                             *
+ * Note: A lot of the CSS for TreeTableView is included with the TreeView and  *
+ * TableView CSS styles elsewhere in caspian.css (as they are the same, just   *
+ * targeting different CSS style classes).                                     *
+ ******************************************************************************/
+
+.tree-table-row-cell {
+    -fx-background-color: -fx-control-inner-background;
+    -fx-padding: 0.0em; /* 0 */
+    -fx-text-fill: -fx-text-inner-color;
+}
+.tree-table-cell {
+    -fx-padding: 0.166667em; /* 2px, plus border adds 1px */
+    -fx-background-color: transparent;
+    -fx-border-color: transparent -fx-table-cell-border-color transparent transparent;
+    -fx-border-width: 0.083333em; /* 1 */
+    -fx-cell-size: 2.0em; /* 24 */
+    -fx-text-fill: -fx-text-inner-color;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * TreeTableView cell spanning                                                 *
+ *                                                                             *
+ ******************************************************************************/
+
+.cell-span-tree-table-view > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell {
+    -fx-background-color: transparent;
+} 
+/* All table-row-cells - we don't care if they are even or odd */
+.cell-span-tree-table-view > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell {
+    -fx-background-color: -fx-table-cell-border-color, -fx-control-inner-background;
+    -fx-background-insets: 0, 0 1 0 0;
+    -fx-alignment: center;
+}
+/** Selection styles */
+/*.cell-span-table-view > .virtual-flow > .clipped-container > .sheet > .table-row-cell > .table-cell:focused:selected, */
+.cell-span-tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected > .tree-table-cell,
+.cell-span-tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:selected > .tree-table-cell,
+.cell-span-tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:selected:hover > .tree-table-cell,
+.cell-span-tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:filled:selected,
+.cell-span-tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:filled:focused:selected,
+.cell-span-tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell > .tree-table-cell:filled:focused:selected:hover{
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+/** Hover styles */
+/** --- Row selection mode hover */
+.cell-span-tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:hover > .tree-table-cell { 
+    -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color;
+    -fx-background-insets: 0, 0 0 1 0;
+    -fx-text-fill: -fx-text-inner-color;
+}
+.cell-span-tree-table-view:row-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:focused:hover > .tree-table-cell { 
+    -fx-background-color: -fx-table-cell-border-color, -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 0 0 1 0, 1 1 2 1, 2 2 3 2, 3 3 4 3;
+    -fx-text-fill: -fx-text-inner-color;
+}
+/** --- Cell selection mode hover */
+.cell-span-tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:hover{
+    -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color;
+    -fx-text-fill: -fx-text-inner-color;
+    -fx-background-insets: 0, 0 0 1 0;
+}
+.cell-span-tree-table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled > .tree-table-cell:focused:hover{
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-text-fill: -fx-text-inner-color;
+}
+/** End of hover styles */
+
+/*******************************************************************************
+ *                                                                             *
+ * Tooltip                                                                     *
+ *                                                                             *
+ ******************************************************************************/
+
+.tooltip {
+    -fx-background: rgba(30,30,30);
+    -fx-text-fill: white;
+    -fx-background-color: rgba(30,30,30,0.8);
+    -fx-background-radius: 6px;
+    -fx-background-insets: 0;
+    -fx-padding: 0.666667em; /* 8 */
+    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.5) , 10, 0.0 , 0 , 0 );
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Charts                                                                      *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart {
+    -fx-padding: 5px;
+}
+.chart-content {
+    -fx-padding: 10px;
+}
+.chart-title {
+    -fx-font-size: 1.4em;
+}
+.chart-legend {
+   -fx-background-color:  #cccccc, #eeeeee;
+   -fx-background-insets: 0,1;
+   -fx-background-radius: 6,5;
+   -fx-padding: 6px;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * Axis                                                                        *
+ *                                                                             *
+ ******************************************************************************/
+
+.axis {
+    -fx-tick-label-font: 0.833333em System; /* 10 pix */
+    -fx-tick-label-fill: -fx-text-background-color;
+}
+.axis:top {
+    -fx-border-color: transparent transparent #666666 transparent;
+}
+.axis:right {
+    -fx-border-color: transparent transparent transparent #666666;
+}
+.axis:bottom {
+    -fx-border-color: #666666 transparent transparent transparent;
+}
+.axis:left {
+    -fx-border-color: transparent #666666 transparent transparent;
+}
+.axis-tick-mark {
+    -fx-fill: null;
+    -fx-stroke: #666666;
+}
+.axis-minor-tick-mark {
+    -fx-fill: null;
+    -fx-stroke: #AAAAAA;
+}
+
+.axis .text {
+  -fx-font-smoothing-type: lcd;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * ChartPlot                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart-plot-background {
+    -fx-background-color: #f5f5f5;
+}
+.chart-vertical-grid-lines {
+    -fx-stroke: #dddddd;
+}
+.chart-horizontal-grid-lines {
+    -fx-stroke: #dddddd;
+}
+.chart-alternative-column-fill {
+    -fx-fill: #eeeeee;
+    -fx-stroke: transparent;
+    -fx-stroke-width: 0;
+}
+.chart-alternative-row-fill {
+    -fx-fill: #eeeeee;
+    -fx-stroke: transparent;
+    -fx-stroke-width: 0;
+}
+.chart-vertical-zero-line {
+    -fx-stroke: #999999;
+}
+.chart-horizontal-zero-line {
+    -fx-stroke: #999999;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * ScatterChart                                                                *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart-symbol { /* solid circle */
+    -fx-background-color: #f9d900;
+    -fx-background-radius: 5px;
+    -fx-padding: 5px;
+}
+.default-color1.chart-symbol { /* solid square */
+    -fx-background-color: #a9e200;
+    -fx-background-radius: 0;
+}
+.default-color2.chart-symbol { /* solid diamond */
+    -fx-background-color: #22bad9;
+    -fx-background-radius: 0;
+    -fx-padding: 7px 5px 7px 5px;
+    -fx-shape: "M5,0 L10,9 L5,18 L0,9 Z";
+}
+.default-color3.chart-symbol { /* cross */
+    -fx-background-color: #0181e2;
+    -fx-background-radius: 0;
+    -fx-background-insets: 0;
+    -fx-shape: "M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z";
+}
+.default-color4.chart-symbol { /* solid triangle */
+    -fx-background-color: #2f357f;
+    -fx-background-radius: 0;
+    -fx-background-insets: 0;
+    -fx-shape: "M5,0 L10,8 L0,8 Z";
+}
+.default-color5.chart-symbol { /* hollow circle */
+    -fx-background-color: #860061, white;
+    -fx-background-insets: 0, 2;
+    -fx-background-radius: 5px;
+    -fx-padding: 5px;
+}
+.default-color6.chart-symbol { /* hollow square */
+    -fx-background-color: #c62b00, white;
+    -fx-background-insets: 0, 2;
+    -fx-background-radius: 0;
+}
+.default-color7.chart-symbol { /* hollow diamond */
+    -fx-background-color: #ff5700, white;
+    -fx-background-radius: 0;
+    -fx-background-insets: 0, 2.5;
+    -fx-padding: 7px 5px 7px 5px;
+    -fx-shape: "M5,0 L10,9 L5,18 L0,9 Z";
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * LineChart                                                                     *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart-line-symbol {
+    -fx-background-color: #f9d900, white;
+    -fx-background-insets: 0, 2;
+    -fx-background-radius: 5px;
+    -fx-padding: 5px;
+}
+.chart-series-line {
+    -fx-stroke: #f9d900;
+    -fx-stroke-width: 4px;
+    -fx-effect: dropshadow( two-pass-box , rgba(0,0,0,0.3) , 8, 0.0 , 0 , 3 );
+}
+.default-color0.chart-line-symbol { -fx-background-color: #f9d900, white; }
+.default-color1.chart-line-symbol { -fx-background-color: #a9e200, white; }
+.default-color2.chart-line-symbol { -fx-background-color: #22bad9, white; }
+.default-color3.chart-line-symbol { -fx-background-color: #0181e2, white; }
+.default-color4.chart-line-symbol { -fx-background-color: #2f357f, white; }
+.default-color5.chart-line-symbol { -fx-background-color: #860061, white; }
+.default-color6.chart-line-symbol { -fx-background-color: #c62b00, white; }
+.default-color7.chart-line-symbol { -fx-background-color: #ff5700, white; }
+.default-color0.chart-series-line { -fx-stroke: #f9d900; }
+.default-color1.chart-series-line { -fx-stroke: #a9e200; }
+.default-color2.chart-series-line { -fx-stroke: #22bad9; }
+.default-color3.chart-series-line { -fx-stroke: #0181e2; }
+.default-color4.chart-series-line { -fx-stroke: #2f357f; }
+.default-color5.chart-series-line { -fx-stroke: #860061; }
+.default-color6.chart-series-line { -fx-stroke: #c62b00; }
+.default-color7.chart-series-line { -fx-stroke: #ff5700; }
+
+/*******************************************************************************
+ *                                                                             *
+ * AreaChart                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart-area-symbol {
+    -fx-background-color: #f9d900, white;
+    -fx-background-insets: 0, 1;
+    -fx-background-radius: 4px; /* makes sure this remains circular */
+    -fx-padding: 3px;
+}
+.default-color0.chart-area-symbol { -fx-background-color: #f9d900, white; }
+.default-color1.chart-area-symbol { -fx-background-color: #a9e200, white; }
+.default-color2.chart-area-symbol { -fx-background-color: #22bad9, white; }
+.default-color3.chart-area-symbol { -fx-background-color: #0181e2, white; }
+.default-color4.chart-area-symbol { -fx-background-color: #2f357f, white; }
+.default-color5.chart-area-symbol { -fx-background-color: #860061, white; }
+.default-color6.chart-area-symbol { -fx-background-color: #c62b00, white; }
+.default-color7.chart-area-symbol { -fx-background-color: #ff5700, white; }
+.chart-series-area-line {
+    -fx-stroke: #f9d900;
+    -fx-stroke-width: 1px;
+}
+.default-color0.chart-series-area-line { -fx-stroke: #c2a902; }
+.default-color1.chart-series-area-line { -fx-stroke: #88b501; }
+.default-color2.chart-series-area-line { -fx-stroke: #22bad9; }
+.default-color3.chart-series-area-line { -fx-stroke: #0181e2; }
+.default-color4.chart-series-area-line { -fx-stroke: #2f357f; }
+.default-color5.chart-series-area-line { -fx-stroke: #860061; }
+.default-color6.chart-series-area-line { -fx-stroke: #c62b00; }
+.default-color7.chart-series-area-line { -fx-stroke: #ff5700; }
+.chart-series-area-fill {
+    -fx-stroke: null;
+    -fx-fill: #f9d90044;
+}
+.default-color0.chart-series-area-fill { -fx-fill: #f9d90044; }
+.default-color1.chart-series-area-fill { -fx-fill: #a9e20044; }
+.default-color2.chart-series-area-fill { -fx-fill: #22bad944; }
+.default-color3.chart-series-area-fill { -fx-fill: #0181e244; }
+.default-color4.chart-series-area-fill { -fx-fill: #2f357f44; }
+.default-color5.chart-series-area-fill { -fx-fill: #86006144; }
+.default-color6.chart-series-area-fill { -fx-fill: #c62b0044; }
+.default-color7.chart-series-area-fill { -fx-fill: #ff570044; }
+.area-legend-symbol {
+    -fx-padding: 6px;
+    -fx-background-radius: 6px; /* makes sure this remains circular */
+    -fx-background-insets: 0, 3;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * BubbleChart                                                                 *
+ *                                                                             *
+ ******************************************************************************/
+
+.bubble-legend-symbol {
+    -fx-background-radius: 8px;
+    -fx-padding: 8px;
+}
+.chart-bubble {
+    -fx-bubble-fill: #f9d900;
+    -fx-background-color: radial-gradient(center 50% 50%, radius 80%, derive(-fx-bubble-fill,20%), derive(-fx-bubble-fill,-30%));
+}
+.default-color0.chart-bubble { -fx-bubble-fill: #f9d900aa; }
+.default-color1.chart-bubble { -fx-bubble-fill: #a9e200aa; }
+.default-color2.chart-bubble { -fx-bubble-fill: #22bad9aa; }
+.default-color3.chart-bubble { -fx-bubble-fill: #0181e2aa; }
+.default-color4.chart-bubble { -fx-bubble-fill: #2f357faa; }
+.default-color5.chart-bubble { -fx-bubble-fill: #860061aa; }
+.default-color6.chart-bubble { -fx-bubble-fill: #c62b00aa; }
+.default-color7.chart-bubble { -fx-bubble-fill: #ff5700aa; }
+
+/*******************************************************************************
+ *                                                                             *
+ * BarChart                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+/* TODO flip gradient vertical for negative bars */
+.chart-bar {
+    -fx-bar-fill: #22bad9;
+    -fx-background-color: linear-gradient(derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
+                          linear-gradient(derive(-fx-bar-fill,80%), derive(-fx-bar-fill, 0%)),
+                          linear-gradient(derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
+    -fx-background-insets: 0,1,2;
+    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
+}
+
+.negative.chart-bar {
+   -fx-background-color: linear-gradient(to top, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
+                          linear-gradient(to top, derive(-fx-bar-fill, 80%), derive(-fx-bar-fill,0%)),
+                          linear-gradient(to top, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
+   -fx-background-radius: 0 0 5 5, 0 0 4 4, 0 0 3 3;
+}
+.bar-chart:horizontal .chart-bar, .stacked-bar-chart:horizontal .chart-bar {
+    -fx-background-color: linear-gradient(to left, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
+                          linear-gradient(to left, derive(-fx-bar-fill,80%), derive(-fx-bar-fill, 0%)),
+                          linear-gradient(to left, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
+    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
+}
+.bar-chart:horizontal .negative.chart-bar, .stacked-bar-chart:horizontal .negative.chart-bar {
+    -fx-background-color: linear-gradient(to right, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
+                          linear-gradient(to right, derive(-fx-bar-fill, 80%), derive(-fx-bar-fill, 0%)),
+                          linear-gradient(to right, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
+    -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3;
+}
+.default-color0.chart-bar { -fx-bar-fill: #f9d900; }
+.default-color1.chart-bar { -fx-bar-fill: #a9e200; }
+.default-color2.chart-bar { -fx-bar-fill: #22bad9; }
+.default-color3.chart-bar { -fx-bar-fill: #0181e2; }
+.default-color4.chart-bar { -fx-bar-fill: #2f357f; }
+.default-color5.chart-bar { -fx-bar-fill: #860061; }
+.default-color6.chart-bar { -fx-bar-fill: #c62b00; }
+.default-color7.chart-bar { -fx-bar-fill: #ff5700; }
+.bar-legend-symbol {
+    -fx-padding: 8px;
+}
+
+/*******************************************************************************
+ *                                                                             *
+ * PieChart                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.chart-pie {
+    -fx-pie-color: #2f357f;
+    -fx-background-color: radial-gradient(radius 100%, derive(-fx-pie-color,55%), derive(-fx-pie-color,-20%));
+    -fx-background-insets: 0;
+    -fx-border-color: derive(-fx-pie-color,-30%);
+}
+.chart-pie-label {
+    -fx-padding: 3px;
+}
+.chart-pie-label-line {
+    -fx-stroke: #aaaaaa;
+    -fx-fill: #aaaaaa;
+}
+.default-color0.chart-pie { -fx-pie-color: #f9d900; }
+.default-color1.chart-pie { -fx-pie-color: #a9e200; }
+.default-color2.chart-pie { -fx-pie-color: #22bad9; }
+.default-color3.chart-pie { -fx-pie-color: #0181e2; }
+.default-color4.chart-pie { -fx-pie-color: #2f357f; }
+.default-color5.chart-pie { -fx-pie-color: #860061; }
+.default-color6.chart-pie { -fx-pie-color: #c62b00; }
+.default-color7.chart-pie { -fx-pie-color: #ff5700; }
+.negative.chart-pie {
+    -fx-pie-color: transparent;
+    -fx-background-color: white;
+}
+.pie-legend-symbol.chart-pie {
+    -fx-background-radius: 8px;
+    -fx-padding: 8px;
+    -fx-border-color: null;
 }
\ No newline at end of file
--- a/apps/experiments/Modena/src/modena/Modena.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/apps/experiments/Modena/src/modena/Modena.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1,177 +1,371 @@
+/*
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 package modena;
 
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringBufferInputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javafx.application.Application;
 import javafx.application.Platform;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.embed.swing.SwingFXUtils;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
-import javafx.scene.Group;
+import javafx.fxml.FXMLLoader;
 import javafx.scene.Node;
 import javafx.scene.Scene;
+import javafx.scene.SnapshotParameters;
+import javafx.scene.control.ButtonBuilder;
+import javafx.scene.control.ColorPicker;
 import javafx.scene.control.Label;
-import javafx.scene.control.ScrollPane;
+import javafx.scene.control.ScrollPaneBuilder;
 import javafx.scene.control.Separator;
+import javafx.scene.control.TabBuilder;
+import javafx.scene.control.TabPane;
 import javafx.scene.control.ToggleButton;
 import javafx.scene.control.ToggleButtonBuilder;
 import javafx.scene.control.ToggleGroup;
 import javafx.scene.control.ToolBar;
+import javafx.scene.image.WritableImage;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.HBoxBuilder;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import javafx.scene.transform.Scale;
+import javafx.stage.FileChooser;
 import javafx.stage.Stage;
+import javax.imageio.ImageIO;
 
 public class Modena extends Application {
     static {
         System.getProperties().put("javafx.pseudoClassOverrideEnabled", "true");
     }
+    private static final String testAppCssUrl = Modena.class.getResource("TestApp.css").toExternalForm();
     
     private BorderPane root;
+    private SamplePage samplePage;
+    private Node mosaic;
+    private Stage mainStage;
     
     @Override public void start(Stage stage) throws Exception {
+        mainStage = stage;
         // build UI
-        rebuildUI(true, false);
+        rebuildUI(true, false,0);
         // show UI
         Scene scene = new Scene(root, 1024, 768);
-        scene.getStylesheets().add(
-                getClass().getResource("TestApp.css").toExternalForm());
+        scene.getStylesheets().add(testAppCssUrl);
         stage.setScene(scene);
         stage.show();
     }
     
-    private void rebuildUI(boolean modena, boolean retina) {
-        // load theme
-        if (modena) {
-            setUserAgentStylesheet(
-                    getClass().getResource("Modena.css").toExternalForm());
-        } else {
-            setUserAgentStylesheet(null);
-        }
-        if (root == null) {
-            root = new BorderPane();
-        } else {
-            // clear out old UI
-            root.setTop(null);
-            root.setCenter(null);
-        }
-        // Create Toolbar
-        final Group contentGroup = new Group();
-        final ScrollPane contentScrollPane = new ScrollPane();
-        final ToggleButton modenaButton;;
-        final ToggleButton retinaButton = ToggleButtonBuilder.create()
-            .text("Retina @2x")
-            .selected(retina)
-            .onAction(new EventHandler<ActionEvent>(){
-                @Override public void handle(ActionEvent event) {
-                    ToggleButton btn = (ToggleButton)event.getSource();
-                    Node content = contentGroup.getChildren().get(0);
-                    if (btn.isSelected()) {
-                        content.setScaleX(2);
-                        content.setScaleY(2);
-                    } else {
-                        content.setScaleX(1);
-                        content.setScaleY(1);
+    private void rebuildUI(boolean modena, boolean retina, int selectedTab) {
+        try {
+            // load theme
+            if (modena) {
+                setUserAgentStylesheet(
+                        getClass().getResource("Modena.css").toExternalForm());
+            } else {
+                setUserAgentStylesheet(null);
+            }
+            if (root == null) {
+                root = new BorderPane();
+            } else {
+                // clear out old UI
+                root.setTop(null);
+                root.setCenter(null);
+            }
+            // Create Content Area
+            final TabPane contentTabs = new TabPane();
+            contentTabs.getTabs().addAll(
+                TabBuilder.create().text("All Controls").content(
+                    ScrollPaneBuilder.create().content(
+                        samplePage = new SamplePage()
+                    ).build()
+                ).build(),
+                TabBuilder.create().text("UI Mosaic").content(
+                    ScrollPaneBuilder.create().content(
+                        mosaic = (Node)FXMLLoader.load(Modena.class.getResource("ui-mosaic.fxml"))
+                    ).build()
+                ).build()
+            );
+            contentTabs.getSelectionModel().select(selectedTab);
+            // set white background for caspian
+            if (!modena) {
+                samplePage.setStyle("-fx-background-color: white;");
+                mosaic.setStyle("-fx-background-color: white;");
+            }
+            // Create Toolbar
+            final ToggleButton modenaButton;;
+            final ToggleButton retinaButton = ToggleButtonBuilder.create()
+                .text("Retina @2x")
+                .selected(retina)
+                .onAction(new EventHandler<ActionEvent>(){
+                    @Override public void handle(ActionEvent event) {
+                        ToggleButton btn = (ToggleButton)event.getSource();
+                        if (btn.isSelected()) {
+                            contentTabs.getTransforms().setAll(new Scale(2,2));
+                        } else {
+                            contentTabs.getTransforms().setAll(new Scale(1,1));
+                        }
+                        contentTabs.requestLayout();
                     }
+                })
+                .build();
+            ToggleGroup themesToggleGroup = new ToggleGroup();
+            ToggleGroup colorToggleGroup = new ToggleGroup();
+            ToolBar toolBar = new ToolBar(
+                HBoxBuilder.create()
+                    .children(
+                        modenaButton = ToggleButtonBuilder.create()
+                            .text("Modena")
+                            .toggleGroup(themesToggleGroup)
+                            .selected(modena)
+                            .onAction(new EventHandler<ActionEvent>(){
+                                @Override public void handle(ActionEvent event) { 
+                                    rebuildUI(true,retinaButton.isSelected(), contentTabs.getSelectionModel().getSelectedIndex());
+                                }
+                            })
+                            .styleClass("left-pill")
+                            .build(),
+                        ToggleButtonBuilder.create()
+                            .text("Caspian")
+                            .toggleGroup(themesToggleGroup)
+                            .selected(!modena)
+                            .onAction(new EventHandler<ActionEvent>(){
+                                @Override public void handle(ActionEvent event) { 
+                                    rebuildUI(false,retinaButton.isSelected(), contentTabs.getSelectionModel().getSelectedIndex());
+                                }
+                            })
+                            .styleClass("right-pill")
+                            .build()
+                    )
+                    .build(),
+                new Separator(),
+                retinaButton,
+                new Separator(),
+                new Label("Base:"),
+                createBaseColorPicker(),
+                new Separator(),
+                new Label("Accent:"),
+                createAccentColorPicker(),
+                new Separator(),
+                ButtonBuilder.create().text("Save...").onAction(saveBtnHandler).build()
+            );
+            // Create content group used for scaleing @2x
+            final Pane contentGroup = new Pane() {
+                @Override protected void layoutChildren() {
+                    double scale = contentTabs.getTransforms().isEmpty() ? 1 : ((Scale)contentTabs.getTransforms().get(0)).getX();
+                    contentTabs.resizeRelocate(0,0,getWidth()/scale, getHeight()/scale);
                 }
-            })
-            .build();
-        ToggleGroup themesToggleGroup = new ToggleGroup();
-        ToggleGroup colorToggleGroup = new ToggleGroup();
-        ToolBar toolBar = new ToolBar(
-            HBoxBuilder.create()
-                .children(
-                    modenaButton = ToggleButtonBuilder.create()
-                        .text("Modena")
-                        .toggleGroup(themesToggleGroup)
-                        .selected(modena)
-                        .onAction(new EventHandler<ActionEvent>(){
-                            @Override public void handle(ActionEvent event) { 
-                                rebuildUI(true,retinaButton.isSelected());
-                            }
-                        })
-                        .styleClass("left-pill")
-                        .build(),
-                    ToggleButtonBuilder.create()
-                        .text("Caspian")
-                        .toggleGroup(themesToggleGroup)
-                        .selected(!modena)
-                        .onAction(new EventHandler<ActionEvent>(){
-                            @Override public void handle(ActionEvent event) { 
-                                rebuildUI(false,retinaButton.isSelected());
-                            }
-                        })
-                        .styleClass("right-pill")
-                        .build()
-                )
-                .build(),
-            new Separator(),
-            retinaButton,
-            new Separator(),
-            new Label("Base Color:"),
-            HBoxBuilder.create()
-                .spacing(3)
-                .children(
-                    createColorButton(null, colorToggleGroup, modena),
-                    createColorButton("#f3622d", colorToggleGroup, modena),
-                    createColorButton("#fba71b", colorToggleGroup, modena),
-                    createColorButton("#57b757", colorToggleGroup, modena),
-                    createColorButton("#41a9c9", colorToggleGroup, modena),
-                    createColorButton("#888", colorToggleGroup, modena),
-                    createColorButton("red", colorToggleGroup, modena),
-                    createColorButton("orange", colorToggleGroup, modena),
-                    createColorButton("yellow", colorToggleGroup, modena),
-                    createColorButton("green", colorToggleGroup, modena),
-                    createColorButton("cyan", colorToggleGroup, modena),
-                    createColorButton("blue", colorToggleGroup, modena),
-                    createColorButton("purple", colorToggleGroup, modena),
-                    createColorButton("magenta", colorToggleGroup, modena),
-                    createColorButton("black", colorToggleGroup, modena)
-                )
-                .build()
-        );
-        root.setTop(toolBar);
-        contentScrollPane.setContent(contentGroup);
-        root.setCenter(contentScrollPane);
-        // create sample page
-        contentGroup.getChildren().setAll(new SamplePage());
-        // move foucus out of the way
-        Platform.runLater(new Runnable() {
-            @Override public void run() {
-                modenaButton.requestFocus();
+            };
+            contentGroup.getChildren().add(contentTabs);
+            // populate root
+            root.setTop(toolBar);
+            root.setCenter(contentGroup);
+            // move foucus out of the way
+            Platform.runLater(new Runnable() {
+                @Override public void run() {
+                    modenaButton.requestFocus();
+                }
+            });
+            // apply retina scale
+            if (retina) {
+                contentTabs.getTransforms().setAll(new Scale(2,2));
             }
-        });
-        // apply retina scale
-        if (retina) {
-            Node content = contentGroup.getChildren().get(0);
-            content.setScaleX(2);
-            content.setScaleY(2);
+        } catch (IOException ex) {
+            Logger.getLogger(Modena.class.getName()).log(Level.SEVERE, null, ex);
         }
     }
     
-    private ToggleButton createColorButton(final String color, ToggleGroup toggleGroup, boolean modena) {
-        final boolean isBase = color == null;
-        String colorCSS;
-        if (!isBase) {
-            colorCSS = "-fx-base: "+color+";";
-        } else {
-            colorCSS = "-fx-base: "+(modena ? "#ececec" : "#d0d0d0")+";";
+    private ColorPicker createBaseColorPicker() {
+        ColorPicker colorPicker = new ColorPicker(Color.TRANSPARENT);
+        colorPicker.getCustomColors().addAll(
+                Color.TRANSPARENT,
+                Color.web("#f3622d"),
+                Color.web("#fba71b"),
+                Color.web("#57b757"),
+                Color.web("#41a9c9"),
+                Color.web("#888"),
+                Color.RED,
+                Color.ORANGE,
+                Color.YELLOW,
+                Color.GREEN,
+                Color.CYAN,
+                Color.BLUE,
+                Color.PURPLE,
+                Color.MAGENTA,
+                Color.BLACK
+        );
+        colorPicker.valueProperty().addListener(new ChangeListener<Color>() {
+            @Override public void changed(ObservableValue<? extends Color> observable, Color oldValue, Color c) {
+                if (c == null) {
+                    baseColor = null;
+                } else {
+                    baseColor = c;
+                }
+                updateCSSOverrides();
+            }
+        });
+        return colorPicker;
+    }
+    
+    private ColorPicker createAccentColorPicker() {
+        ColorPicker colorPicker = new ColorPicker(Color.web("#0096C9"));
+        colorPicker.getCustomColors().addAll(
+                Color.TRANSPARENT,
+                Color.web("#0096C9"),
+                Color.web("#4fb6d6"),
+                Color.web("#f3622d"),
+                Color.web("#fba71b"),
+                Color.web("#57b757"),
+                Color.web("#41a9c9"),
+                Color.web("#888"),
+                Color.RED,
+                Color.ORANGE,
+                Color.YELLOW,
+                Color.GREEN,
+                Color.CYAN,
+                Color.BLUE,
+                Color.PURPLE,
+                Color.MAGENTA,
+                Color.BLACK
+        );
+        colorPicker.valueProperty().addListener(new ChangeListener<Color>() {
+            @Override public void changed(ObservableValue<? extends Color> observable, Color oldValue, Color c) {
+                if (c == null) {
+                    accentColor = null;
+                } else {
+                    accentColor = c;
+                }
+                updateCSSOverrides();
+            }
+        });
+        return colorPicker;
+    }
+    
+    private Color baseColor;
+    private Color accentColor;
+    private String cssOverride = "";
+    
+    private void updateCSSOverrides() {
+        cssOverride = ".root {\n";
+        System.out.println("baseColor = "+baseColor);
+        System.out.println("accentColor = " + accentColor);
+        if (baseColor != null && baseColor != Color.TRANSPARENT) {
+            final String color = String.format((Locale) null, "#%02x%02x%02x", 
+                    Math.round(baseColor.getRed() * 255), 
+                    Math.round(baseColor.getGreen() * 255), 
+                    Math.round(baseColor.getBlue() * 255));
+            cssOverride += "    -fx-base:"+color+";\n";
         }
-        return ToggleButtonBuilder.create()
-            .text(isBase?"default":null)
-            .style(colorCSS)
-            .toggleGroup(toggleGroup)
-            .selected(isBase)
-            .onAction(new EventHandler<ActionEvent>(){
-                @Override public void handle(ActionEvent event) { 
-                    if (isBase) {
-                        root.setStyle(null);
-                    } else {
-                        root.setStyle("-fx-base: "+color+";");
-                    }
+        if (accentColor != null && accentColor != Color.TRANSPARENT) {
+            final String color = String.format((Locale) null, "#%02x%02x%02x", 
+                    Math.round(accentColor.getRed() * 255), 
+                    Math.round(accentColor.getGreen() * 255), 
+                    Math.round(accentColor.getBlue() * 255));
+            cssOverride += "    -fx-accent:"+color+";\n";
+        }
+        cssOverride += "}\n";
+        System.out.println("cssOverride = " + cssOverride);
+        mainStage.getScene().getStylesheets().setAll(testAppCssUrl,"internal:stylesheet.css");
+    }
+    
+    private EventHandler<ActionEvent> saveBtnHandler = new EventHandler<ActionEvent>() {
+        @Override public void handle(ActionEvent event) {
+            FileChooser fc = new FileChooser();
+            fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG", "*.png"));
+            File file = fc.showSaveDialog(mainStage);
+            if (file != null) {
+                try {
+                    samplePage.getStyleClass().add("root");
+                    WritableImage img = samplePage.snapshot(new SnapshotParameters(), null);
+                    ImageIO.write(SwingFXUtils.fromFXImage(img, null), "PNG", file);
+                } catch (IOException ex) {
+                    Logger.getLogger(Modena.class.getName()).log(Level.SEVERE, null, ex);
                 }
-            })
-            .styleClass("color-well")
-            .build();
-    }
+            }
+        }
+    };
     
     public static void main(String[] args) {
         launch(args);
     }
+    
+    // =========================================================================
+    // URL Handler to create magic "internal:stylesheet.css" url for our css string buffer
+    {
+        URL.setURLStreamHandlerFactory(new StringURLStreamHandlerFactory());
+    }
+    
+    /**
+     * Simple URLConnection that always returns the content of the cssBuffer
+     */
+    private class StringURLConnection extends URLConnection {
+        public StringURLConnection(URL url){
+            super(url);
+        }
+        
+        @Override public void connect() throws IOException {}
+
+        @Override public InputStream getInputStream() throws IOException {
+            return new ByteArrayInputStream(cssOverride.getBytes("UTF-8"));
+        }
+    }
+    
+    private class StringURLStreamHandlerFactory implements URLStreamHandlerFactory {
+        URLStreamHandler streamHandler = new URLStreamHandler(){
+            @Override protected URLConnection openConnection(URL url) throws IOException {
+                if (url.toString().toLowerCase().endsWith(".css")) {
+                    return new StringURLConnection(url);
+                }
+                throw new FileNotFoundException();
+            }
+        };
+        @Override public URLStreamHandler createURLStreamHandler(String protocol) {
+            if ("internal".equals(protocol)) {
+                return streamHandler;
+            }
+            return null;
+        }
+    }
 }
--- a/apps/experiments/Modena/src/modena/SamplePage.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/apps/experiments/Modena/src/modena/SamplePage.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1,6 +1,33 @@
 /*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 package modena;
 
@@ -12,21 +39,44 @@
 import javafx.scene.control.Button;
 import javafx.scene.control.ButtonBuilder;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.ChoiceBoxBuilder;
+import javafx.scene.control.ColorPickerBuilder;
+import javafx.scene.control.ComboBoxBuilder;
+import javafx.scene.control.Hyperlink;
 import javafx.scene.control.Label;
+import javafx.scene.control.LabelBuilder;
+import javafx.scene.control.MenuButtonBuilder;
+import javafx.scene.control.PasswordFieldBuilder;
 import javafx.scene.control.ProgressBar;
+import javafx.scene.control.ProgressIndicator;
+import javafx.scene.control.ProgressIndicatorBuilder;
 import javafx.scene.control.RadioButton;
 import javafx.scene.control.ScrollBar;
 import javafx.scene.control.ScrollBarBuilder;
-import javafx.scene.control.Separator;
+import javafx.scene.control.ScrollPaneBuilder;
 import javafx.scene.control.SeparatorBuilder;
 import javafx.scene.control.Slider;
+import javafx.scene.control.SliderBuilder;
+import javafx.scene.control.SplitMenuButtonBuilder;
+import javafx.scene.control.TextAreaBuilder;
+import javafx.scene.control.TextField;
+import javafx.scene.control.TextFieldBuilder;
+import javafx.scene.control.TitledPaneBuilder;
 import javafx.scene.control.ToggleButton;
 import javafx.scene.control.ToggleButtonBuilder;
 import javafx.scene.control.ToggleGroup;
+import javafx.scene.control.Tooltip;
+import javafx.scene.control.TooltipBuilder;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.HBoxBuilder;
 import javafx.scene.layout.VBox;
+import javafx.scene.layout.VBoxBuilder;
+import javafx.scene.paint.Color;
+import static modena.SamplePageHelpers.*;
+import static modena.SamplePageTableHelper.*;
+import static modena.SamplePageTreeHelper.*;
+import static modena.SamplePageTreeTableHelper.*;
 
 /**
  * Page showing every control in every state
@@ -110,7 +160,7 @@
         ToggleGroup tg2 = new ToggleGroup();
         ToggleGroup tg3 = new ToggleGroup();
         ToggleGroup tg4 = new ToggleGroup();
-        newSection("Pill Buttons:", 
+        newSection("Pill Toggle\nButtons:", 
                 HBoxBuilder.create()
                     .children(
                         ToggleButtonBuilder.create().text("Left").styleClass("left-pill").toggleGroup(tg1).build(),
@@ -195,42 +245,250 @@
                 withState(new RadioButton("Focused & Hover"), "selected, focused, hover"),
                 withState(new RadioButton("Focused & Armed"), "selected, focused, armed"),
                 withState(new RadioButton("Disabled"), "selected, disabled"));
-        newSection("Slider:", 
-                new Slider(0,100,50),
-                withState(new Slider(0,100,50), null, ".thumb", "hover"),
-                withState(new Slider(0,100,50), null, ".thumb", "hover, pressed"),
-                withState(new Slider(0,100,50), "disabled"));
-        newSection("Slider Focused:", 
-                withState(new Slider(0,100,50), "focused"),
-                withState(new Slider(0,100,50), "focused", ".thumb", "hover"),
-                withState(new Slider(0,100,50), "focused", ".thumb", "hover, pressed"));
-        newDetailedSection(
-                new String[] {"Scrollbar - V: ", "normal", "focused", ".thumb hover", ".thumb pressed"}, 
-                new ScrollBar(),
-                withState(new ScrollBar(), "horizontal, focused"),
-                withState(new ScrollBar(), "horizontal", ".thumb", "hover"),
-                withState(new ScrollBar(), "horizontal", ".thumb", "pressed")
+        newSection("HyperLink:", 
+                new Hyperlink("Hyperlink"),
+                withState(new Hyperlink("Visited"), "visited"),
+                withState(new Hyperlink("Hover"), "hover"),
+                withState(new Hyperlink("Armed"), "armed"),
+                withState(new Hyperlink("Focused"), "focused"),
+                withState(new Hyperlink("F & Visited"), "focused, visited"),
+                withState(new Hyperlink("F & Hover"), "focused, hover"),
+                withState(new Hyperlink("F & Armed"), "focused, armed"),
+                withState(new Hyperlink("Disabled"), "disabled"));
+        newSection(      
+                "ChoiceBox:", 
+                ChoiceBoxBuilder.create(String.class).items(sampleItems()).value("Item A").build(),
+                withState(ChoiceBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "hover"),
+                withState(ChoiceBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "showing"),
+                withState(ChoiceBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "focused"),
+                withState(ChoiceBoxBuilder.create(String.class).items(sampleItems()).value("Item C").build(), "disabled")
+                );
+        newSection(      
+                "ComboBox:", 
+                ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item A").build(),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "hover"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "showing"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").build(), "focused"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item C").build(), "disabled")
+                );
+        newSection(      
+                "ComboBox\nEditable:", 
+                ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item A").editable(true).build(),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").editable(true).build(), "hover"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").editable(true).build(), "showing"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item B").editable(true).build(), "focused"),
+                withState(ComboBoxBuilder.create(String.class).items(sampleItems()).value("Item C").editable(true).build(), "disabled")
+                );
+        newSection(      
+                "Color Picker:", 
+                ColorPickerBuilder.create().value(Color.DODGERBLUE).build(),
+                withState(ColorPickerBuilder.create().value(Color.DODGERBLUE).build(), "hover"),
+                withState(ColorPickerBuilder.create().value(Color.DODGERBLUE).build(), "showing"),
+                withState(ColorPickerBuilder.create().value(Color.DODGERBLUE).build(), "focused"),
+                withState(ColorPickerBuilder.create().value(Color.DODGERBLUE).build(), "disabled")
+                );
+        newSection(      
+                "MenuButton:", 
+                MenuButtonBuilder.create().items(createMenuItems(20)).text("normal").build(),
+                withState(MenuButtonBuilder.create().items(createMenuItems(20)).text("hover").build(), "hover"),
+                withState(MenuButtonBuilder.create().items(createMenuItems(20)).text("armed").build(), "armed"),
+                withState(MenuButtonBuilder.create().items(createMenuItems(20)).text("focused").build(), "focused"),
+                withState(MenuButtonBuilder.create().items(createMenuItems(20)).text("disabled").build(), "disabled")
+                );
+        newSection(      
+                "SplitMenuButton:", 
+                SplitMenuButtonBuilder.create().items(createMenuItems(20)).text("normal").build(),
+                withState(SplitMenuButtonBuilder.create().items(createMenuItems(20)).text("hover").build(), "hover"),
+                withState(SplitMenuButtonBuilder.create().items(createMenuItems(20)).text("armed").build(), "armed"),
+                withState(SplitMenuButtonBuilder.create().items(createMenuItems(20)).text("focused").build(), "focused"),
+                withState(SplitMenuButtonBuilder.create().items(createMenuItems(20)).text("disabled").build(), "disabled")
                 );
         newDetailedSection(
-                new String[] {"Scrollbar - V: ", "normal", "focused", ".thumb hover", ".thumb pressed"}, 
+                new String[]{"Slider - H: ", "normal", "hover", "pressed", "disabled", "tickmarks"},
+                withState(SliderBuilder.create().maxWidth(90).min(0).max(100).value(50).build(), null),
+                withState(SliderBuilder.create().maxWidth(90).min(0).max(100).value(50).build(), null, ".thumb", "hover"),
+                withState(SliderBuilder.create().maxWidth(90).min(0).max(100).value(50).build(), null, ".thumb", "hover, pressed"),
+                withState(SliderBuilder.create().maxWidth(90).min(0).max(100).value(50).build(), "disabled"),
+                SliderBuilder.create().min(0).max(100).value(50).showTickMarks(true).showTickLabels(true).build());
+        newDetailedSection(
+                new String[]{"Slider - H - Focused: ", "normal", "hover", "pressed"},
+                withState(new Slider(0, 100, 50), "focused"),
+                withState(new Slider(0, 100, 50), "focused", ".thumb", "hover"),
+                withState(new Slider(0, 100, 50), "focused", ".thumb", "hover, pressed"));
+        newSection("Slider - V:",
+                SliderBuilder.create().min(0).max(100).value(50).orientation(Orientation.VERTICAL).build(),
+                withState(SliderBuilder.create().min(0).max(100).value(50).orientation(Orientation.VERTICAL).build(), null, ".thumb", "hover"),
+                withState(SliderBuilder.create().min(0).max(100).value(50).orientation(Orientation.VERTICAL).build(), null, ".thumb", "hover, pressed"),
+                withState(SliderBuilder.create().min(0).max(100).value(50).orientation(Orientation.VERTICAL).build(), "disabled"),
+                SliderBuilder.create().min(0).max(100).value(50).showTickMarks(true).showTickLabels(true).orientation(Orientation.VERTICAL).build());
+        newDetailedSection(
+                new String[] {"Scrollbar - H: ", "normal", "small", "big thumb"}, 
+                new ScrollBar(),
+                ScrollBarBuilder.create().minWidth(30).prefWidth(30).build(),
+                ScrollBarBuilder.create().visibleAmount(60).max(100).build()
+                );
+        newDetailedSection(
+                new String[] {"Scrollbar - V: ", "normal", "small", "btn hover", "btn pressed", ".thumb hover", ".thumb pressed"}, 
                 withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical"),
-                withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical, focused"),
+                withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).minHeight(30).prefHeight(30).build(), "vertical"),
+                withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical", ".decrement-button", "hover"),
+                withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical", ".decrement-button", "pressed"),
                 withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical", ".thumb", "hover"),
                 withState(ScrollBarBuilder.create().orientation(Orientation.VERTICAL).build(), "vertical", ".thumb", "pressed")
                 );
-        newSection(      
-                "Separator - H:", 
-                new Separator()
-                );
-        newSection(      
-                "Separator - V:", 
-                SeparatorBuilder.create().orientation(Orientation.VERTICAL).build()
+        newDetailedSection(
+                new String[] {"ScrollPane: ", "normal", "small", "focused"}, 
+                ScrollPaneBuilder.create().content(scrollPaneContent()).build(),
+                ScrollPaneBuilder.create().content(scrollPaneContent()).minWidth(40).prefWidth(40).minHeight(40).prefHeight(40).build(),
+                withState(ScrollPaneBuilder.create().content(scrollPaneContent()).build(), "focused")
+                ); 
+        newDetailedSection(
+                new String[] {"Separator: ", "horizontal", "vertical"}, 
+                SeparatorBuilder.create().prefWidth(100).build(),
+                SeparatorBuilder.create().orientation(Orientation.VERTICAL).prefHeight(50).build()
                 );
         newDetailedSection(
                 new String[] {"ProgressBar: ", "normal", "disabled", "indeterminate"}, 
-                new ProgressBar(0.6F),
+                new ProgressBar(0.6),
                 withState(new ProgressBar(), "disabled"),
-                withState(new ProgressBar(), "indeterminate")
+                new ProgressBar(-1)
+                );
+        newDetailedSection(
+                new String[] {"ProgressIndicator: ", "normal 0%", "normal 60%", "normal 100%", "disabled"}, 
+                new ProgressIndicator(0),
+                new ProgressIndicator(0.6),
+                new ProgressIndicator(1),
+                withState(new ProgressIndicator(0.5), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"ProgressIndicator\nIndeterminate: ", "normal", "small", "large", "disabled"}, 
+                ProgressIndicatorBuilder.create().progress(-1).maxWidth(USE_PREF_SIZE).maxHeight(USE_PREF_SIZE).build(),
+                ProgressIndicatorBuilder.create().progress(-1).prefWidth(30).prefHeight(30).build(),
+                ProgressIndicatorBuilder.create().progress(-1).prefWidth(60).prefHeight(60).build(),
+                ProgressIndicatorBuilder.create().progress(-1).maxWidth(USE_PREF_SIZE).maxHeight(USE_PREF_SIZE).disable(true).build()
+                );
+        newSection(      
+                "TextField:", 
+                new TextField("TextField"),
+                TextFieldBuilder.create().promptText("Prompt Text").build(),
+                withState(new TextField("Focused"), "focused"),
+                withState(new TextField("Disabled"), "disabled")
+                );
+        newSection(      
+                "PasswordField:", 
+                PasswordFieldBuilder.create().text("Password").build(),
+                PasswordFieldBuilder.create().promptText("Prompt Text").build(),
+                withState(PasswordFieldBuilder.create().text("Password").build(), "focused"),
+                withState(PasswordFieldBuilder.create().text("Password").build(), "disabled")
+                );
+        newSection(      
+                "TextArea:", 
+                TextAreaBuilder.create().text("TextArea").prefColumnCount(10).prefRowCount(2).build(),
+                TextAreaBuilder.create().text("Many Lines of\nText.\n#3\n#4\n#5\n#6\n#7\n#8\n#9\n#10").prefColumnCount(10).prefRowCount(3).build(),
+                TextAreaBuilder.create().text("Many Lines of\nText.\n#3\n#4\n#5\n#6\n#7\n#8\n#9\n#10").prefColumnCount(6).prefRowCount(3).build(),
+                TextAreaBuilder.create().promptText("Prompt Text").prefColumnCount(10).prefRowCount(2).build(),
+                withState(TextAreaBuilder.create().text("Focused").prefColumnCount(7).prefRowCount(2).build(), "focused"),
+                withState(TextAreaBuilder.create().text("Disabled").prefColumnCount(8).prefRowCount(2).build(), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"ToolBar (H):", "normal", "overflow", "disabled"}, 
+                createToolBar(false,false),
+                createToolBar(false,true),
+                withState(createToolBar(false,false), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"ToolBar (V):", "normal", "overflow", "disabled"}, 
+                createToolBar(true,false),
+                createToolBar(true,true),
+                withState(createToolBar(true,false), "disabled")
+                );
+        newSection(      
+                "Tabs:", 
+                createTabPane(3, 250,null,false),
+                withState(createTabPane(5, 200,"Tab Disabled &\nMany Tabs", false), null, ".tab", "disabled"),
+                withState(createTabPane(5, 200,"Disabled", false), "disabled")
+                );
+        newSection(      
+                "Tabs Floating:", 
+                createTabPane(3, 250,null,true),
+                withState(createTabPane(5, 200,"Tab Disabled &\nMany Tabs", true), null, ".tab", "disabled"),
+                withState(createTabPane(5, 200,"Disabled", true), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"TitledPane:", "normal", "focused", "disabled"}, 
+                TitledPaneBuilder.create().text("Title").content(new Label("Content\nLine2.")).build(),
+                withState(TitledPaneBuilder.create().text("Title").content(new Label("Content\nLine2.")).build(), "focused"),
+                withState(TitledPaneBuilder.create().text("Title").content(new Label("Content\nLine2.")).build(), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"Accordian:", "normal", "hover", "focused", "disabled"}, 
+                createAccordion(),
+                withState(createAccordion(), null, ".titled-pane", "hover"),
+                withState(createAccordion(), null, ".titled-pane", "focused"),
+                withState(createAccordion(), "disabled")
+                );
+        newDetailedSection(
+                new String[] {"SplitPane (H):", "simple", "many", "complex"}, 
+                createSplitPane(2,false,null),
+                createSplitPane(4,false,null),
+                createSplitPane(2,false,createSplitPane(2,true,null))
+                );
+        newDetailedSection(
+                new String[] {"SplitPane (V):", "simple", "many", "complex"}, 
+                createSplitPane(2,true,null),
+                createSplitPane(4,true,null),
+                createSplitPane(2,true,createSplitPane(2,false,null))
+                );
+        newDetailedSection(
+                new String[] {"Pagination:", "simple", "infinate"}, 
+                createPagination(5, false, true),
+                createPagination(Integer.MAX_VALUE, false, true)
+                );
+        newDetailedSection(
+                new String[] {"Pagination\nBullet Style:", "simple", "infinate"}, 
+                createPagination(5, true, true),
+                createPagination(Integer.MAX_VALUE, true, true)
+                );
+        newSection(
+                "Pagination\nNo Arrows:", 
+                createPagination(Integer.MAX_VALUE, false, false)
+                );
+        newDetailedSection(
+                new String[] {"ListView\n2 items\nsingle selection:", "normal", "focused", "disabled"}, 
+                createListView(3, false, false),
+                withState(createListView(3, false, false), "focused"),
+                createListView(3, false, true)
+                );
+        newDetailedSection(
+                new String[] {"ListView\n10,000 items\nmultiple selection:","normal", "focused", "disabled"}, 
+                createListView(10000, true, false),
+                withState(createListView(10000, true, false), "focused"),
+                createListView(10000, true, true)
+                );
+        newSection(
+                "TableView:", 
+                createTableView(550),
+                withState(createTableView(100), "focused")
+                );
+        newSection(
+                "TreeView:", 
+                createTreeView(350),
+                withState(createTreeView(350), "focused")
+                );
+        newSection(
+                "TreeTableView:", 
+                createTreeTableView(550),
+                withState(createTreeTableView(200), "focused")
+                );
+        newDetailedSection(
+                new String[] {"ToolTip:","inline","inline + graphic", "popup"}, 
+                LabelBuilder.create().text("This is a simple Tooltip.").styleClass("tooltip").build(),
+                LabelBuilder.create().text("This is a simple Tooltip\nwith graphic.").graphic(createGraphic()).styleClass("tooltip").build(),
+                VBoxBuilder.create().fillWidth(true).spacing(4).children(
+                    ButtonBuilder.create().text("Hover over me").tooltip(new Tooltip("This is a simple Tooltip.")).build(),
+                    ButtonBuilder.create().text("me too").tooltip(new Tooltip("This is a simple Tooltip\nwith more than one line.")).build(),
+                    ButtonBuilder.create().text("or me").tooltip(TooltipBuilder.create().text("This is a simple Tooltip\nwith graphic.").graphic(createGraphic()).build()).build()
+                ).build()
                 );
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/experiments/Modena/src/modena/SamplePageHelpers.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package modena;
+
+import java.util.ArrayList;
+import java.util.List;
+import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.Orientation;
+import javafx.scene.GroupBuilder;
+import javafx.scene.Node;
+import javafx.scene.control.Accordion;
+import javafx.scene.control.Button;
+import javafx.scene.control.CheckMenuItem;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListView;
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.MultipleSelectionModel;
+import javafx.scene.control.Pagination;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.Separator;
+import javafx.scene.control.SeparatorMenuItem;
+import javafx.scene.control.SplitPane;
+import javafx.scene.control.TabBuilder;
+import javafx.scene.control.TabPane;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+import javafx.scene.control.TitledPaneBuilder;
+import javafx.scene.control.ToolBar;
+import javafx.scene.control.Tooltip;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.KeyCharacterCombination;
+import javafx.scene.input.KeyCombination;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.LineBuilder;
+import javafx.scene.shape.RectangleBuilder;
+import javafx.util.Callback;
+
+/**
+ * Helper static methods for Sample Page
+ */
+public class SamplePageHelpers {
+    
+    private static final String[] LETTERS = new String[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
+    
+    static ObservableList<String> sampleItems() {
+        return sampleItems(7);
+    }
+    
+    static ObservableList<String> sampleItems(int numberOfItems) {
+        ArrayList<String> items = new ArrayList<String>();
+        if (numberOfItems < 26) {
+            for(int i=0; i<numberOfItems; i++) {
+                items.add("Item "+LETTERS[i]);
+            }
+        } else {
+            for(int i=0; i<numberOfItems; i++) {
+                items.add("Item "+i);
+            }
+        }
+        return FXCollections.observableArrayList(items);
+    }
+    
+    static Node scrollPaneContent() {
+        return GroupBuilder.create().children(
+                RectangleBuilder.create().width(200).height(200).fill(Color.PALETURQUOISE).build(),
+                LineBuilder.create().endX(200).endY(200).stroke(Color.DODGERBLUE).build(),
+                LineBuilder.create().startX(200).endX(0).endY(200).stroke(Color.DODGERBLUE).build()
+            ).build();
+    }
+    
+    static TabPane createTabPane(int numOfTabs, int prefWidth, String firstTabText, boolean floating) {
+        TabPane tabPane = new TabPane();
+        if (floating) tabPane.getStyleClass().add("floating");
+        for (int i=1; i<=numOfTabs; i++) {
+            tabPane.getTabs().add(
+                TabBuilder.create()
+                    .text("Tab "+i)
+                    .content(new Label((i==1 && firstTabText!=null)? firstTabText :"Tab "+i+" Content"))
+                    .build()
+            );
+        }
+        tabPane.setPrefWidth(prefWidth);
+        tabPane.setPrefHeight(100);
+        return tabPane;
+    }
+    
+    static ToolBar createToolBar(boolean vertical, boolean overFlow) {
+        ToolBar toolBar = new ToolBar();
+        if (vertical) toolBar.setOrientation(Orientation.VERTICAL);
+        toolBar.getItems().addAll(
+                new Button("A"),
+                new Button("B"),
+                new Separator()
+        );
+        if (vertical) {
+            toolBar.getItems().addAll(
+                new Button("C"),
+                new Button("D")
+            );
+        } else {
+            toolBar.getItems().addAll(
+                new Label("Search:"),
+                new TextField()
+            );
+        }
+        if (overFlow) {
+            if (vertical) {
+                toolBar.setPrefHeight(80);
+            } else {
+                toolBar.setPrefWidth(80);
+            }
+        }
+        return toolBar;
+    }
+    
+    static Accordion createAccordion() {
+        Accordion accordian = new Accordion();
+        accordian.getPanes().addAll(
+            TitledPaneBuilder.create().text("Title 1").content(new Label("Content\nLine2.")).build(),
+            TitledPaneBuilder.create().text("Title 2").content(new Label("Content\nLine2.")).build(),
+            TitledPaneBuilder.create().text("Title 3").content(new Label("Content\nLine2.")).build()
+        );
+        return accordian;
+    }
+    
+    static SplitPane createSplitPane(int numOfItems, boolean vertical, Node firstItem) {
+        SplitPane splitPane = new SplitPane();
+        if(vertical) splitPane.setOrientation(Orientation.VERTICAL);
+        if (firstItem != null) splitPane.getItems().add(firstItem);
+        for (int i=1; i<=numOfItems; i++) {
+            splitPane.getItems().add(new Label("Item "+i));
+        }
+        splitPane.setPrefSize(150, 150);
+        return splitPane;
+    }
+    
+    static Pagination createPagination(int numOfPages, boolean bullet, boolean arrows) {
+        Pagination pagination = new Pagination(numOfPages);
+        if (bullet) pagination.getStyleClass().add("bullet");
+        if (!arrows) pagination.setStyle("-fx-arrows-visible:false;");
+        pagination.setPageFactory(new Callback<Integer, Node>() {
+            @Override public Node call(Integer param) {
+                return new Label("Page Label "+param);
+            }
+        });
+        return pagination;
+    }
+    
+    static ListView<String> createListView(int numOfItems, boolean multipleSelection, boolean disable) {
+        ListView<String> listView = new ListView<String>();
+        listView.setPrefHeight((24*7)+4);
+        listView.setPrefWidth(140);
+        listView.getItems().addAll(sampleItems(numOfItems));
+        listView.setDisable(disable);
+        if (multipleSelection) {
+            listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+            listView.getSelectionModel().selectRange(1, 5);
+        } else {
+            listView.getSelectionModel().select(1);
+        }
+        return listView;
+    }
+    
+    static MenuItem[] createMenuItems(int numberOfItems) {
+        ArrayList<MenuItem> items = new ArrayList<MenuItem>();
+        if (numberOfItems < 26) {
+            for(int i=0; i<numberOfItems; i++) {
+                items.add(new MenuItem("Item "+LETTERS[i]));
+            }
+        } else {
+            for(int i=0; i<numberOfItems; i++) {
+                items.add(new MenuItem("Item "+i));
+            }
+        }
+        return items.toArray(new MenuItem[items.size()]);
+    }
+    
+    static Object[] createMenuContents() {
+        List menuItems = new ArrayList();
+//        Menu menu11 = makeMenu("_New", new ImageView(new Image(getClass().getResourceAsStream("about_16.png"))));
+        final Menu menu11 = new Menu("_New", new ImageView(new Image("helloworld/about_16.png")));
+        MenuItem menu12 = new MenuItem("_Open", new ImageView(new Image("helloworld/folder_16.png")));
+        menu12.setAccelerator(new KeyCharacterCombination("]", 
+                KeyCombination.SHIFT_DOWN, KeyCombination.META_DOWN));
+        Menu menu13 = new Menu("_Submenu");
+        CheckMenuItem showMessagesItem = new CheckMenuItem("Enable onShowing/onHiding _messages", 
+                                             new ImageView(new Image("helloworld/about_16.png")));
+        MenuItem menu15 = new MenuItem("E_xit");
+        final String change[] = {"Change Text", "Change Back"};
+        final MenuItem menu16 = new MenuItem(change[0]);
+        final boolean toggle = false;
+        menu16.setAccelerator(KeyCombination.keyCombination("Shortcut+C"));
+        menuItems.add(menu11);
+        menuItems.add(menu12);
+        menuItems.add(menu13);
+        menuItems.add(showMessagesItem);
+        menuItems.add(new SeparatorMenuItem());
+        menuItems.add(menu15);
+        menuItems.add(menu16);
+
+        // --- Menu 11 submenu
+        final MenuItem menu111 = new MenuItem("blah");
+        final MenuItem menu112 = new MenuItem("foo");
+        final CheckMenuItem menu113 = new CheckMenuItem("Show \"foo\" item");
+        menu113.setSelected(true);
+        menu113.selectedProperty().addListener(new InvalidationListener() {
+            @Override public void invalidated(Observable valueModel) {
+                menu112.setVisible(menu113.isSelected());
+                System.err.println("MenuItem \"foo\" is now " + (menu112.isVisible() ? "" : "not") + " visible.");
+            }
+        });
+        menu11.getItems().addAll(menu111, menu112, menu113);
+
+        // --- Menu 13 submenu
+        MenuItem menu131 = new MenuItem("Item _1");
+        MenuItem menu132 = new MenuItem("Item _2");
+        menu13.getItems().addAll(menu131, menu132);
+        
+        return menuItems.toArray();
+    }
+    
+    static final Image recorder48 = new Image(SamplePageHelpers.class.getResource("recorder-icon-48.png").toExternalForm());
+    
+    static ImageView createGraphic() {
+        return new ImageView(recorder48);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/experiments/Modena/src/modena/SamplePageTableHelper.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package modena;
+
+import javafx.beans.binding.ObjectBinding;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.EventHandler;
+import javafx.scene.Node;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.CheckBoxTableCell;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
+import javafx.scene.shape.Rectangle;
+import javafx.util.Callback;
+
+/**
+ * Helper class for creating table views for testing
+ */
+public class SamplePageTableHelper {
+    
+    public static class Person {
+
+        private BooleanProperty invited;
+        private StringProperty firstName;
+        private StringProperty lastName;
+        private StringProperty email;
+        
+        private final String country = "New Zealand";
+
+        public Person(String fName, String lName) {
+            this(fName, lName, null);
+        }
+
+        public Person(String fName, String lName, String email) {
+            this(fName, lName, email, false);
+        }
+        
+        public Person(String fName, String lName, String email, boolean invited) {
+            this.firstName = new SimpleStringProperty(fName);
+            this.lastName = new SimpleStringProperty(lName);
+            this.email = new SimpleStringProperty(email);
+            this.invited = new SimpleBooleanProperty(invited);
+            
+            this.invited.addListener(new ChangeListener<Boolean>() {
+                public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
+                    System.out.println(getFirstName() + " invited: " + t1);
+                }
+            });
+        }
+        
+        public Boolean isInvited() { return invited.get(); }
+        public BooleanProperty invitedProperty() { return invited; }
+
+        public String getFirstName() {
+            return firstName.get();
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName.set(firstName);
+        }
+
+        public StringProperty firstNameProperty() {
+            return firstName;
+        }
+
+        public String getLastName() {
+            return lastName.get();
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName.set(lastName);
+        }
+
+        public StringProperty lastNameProperty() {
+            return lastName;
+        }
+
+        public String getEmail() {
+            return email.get();
+        }
+
+        public void setEmail(String email) {
+            this.email.set(email);
+        }
+
+        public StringProperty emailProperty() {
+            return email;
+        }
+        
+        public String getCountry() {
+            return country;
+        }
+
+        public String toString() {
+            return "Person [ " + getFirstName() + " " + getLastName()/* + ", " + getEmail()*/ + " ]";
+        }
+    }
+
+    private static ObservableList<Person> data = FXCollections.<Person>observableArrayList();
+    private final static TableColumn<Person, String> firstNameCol;
+    private final static TableColumn<Person, String> lastNameCol;
+    private final static TableColumn<Person, String> nameCol;
+    private final static TableColumn<Person, String> emailCol;
+    private final static TableColumn<Person, String> countryCol;
+    private final static TableColumn<Person, Boolean> invitedCol;
+    
+    static {
+        // Data
+        data.addAll(
+            new Person("Jacob",     "Smith\nSmith\nSmith",    "jacob.smith<at>example.com", true ),
+            new Person("Isabella",  "Johnson",  "isabella.johnson<at>example.com" ),
+            new Person("Ethan",     "Williams", "ethan.williams<at>example.com", true ),
+            new Person("Emma",      "Jones",    "emma.jones<at>example.com" ),
+            new Person("Michael",   "Brown",    "michael.brown<at>example.com", true ),
+            new Person("Olivia",    "Davis",    "olivia.davis<at>example.com" ),
+            new Person("Alexander", "Miller",   "alexander.miller<at>example.com", true ),
+            new Person("Sophia",    "Wilson",   "sophia.wilson<at>example.com" ),
+            new Person("William",   "Moore",    "william.moore<at>example.com", true ),
+            new Person("Ava",       "Taylor",   "ava.taylor<at>example.com" ),
+            new Person("Joshua",    "Anderson", "joshua.anderson<at>example.com" ),
+            new Person("Emily",     "Thomas",   "emily.thomas<at>example.com" ),
+            new Person("Daniel",    "Jackson",  "daniel.jackson<at>example.com" ),
+            new Person("Madison",   "White",    "madison.white<at>example.com" ),
+            new Person("Jayden",    "Harris",   "jayden.harris<at>example.com" ),
+            new Person("Abigail",   "Martin",   "abigail.martin<at>example.com" ),
+            new Person("Noah",      "Thompson", "noah.thompson<at>example.com" ),
+            new Person("Chloe",     "Garcia",   "chloe.garcia<at>example.com" ),
+            new Person("Anthony",   "Martinez", "anthony.martinez<at>example.com" ),
+            new Person("Mia",       "Robinson", "mia.robinson<at>example.com" ),
+            new Person("Jacob",     "Smith" ),
+            new Person("Isabella",  "Johnson" ),
+            new Person("Ethan",     "Williams" ),
+            new Person("Emma",      "Jones" ),
+            new Person("Michael",   "Brown" ),
+            new Person("Olivia",    "Davis" ),
+            new Person("Alexander", "Miller" ),
+            new Person("Sophia",    "Wilson" ),
+            new Person("William",   "Moore" ),
+            new Person("Ava",       "Taylor" ),
+            new Person("Joshua",    "Anderson" ),
+            new Person("Emily",     "Thomas" ),
+            new Person("Daniel",    "Jackson" ),
+            new Person("Madison",   "White" ),
+            new Person("Jayden",    "Harris" ),
+            new Person("Abigail",   "Martin" ),
+            new Person("Noah",      "Thompson" ),
+            new Person("Chloe",     "Garcia" ),
+            new Person("Anthony",   "Martinez" ),
+            new Person("Mia",       "Robinson" )
+        );
+
+        // Columns
+        firstNameCol = new TableColumn<Person, String>();
+        firstNameCol.setText("First");
+        Rectangle sortNode = new Rectangle(10, 10, Color.RED);
+        sortNode.fillProperty().bind(new ObjectBinding<Paint>() {
+            { bind(firstNameCol.sortTypeProperty()); }
+            @Override protected Paint computeValue() {
+                switch (firstNameCol.getSortType()) {
+                    case ASCENDING: return Color.GREEN;
+                    case DESCENDING: return Color.RED;
+                    default: return Color.BLACK;
+                }
+            }
+        });
+        firstNameCol.setSortNode(sortNode);
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
+        firstNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() {
+            @Override public void handle(TableColumn.CellEditEvent<Person, String> t) {
+                System.out.println("Edit commit event: " + t.getNewValue());
+            }
+        });
+        final Node graphic1 = new ImageView(new Image("file:src/helloworld/about_16.png"));
+        lastNameCol = new TableColumn<Person, String>();
+        lastNameCol.setGraphic(graphic1);
+        lastNameCol.setText("Last");
+        lastNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
+            public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
+                return p.getValue().lastNameProperty();
+            }
+        });
+        nameCol = new TableColumn<Person, String>();
+        nameCol.setText("Name");
+        nameCol.getColumns().addAll(firstNameCol, lastNameCol);
+        emailCol = new TableColumn<Person, String>();
+        emailCol.setText("Email");
+        emailCol.setMinWidth(200);
+        emailCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
+            public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
+                return p.getValue().emailProperty();
+            }
+        });
+        countryCol = new TableColumn<Person, String>();
+        countryCol.setText("Country");
+        countryCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
+            public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
+                return new ReadOnlyObjectWrapper<String>("New Zealand");
+            }
+        });
+        invitedCol = new TableColumn<Person, Boolean>();
+        invitedCol.setText("Invited");
+        invitedCol.setPrefWidth(55);
+        invitedCol.setMaxWidth(55);
+        invitedCol.setCellValueFactory(new PropertyValueFactory("invited"));
+        invitedCol.setCellFactory(new Callback<TableColumn<Person, Boolean>, TableCell<Person, Boolean>>() {
+            public TableCell<Person, Boolean> call(TableColumn<Person, Boolean> p) {
+                return new CheckBoxTableCell<Person, Boolean>();
+            }
+        });
+    }
+    
+    static TableView createTableView(int width) {
+        TableView<Person> tableView = new TableView<Person>();
+        tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+        tableView.getSelectionModel().setCellSelectionEnabled(false);
+        tableView.setTableMenuButtonVisible(true);
+        tableView.setItems(data);
+        tableView.getColumns().addAll(invitedCol, nameCol, emailCol, countryCol);
+        tableView.setPrefSize(width, 300);
+        tableView.getSelectionModel().selectRange(2, 5);
+        return tableView;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/experiments/Modena/src/modena/SamplePageTreeHelper.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package modena;
+
+import javafx.scene.Node;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TreeItem;
+import javafx.scene.control.TreeView;
+import javafx.scene.shape.SVGPath;
+
+/**
+ * Helper class for creating tree views for testing
+ */
+public class SamplePageTreeHelper {
+    
+    private static final String RSS = "M13.33,13.334h-1.693c0-4.954-4.016-8.97-8.97-8.97V2.66"
+            + "9l0.243-0.002c5.757,0,10.423,4.667,10.423,10.425L13.33,13.334z M9.45,13.334H7."
+            + "758c0-2.812-2.279-5.091-5.091-5.091V6.551l0.243-0.005c3.615,0,6.545,2.93,6.545"
+            + ",6.546L9.45,13.334z M2.667,11.878c0-0.802,0.651-1.455,1.455-1.455c0.803,0,1.45"
+            + "4,0.653,1.454,1.455c0,0.804-0.651,1.456-1.454,1.456C3.318,13.334,2.667,12.682,"
+            + "2.667,11.878z M1.6,0C0.716,0,0,0.716,0,1.6v12.8C0,15.283,0.716,16,1.6,16H14.4c"
+            + "0.885,0,1.6-0.717,1.6-1.6V1.6C16,0.716,15.285,0,14.4,0H1.6z";
+    private static final String CLOUD = "M8.972,8.088h1.91v2.39l1.433-0.956l1.06,0.986l-3.448"
+            + ",3.313l-3.418-3.299l1.03-1l1.434,0.956V8.088z M-0.104,12.685c0,2.211,1.563,4.0"
+            + "03,3.489,4.003c0.112,0,12.275,0,12.275,0c2.382-0.044,4.299-2.089,4.299-4.607c0"
+            + "-2.542-1.961-4.605-4.379-4.605l-0.173,0.002c-0.673-2.396-3.037-4.165-5.849-4.1"
+            + "65c-3.268,0-5.931,2.389-6.037,5.374L3.385,8.682C1.459,8.682-0.104,10.475-0.104"
+            + ",12.685z";
+    
+    private static Node createRSS() { 
+        SVGPath sp = new SVGPath();
+        sp.setContent(RSS);
+        return sp;
+    }
+    
+    private static Node createCLOUD() { 
+        SVGPath sp = new SVGPath();
+        sp.setContent(CLOUD);
+        return sp;
+    }
+    
+    static TreeView createTreeView(int width) {
+        final TreeItem<String> root = new TreeItem<String>("Root node");
+        final TreeItem<String> childNode1 = new TreeItem<String>("Child Node 1", createCLOUD());
+        final TreeItem<String> childNode2 = new TreeItem<String>("Child Node 2", createCLOUD());
+        final TreeItem<String> childNode3 = new TreeItem<String>("Child Node 3", createCLOUD());
+        final TreeItem<String> childNode4 = new TreeItem<String>("Child Node 4", createRSS());
+        final TreeItem<String> childNode5 = new TreeItem<String>("Child Node 5", createRSS());
+        final TreeItem<String> childNode6 = new TreeItem<String>("Child Node 6", createRSS());
+        final TreeItem<String> childNode7 = new TreeItem<String>("Child Node 7", createRSS());
+        final TreeItem<String> childNode8 = new TreeItem<String>("Child Node 8", createRSS());
+        final TreeItem<String> childNode9 = new TreeItem<String>("Child Node 9", createRSS());
+        final TreeItem<String> childNode10 = new TreeItem<String>("Child Node 10");
+        final TreeItem<String> childNode11 = new TreeItem<String>("Child Node 11");
+        final TreeItem<String> childNode12 = new TreeItem<String>("Child Node 12");
+        final TreeItem<String> childNode13 = new TreeItem<String>("Child Node 13");
+        final TreeItem<String> childNode14 = new TreeItem<String>("Child Node 14");
+        final TreeItem<String> childNode15 = new TreeItem<String>("Child Node 15");
+        final TreeItem<String> childNode16 = new TreeItem<String>("Child Node 16");
+        final TreeItem<String> childNode17 = new TreeItem<String>("Child Node 17");
+        final TreeItem<String> childNode18 = new TreeItem<String>("Child Node 18");
+        final TreeItem<String> childNode19 = new TreeItem<String>("Child Node 19");
+        final TreeItem<String> childNode20 = new TreeItem<String>("Child Node 20");
+        final TreeItem<String> childNode21 = new TreeItem<String>("Child Node 21");
+    
+        root.setExpanded(true);
+        root.getChildren().setAll(childNode1, childNode2, childNode3);
+        childNode3.setExpanded(true);
+        childNode3.getChildren().setAll(childNode4, childNode5, childNode6,
+                childNode7, childNode8, childNode9,
+                childNode10, childNode11, childNode12,
+                childNode13, childNode14, childNode15,
+                childNode16, childNode17, childNode18,
+                childNode19, childNode20, childNode21);
+        
+        final TreeView treeView = new TreeView(root);
+        treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+        treeView.setShowRoot(true);
+        treeView.setPrefSize(width, 300);
+        treeView.getSelectionModel().selectRange(5, 8);
+        return treeView;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/experiments/Modena/src/modena/SamplePageTreeTableHelper.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
+ * All rights reserved. Use is subject to license terms.
+ *
+ * This file is available and licensed under the following license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Oracle Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package modena;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Comparator;
+import java.util.Date;
+import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.scene.Node;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TreeItem;
+import javafx.scene.control.TreeSortMode;
+import javafx.scene.control.TreeTableCell;
+import javafx.scene.control.TreeTableColumn;
+import javafx.scene.control.TreeTableView;
+import javafx.scene.shape.SVGPath;
+import javafx.util.Callback;
+
+/**
+ * Helper class for creating tree table views for testing
+ */
+public class SamplePageTreeTableHelper {
+    private static final NumberFormat nf = NumberFormat.getNumberInstance();
+    private static final DateFormat df = new SimpleDateFormat("EEE, MMM d, yyyy");
+    private static final String FOLDER = "M8,2.001V0H0v6.002v1.688V14c0,1.105,0.895,2,2,2h12c"
+            + "1.104,0,2-0.895,2-2V8.002v-2V2.001H8z M6,2L6,2v2.001h2h6V6H2V2H6z M14,14H2V8h1"
+            + "2v0.002V14z";
+    private static final String FILE = "M4.775,1.592h5.836c0.293,0,0.531,0.238,0.531,0.53v11"
+            + ".673c0,0.293-0.237,0.53-0.531,0.53H2.122c-0.293,0-0.53-0.237-0.53-0.53v-9.02h3"
+            + ".183V1.592z M0,4.245v10.611c0,0.586,0.475,1.061,1.061,1.061h10.611c0.586,0,1.0"
+            + "61-0.475,1.061-1.061V1.061C12.733,0.475,12.258,0,11.672,0H4.245L0,4.245z";
+    
+    private static Node createFOLDER() { 
+        SVGPath sp = new SVGPath();
+        sp.setContent(FOLDER);
+        return sp;
+    }
+    
+    private static Node createFILE() { 
+        SVGPath sp = new SVGPath();
+        sp.setContent(FILE);
+        return sp;
+    }
+    
+    static TreeTableView createTreeTableView(int width) {
+        TreeTableView treeTableView = buildFileBrowserTreeTableView();
+        treeTableView.setSortMode(TreeSortMode.ONLY_FIRST_LEVEL);
+        treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+        treeTableView.setPrefSize(width, 300);
+        treeTableView.getSelectionModel().selectRange(5, 8);
+        return treeTableView;
+    }
+    
+    private static TreeTableView buildFileBrowserTreeTableView() {
+        // create a simple String treeview
+        TreeItem<File> root = new FileTreeItem(new File("/"));
+        root.setExpanded(true);
+        
+        final TreeTableView<File> treeTableView = new TreeTableView<File>();
+        treeTableView.setShowRoot(true);
+        treeTableView.setRoot(root);
+        
+        // --- name column
+        TreeTableColumn<File, String> nameColumn = new TreeTableColumn<File, String>("Name");
+        nameColumn.setPrefWidth(300);
+        nameColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<File, String>, ObservableValue<String>>() {
+            @Override public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<File, String> p) {
+                File f = p.getValue().getValue();
+                String text = f.getParentFile() == null ? "/" : f.getName();
+                return new ReadOnlyObjectWrapper<String>(text);
+            }
+        });
+
+        // --- size column
+        TreeTableColumn<File, File> sizeColumn = new TreeTableColumn<File, File>("Size");
+        sizeColumn.setPrefWidth(100);
+        sizeColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<File, File>, ObservableValue<File>>() {
+            @Override public ObservableValue<File> call(TreeTableColumn.CellDataFeatures<File, File> p) {
+                return new ReadOnlyObjectWrapper<File>(p.getValue().getValue());
+            }
+        });
+        sizeColumn.setCellFactory(new Callback<TreeTableColumn<File, File>, TreeTableCell<File, File>>() {
+            @Override public TreeTableCell<File, File> call(final TreeTableColumn<File, File> p) {
+                return new TreeTableCell<File, File>() {
+                    @Override protected void updateItem(File item, boolean empty) {
+                        super.updateItem(item, empty);
+                        
+                        TreeTableView treeTable = p.getTreeTableView();
+
+                        // if the File is a directory, it has no size...
+//                        ObservableList<TreeItem<File>> items = p.getTreeTableView().getItems();
+                        if (getIndex() >= treeTable.getExpandedItemCount()) {
+                            setText(null);
+                        } else {
+                            TreeItem<File> treeItem = treeTable.getTreeItem(getIndex());
+                            if (item == null || empty || treeItem == null || 
+                                    treeItem.getValue() == null || treeItem.getValue().isDirectory()) {
+                                setText(null);
+                            } else {
+                                setText(nf.format(item.length()) + " KB");
+                            }
+                        }
+                    }
+                };
+            }
+        });
+        sizeColumn.setComparator(new Comparator<File>() {
+            @Override public int compare(File f1, File f2) {
+                long s1 = f1.isDirectory() ? 0 : f1.length();
+                long s2 = f2.isDirectory() ? 0 : f2.length();
+                long result = s1 - s2;
+                if (result < 0) {
+                    return -1;
+                } else if (result == 0) {
+                    return 0;
+                } else {
+                    return 1;
+                }
+            }
+        });
+        
+        // --- modified column
+        TreeTableColumn<File, Date> lastModifiedColumn = new TreeTableColumn<File, Date>("Last Modified");
+        lastModifiedColumn.setPrefWidth(130);
+        lastModifiedColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<File, Date>, ObservableValue<Date>>() {
+            @Override public ObservableValue<Date> call(TreeTableColumn.CellDataFeatures<File, Date> p) {
+                return new ReadOnlyObjectWrapper<Date>(new Date(p.getValue().getValue().lastModified()));
+            }
+        });
+        lastModifiedColumn.setCellFactory(new Callback<TreeTableColumn<File, Date>, TreeTableCell<File, Date>>() {
+            @Override public TreeTableCell<File, Date> call(TreeTableColumn<File, Date> p) {
+                return new TreeTableCell<File, Date>() {
+                    @Override protected void updateItem(Date item, boolean empty) {
+                        super.updateItem(item, empty);
+                        
+                        if (item == null || empty) {
+                            setText(null);
+                        } else {
+                            setText(df.format(item));
+                        }
+                    }
+                };
+            }
+        });
+        
+        treeTableView.getColumns().setAll(nameColumn, sizeColumn, lastModifiedColumn);
+        return treeTableView;
+    }
+    
+    private static ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) {
+        File f = (File) TreeItem.getValue();
+        if (f != null && f.isDirectory()) {
+            File[] files = f.listFiles();
+            if (files != null) {
+                ObservableList<TreeItem<File>> children = FXCollections.observableArrayList();
+                for (File childFile : files) {
+                    children.add(new FileTreeItem(childFile));
+                }
+                return children;
+            }
+        }
+        return FXCollections.emptyObservableList();
+    }
+    
+    private static class FileTreeItem extends TreeItem<File> {
+        private boolean isLeaf;
+        private boolean isFirstTimeChildren = true;
+        private boolean isFirstTimeLeaf = true;
+
+        public FileTreeItem(File value) {
+            super(value);
+//            setGraphic(value.isFile() ? createFILE() : createFOLDER());
+        }
+
+        @Override public ObservableList<TreeItem<File>> getChildren() {
+            if (isFirstTimeChildren) {
+                isFirstTimeChildren = false;
+                super.getChildren().setAll(buildChildren(this));
+            }
+            return super.getChildren();
+        }
+
+        @Override public boolean isLeaf() {
+            if (isFirstTimeLeaf) {
+                isFirstTimeLeaf = false;
+                File f = (File) getValue();
+                isLeaf = f.isFile();
+            }
+            return isLeaf;
+        }
+    }
+}
--- a/apps/experiments/Modena/src/modena/TestApp.css	Thu Jan 10 10:01:15 2013 -0800
+++ b/apps/experiments/Modena/src/modena/TestApp.css	Wed Jan 16 11:42:20 2013 -0800
@@ -29,25 +29,16 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- .color-well , .color-well:focused {
-    -fx-background-color: -fx-base;
-    -fx-background-insets: 0;
-    -fx-effect: innershadow(gaussian,rgba(0,0,0,0.7),3,0,0,1);
-}
-.color-well:selected {
-    -fx-background-color: -fx-base;
-    -fx-effect: innershadow(gaussian,rgba(0,0,0,1),5,0,0,1);
-    -fx-text-fill: -fx-text-base-color;
-}
-.color-well .text {
-    -fx-effect: null;
-}
+
 .section-label {
     -fx-font-weight: normal;
-    -fx-text-fill: rgba(0,0,0,0.5);
+    -fx-text-fill: derive(-fx-text-background-color,30%);
 }
-
 .section-border {
-    -fx-border-color: rgba(0,0,0,0.1);
+    -fx-border-color: ladder(
+        -fx-background,
+        derive(-fx-background,10%) 20%,
+        derive(-fx-background,-10%)  21%
+     );;
     -fx-padding: 20;
 }
\ No newline at end of file
Binary file apps/experiments/Modena/src/modena/recorder-icon-48.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/experiments/Modena/src/modena/ui-mosaic.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.collections.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+
+<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="800.0" xmlns:fx="http://javafx.com/fxml">
+  <children>
+    <Button layoutX="40.0" layoutY="41.0" mnemonicParsing="false" text="Button" />
+    <CheckBox layoutX="561.0" layoutY="400.0" mnemonicParsing="false" text="CheckBox" />
+    <CheckBox layoutX="561.0" layoutY="367.0" mnemonicParsing="false" selected="true" text="CheckBox" />
+    <ComboBox layoutX="234.0" layoutY="41.0" prefWidth="160.0">
+      <items>
+        <FXCollections fx:factory="observableArrayList">
+          <String fx:value="Item 1" />
+          <String fx:value="Item 2" />
+          <String fx:value="Item 3" />
+        </FXCollections>
+      </items>
+    </ComboBox>
+    <Hyperlink layoutX="134.0" layoutY="40.0" text="Hyperlink" />
+    <Label layoutX="242.0" layoutY="153.0" text="A label" />
+    <ListView layoutX="560.0" layoutY="94.0" prefHeight="216.0" prefWidth="200.0" />
+    <MenuBar layoutX="560.0" layoutY="40.0" prefWidth="200.0">
+      <menus>
+        <Menu mnemonicParsing="false" text="File">
+          <items>
+            <MenuItem mnemonicParsing="false" text="Close" />
+          </items>
+        </Menu>
+        <Menu mnemonicParsing="false" text="Edit">
+          <items>
+            <MenuItem mnemonicParsing="false" text="Delete" />
+          </items>
+        </Menu>
+        <Menu mnemonicParsing="false" text="Help">
+          <items>
+            <MenuItem mnemonicParsing="false" text="About" />
+          </items>
+        </Menu>
+      </menus>
+    </MenuBar>
+    <PasswordField layoutX="240.0" layoutY="243.0" prefWidth="138.0" promptText="Password" />
+    <ProgressBar layoutX="291.0" layoutY="291.0" prefWidth="200.0" progress="0.3" />
+    <ProgressIndicator layoutX="445.0" layoutY="48.0" prefHeight="59.0" prefWidth="56.0" progress="0.58" />
+    <RadioButton layoutX="587.0" layoutY="121.0" mnemonicParsing="false" text="RadioButton 1">
+      <toggleGroup>
+        <ToggleGroup fx:id="toggle2" />
+      </toggleGroup>
+    </RadioButton>
+    <ScrollBar layoutX="41.0" layoutY="329.0" prefWidth="719.0" />
+    <Separator layoutX="41.0" layoutY="129.0" prefWidth="490.0" />
+    <Separator layoutX="217.0" layoutY="151.0" orientation="VERTICAL" prefHeight="158.0" />
+    <SplitMenuButton layoutX="40.0" layoutY="83.0" mnemonicParsing="false" prefWidth="153.0" text="SplitMenuButton">
+      <items>
+        <MenuItem mnemonicParsing="false" text="Action 1" />
+        <MenuItem mnemonicParsing="false" text="Action 2" />
+      </items>
+    </SplitMenuButton>
+    <TextField layoutX="39.0" layoutY="149.0" prefWidth="160.0" promptText="Textfield" />
+    <TextArea layoutX="39.0" layoutY="180.0" prefHeight="130.0" prefWidth="160.0" promptText="Text Area" wrapText="true" />
+    <ToggleButton layoutX="241.0" layoutY="196.0" mnemonicParsing="false" prefWidth="90.0" selected="true" text="Toggle">
+      <toggleGroup>
+        <ToggleGroup fx:id="toggle1" />
+      </toggleGroup>
+    </ToggleButton>
+    <ToggleButton layoutX="341.0" layoutY="196.0" mnemonicParsing="false" prefWidth="90.0" selected="false" text="Toggle" toggleGroup="$toggle1" />
+    <RadioButton layoutX="587.0" layoutY="146.0" mnemonicParsing="false" text="RadioButton 2" toggleGroup="$toggle2" />
+    <ScrollPane layoutX="560.0" layoutY="439.0" prefHeight="330.0" prefWidth="200.0">
+      <content>
+        <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="400.0" prefWidth="400.0" />
+      </content>
+    </ScrollPane>
+    <TabPane layoutX="39.0" layoutY="561.0" prefHeight="158.0" prefWidth="454.0" tabClosingPolicy="UNAVAILABLE">
+      <tabs>
+        <Tab text="Tab 1">
+          <content>
+            <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
+          </content>
+        </Tab>
+        <Tab text="Tab 2">
+          <content>
+            <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
+          </content>
+        </Tab>
+        <Tab text="Tab 3">
+          <content>
+            <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
+          </content>
+        </Tab>
+      </tabs>
+    </TabPane>
+    <ChoiceBox layoutX="234.0" layoutY="85.0" prefWidth="160.0">
+      <items>
+        <FXCollections fx:factory="observableArrayList">
+          <String fx:value="Item 1" />
+          <String fx:value="Item 2" />
+          <String fx:value="Item 3" />
+        </FXCollections>
+      </items>
+    </ChoiceBox>
+    <ToolBar layoutX="39.0" layoutY="738.0" prefWidth="200.0">
+      <items>
+        <Button mnemonicParsing="false" text="New" />
+        <Button mnemonicParsing="false" text="Delete" />
+        <Button mnemonicParsing="false" text="Save" />
+        <Button mnemonicParsing="false" text="Exit" />
+      </items>
+    </ToolBar>
+    <Slider layoutX="304.0" layoutY="154.0" prefWidth="230.0" />
+    <Slider layoutX="518.0" layoutY="556.0" orientation="VERTICAL" prefHeight="216.0" showTickMarks="true" />
+    <SplitPane dividerPositions="0.4180327868852459" focusTraversable="true" layoutX="39.0" layoutY="364.0" prefHeight="172.0" prefWidth="490.0">
+      <items>
+        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+          <children>
+            <TreeView prefHeight="158.0" prefWidth="56.0" showRoot="false" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="20.0">
+              <root>
+                <TreeItem value="Family">
+                  <children>
+                    <TreeItem value="Grandparent A">
+                      <children>
+                        <TreeItem value="Parent A">
+                          <children>
+                            <TreeItem value="Child A" />
+                          </children>
+                        </TreeItem>
+                      </children>
+                    </TreeItem>
+                    <TreeItem value="Grandparent B">
+                      <children>
+                        <TreeItem value="Parent B">
+                          <children>
+                            <TreeItem value="Child B" />
+                          </children>
+                        </TreeItem>
+                      </children>
+                    </TreeItem>
+                    <TreeItem value="Grandparent C">
+                      <children>
+                        <TreeItem value="Parent C">
+                          <children>
+                            <TreeItem value="Child C" />
+                          </children>
+                        </TreeItem>
+                      </children>
+                    </TreeItem>
+                  </children>
+                </TreeItem>
+              </root>
+            </TreeView>
+          </children>
+        </AnchorPane>
+        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+          <children>
+            <TableView prefHeight="158.0" prefWidth="136.0" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="20.0">
+              <columns>
+                <TableColumn prefWidth="75.0" text="Column X" />
+                <TableColumn prefWidth="75.0" text="Column X" />
+              </columns>
+            </TableView>
+          </children>
+        </AnchorPane>
+      </items>
+    </SplitPane>
+    <ToggleButton layoutX="441.0" layoutY="196.0" mnemonicParsing="false" prefWidth="90.0" selected="false" text="Toggle">
+      <toggleGroup>
+        <ToggleGroup />
+      </toggleGroup>
+    </ToggleButton>
+    <ComboBox editable="true" layoutX="395.0" layoutY="244.0" prefWidth="136.0001220703125" promptText="Choose">
+      <items>
+        <FXCollections fx:factory="observableArrayList">
+          <String fx:value="Item 1" />
+          <String fx:value="Item 2" />
+          <String fx:value="Item 3" />
+        </FXCollections>
+      </items>
+    </ComboBox>
+    <ProgressIndicator layoutX="680.0" layoutY="361.0" prefHeight="59.0" prefWidth="56.0" progress="-1.0" />
+  </children>
+</AnchorPane>
--- a/javafx-fxml/src/javafx/fxml/FXMLLoader.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-fxml/src/javafx/fxml/FXMLLoader.java	Wed Jan 16 11:42:20 2013 -0800
@@ -87,6 +87,7 @@
 import com.sun.javafx.fxml.expression.Expression;
 import com.sun.javafx.fxml.expression.ExpressionValue;
 import com.sun.javafx.fxml.expression.KeyPath;
+import java.net.MalformedURLException;
 
 /**
  * Loads an object hierarchy from an XML document.
@@ -275,171 +276,209 @@
         @SuppressWarnings("unchecked")
         public void processPropertyAttribute(Attribute attribute) throws IOException {
             String value = attribute.value;
-
-            if (value.startsWith(ESCAPE_PREFIX)) {
-                value = value.substring(ESCAPE_PREFIX.length());
-
-                if (value.length() == 0
-                    || !(value.startsWith(ESCAPE_PREFIX)
-                        || value.startsWith(RELATIVE_PATH_PREFIX)
-                        || value.startsWith(RESOURCE_KEY_PREFIX)
-                        || value.startsWith(EXPRESSION_PREFIX)
-                        || value.startsWith(BI_DIRECTIONAL_BINDING_PREFIX))) {
+            if (isBindingExpression(value)) {
+                // Resolve the expression
+                Expression expression;
+
+                if (attribute.sourceType != null) {
+                    throw new LoadException("Cannot bind to static property.");
+                }
+
+                if (!isTyped()) {
+                    throw new LoadException("Cannot bind to untyped object.");
+                }
+
+                // TODO We may want to identify binding properties in processAttribute()
+                // and apply them after build() has been called
+                if (this.value instanceof Builder) {
+                    throw new LoadException("Cannot bind to builder property.");
+                }
+
+                value = value.substring(BINDING_EXPRESSION_PREFIX.length(),
+                        value.length() - 1);
+                expression = Expression.valueOf(value);
+
+                // Create the binding
+                BeanAdapter targetAdapter = new BeanAdapter(this.value);
+                ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);
+                Class<?> type = targetAdapter.getType(attribute.name);
+
+                if (propertyModel instanceof Property<?>) {
+                    ((Property<Object>)propertyModel).bind(new ExpressionValue(namespace, expression, type));
+                }
+            } else if (isBidirectionalBindingExpression(value)) {
+                throw new UnsupportedOperationException("This feature is not currently enabled.");
+            } else {
+                processValue(attribute.sourceType, attribute.name, value);
+            }
+        }
+
+        private boolean isBindingExpression(String aValue) {
+            return aValue.startsWith(BINDING_EXPRESSION_PREFIX)
+                   && aValue.endsWith(BINDING_EXPRESSION_SUFFIX);
+        }
+
+        private boolean isBidirectionalBindingExpression(String aValue) {
+            return aValue.startsWith(BI_DIRECTIONAL_BINDING_PREFIX);
+        }
+
+        private boolean processValue(Class sourceType, String propertyName, String aValue)
+            throws LoadException {
+
+            boolean processed = false;
+                //process list or array first
+                if (sourceType == null && isTyped()) {
+                    BeanAdapter valueAdapter = getValueAdapter();
+                    Class<?> type = valueAdapter.getType(propertyName);
+
+                    if (type == null) {
+                        throw new PropertyNotFoundException("Property \"" + propertyName
+                            + "\" does not exist" + " or is read-only.");
+                    }
+
+                    if (List.class.isAssignableFrom(type)
+                        && valueAdapter.isReadOnly(propertyName)) {
+                        populateListFromString(valueAdapter, propertyName, aValue);
+                        processed = true;
+                    } else if (type.isArray()) {
+                        applyProperty(propertyName, sourceType,
+                                populateArrayFromString(type, aValue));
+                        processed = true;
+                    }
+                }
+                if (!processed) {
+                    applyProperty(propertyName, sourceType, resolvePrefixedValue(aValue));
+                    processed = true;
+                }
+                return processed;
+        }
+
+        /**
+         * Resolves value prefixed with RELATIVE_PATH_PREFIX and RESOURCE_KEY_PREFIX.
+         */
+        private Object resolvePrefixedValue(String aValue) throws LoadException {
+            if (aValue.startsWith(ESCAPE_PREFIX)) {
+                aValue = aValue.substring(ESCAPE_PREFIX.length());
+
+                if (aValue.length() == 0
+                    || !(aValue.startsWith(ESCAPE_PREFIX)
+                        || aValue.startsWith(RELATIVE_PATH_PREFIX)
+                        || aValue.startsWith(RESOURCE_KEY_PREFIX)
+                        || aValue.startsWith(EXPRESSION_PREFIX)
+                        || aValue.startsWith(BI_DIRECTIONAL_BINDING_PREFIX))) {
                     throw new LoadException("Invalid escape sequence.");
                 }
-
-                applyProperty(attribute.name, attribute.sourceType, value);
-            } else if (value.startsWith(RELATIVE_PATH_PREFIX)) {
-                value = value.substring(RELATIVE_PATH_PREFIX.length());
-
-                if (value.startsWith(RELATIVE_PATH_PREFIX)) {
+                return aValue;
+            } else if (aValue.startsWith(RELATIVE_PATH_PREFIX)) {
+                aValue = aValue.substring(RELATIVE_PATH_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing relative path.");
+                }
+                if (aValue.startsWith(RELATIVE_PATH_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(RELATIVE_PATH_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
+                    return aValue;
                 } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing relative path.");
+                    try {
+                        return (aValue.charAt(0) == '/') ?
+                                classLoader.getResource(aValue.substring(1)).toString() :
+                                new URL(FXMLLoader.this.location, aValue).toString();
+                    } catch (MalformedURLException e) {
+                        System.err.println(FXMLLoader.this.location + "/" + aValue);
                     }
-
-                    URL location;
-                    if (value.charAt(0) == '/') {
-                        location = classLoader.getResource(value.substring(1));
-                    } else {
-                        if (FXMLLoader.this.location == null) {
-                            throw new LoadException("Base location is undefined.");
-                        }
-
-                        location = new URL(FXMLLoader.this.location, value);
-                    }
-
-                    applyProperty(attribute.name, attribute.sourceType, location);
                 }
-            } else if (value.startsWith(RESOURCE_KEY_PREFIX)) {
-                value = value.substring(RESOURCE_KEY_PREFIX.length());
-
-                if (value.startsWith(RESOURCE_KEY_PREFIX)) {
+            } else if (aValue.startsWith(RESOURCE_KEY_PREFIX)) {
+                aValue = aValue.substring(RESOURCE_KEY_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing resource key.");
+                }
+                if (aValue.startsWith(RESOURCE_KEY_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(RESOURCE_KEY_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
+                    return aValue;
                 } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing resource key.");
-                    }
-
                     // Resolve the resource value
                     if (resources == null) {
                         throw new LoadException("No resources specified.");
                     }
-
-                    if (!resources.containsKey(value)) {
-                        throw new LoadException("Resource \"" + value + "\" not found.");
+                    if (!resources.containsKey(aValue)) {
+                        throw new LoadException("Resource \"" + aValue + "\" not found.");
                     }
 
-                    applyProperty(attribute.name, attribute.sourceType, resources.getObject(value));
+                    return resources.getString(aValue);
                 }
-            } else if (value.startsWith(EXPRESSION_PREFIX)) {
-                value = value.substring(EXPRESSION_PREFIX.length());
-
-                if (value.startsWith(EXPRESSION_PREFIX)) {
+            } else if (aValue.startsWith(EXPRESSION_PREFIX)) {
+                aValue = aValue.substring(EXPRESSION_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing expression.");
+                }
+                if (aValue.startsWith(EXPRESSION_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(EXPRESSION_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
-                } else if (value.equals(NULL_KEYWORD)) {
+                    return aValue;
+                } else if (aValue.equals(NULL_KEYWORD)) {
                     // The attribute value is null
-                    applyProperty(attribute.name, attribute.sourceType, null);
-                } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing expression.");
-                    }
-
-                    // Resolve the expression
-                    Expression expression;
-                    if (value.startsWith(BINDING_EXPRESSION_PREFIX)
-                        && value.endsWith(BINDING_EXPRESSION_SUFFIX)) {
-                        if (attribute.sourceType != null) {
-                            throw new LoadException("Cannot bind to static property.");
-                        }
-
-                        if (!isTyped()) {
-                            throw new LoadException("Cannot bind to untyped object.");
-                        }
-
-                        // TODO We may want to identify binding properties in processAttribute()
-                        // and apply them after build() has been called
-                        if (this.value instanceof Builder) {
-                            throw new LoadException("Cannot bind to builder property.");
-                        }
-
-                        value = value.substring(1, value.length() - 1);
-                        expression = Expression.valueOf(value);
-
-                        // Create the binding
-                        BeanAdapter targetAdapter = new BeanAdapter(this.value);
-                        ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);
-                        Class<?> type = targetAdapter.getType(attribute.name);
-
-                        if (propertyModel instanceof Property<?>) {
-                            ((Property<Object>)propertyModel).bind(new ExpressionValue(namespace, expression, type));
-                        }
-                    } else {
-                        applyProperty(attribute.name, attribute.sourceType, Expression.get(namespace, KeyPath.parse(value)));
-                    }
+                    return null;
                 }
-            } else if (value.startsWith(BI_DIRECTIONAL_BINDING_PREFIX)) {
-                throw new UnsupportedOperationException("This feature is not currently enabled.");
+                return Expression.get(namespace, KeyPath.parse(aValue));
+            }
+            return aValue;
+        }
+
+        /**
+         * Creates an array of given type and populates it with values from
+         * a string where tokens are separated by ARRAY_COMPONENT_DELIMITER.
+         * If token is prefixed with RELATIVE_PATH_PREFIX a value added to
+         * the array becomes relative to document location.
+         */
+        private Object populateArrayFromString(
+                Class<?>type,
+                String stringValue) throws LoadException {
+
+            Object propertyValue = null;
+            // Split the string and set the values as an array
+            Class<?> componentType = type.getComponentType();
+
+            if (stringValue.length() > 0) {
+                String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
+                propertyValue = Array.newInstance(componentType, values.length);
+                for (int i = 0; i < values.length; i++) {
+                    Array.set(propertyValue, i,
+                            BeanAdapter.coerce(resolvePrefixedValue(values[i].trim()),
+                            type.getComponentType()));
+                }
             } else {
-                Object propertyValue = value;
-
-                if (attribute.sourceType == null && isTyped()) {
-                    BeanAdapter valueAdapter = getValueAdapter();
-                    Class<?> type = valueAdapter.getType(attribute.name);
-
-                    if (type == null) {
-                        throw new PropertyNotFoundException("Property \"" + attribute.name
-                            + "\" does not exist" + " or is read-only.");
-                    }
-
-                    if (List.class.isAssignableFrom(type)
-                        && valueAdapter.isReadOnly(attribute.name)) {
-                        // Split the string and add the values to the list
-                        List<Object> list = (List<Object>)valueAdapter.get(attribute.name);
-                        Type listType = valueAdapter.getGenericType(attribute.name);
-                        Type itemType = (Class<?>)BeanAdapter.getGenericListItemType(listType);
-
-                        if (itemType instanceof ParameterizedType) {
-                            itemType = ((ParameterizedType)itemType).getRawType();
-                        }
-
-                        String stringValue = value.toString();
-                        if (stringValue.length() > 0) {
-                            String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
-
-                            for (int i = 0; i < values.length; i++) {
-                                list.add(BeanAdapter.coerce(values[i].trim(), (Class<?>)itemType));
-                            }
-                        }
-
-                        propertyValue = null;
-                    } else if (type.isArray()) {
-                        // Split the string and set the values as an array
-                        Class<?> componentType = type.getComponentType();
-
-                        String stringValue = value.toString();
-                        if (stringValue.length() > 0) {
-                            String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
-                            propertyValue = Array.newInstance(componentType, values.length);
-                            for (int i = 0; i < values.length; i++) {
-                                Array.set(propertyValue, i, BeanAdapter.coerce(values[i].trim(),
-                                    type.getComponentType()));
-                            }
-                        } else {
-                            propertyValue = Array.newInstance(componentType, 0);
-                        }
-                    }
-                }
-
-                if (propertyValue != null) {
-                    applyProperty(attribute.name, attribute.sourceType, propertyValue);
+                propertyValue = Array.newInstance(componentType, 0);
+            }
+            return propertyValue;
+        }
+
+        /**
+         * Populates list with values from a string where tokens are separated
+         * by ARRAY_COMPONENT_DELIMITER. If token is prefixed with RELATIVE_PATH_PREFIX
+         * a value added to the list becomes relative to document location.
+         */
+        private void populateListFromString(
+                BeanAdapter valueAdapter,
+                String listPropertyName,
+                String stringValue) throws LoadException {
+            // Split the string and add the values to the list
+            List<Object> list = (List<Object>)valueAdapter.get(listPropertyName);
+            Type listType = valueAdapter.getGenericType(listPropertyName);
+            Type itemType = (Class<?>)BeanAdapter.getGenericListItemType(listType);
+
+            if (itemType instanceof ParameterizedType) {
+                itemType = ((ParameterizedType)itemType).getRawType();
+            }
+
+            if (stringValue.length() > 0) {
+                String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
+
+                for (String aValue: values) {
+                    aValue = aValue.trim();
+                    list.add(
+                            BeanAdapter.coerce(resolvePrefixedValue(aValue),
+                                               (Class<?>)itemType));
                 }
             }
         }
@@ -919,7 +958,7 @@
                 builderFactory, controllerFactory, charset,
                 loaders);
             fxmlLoader.parentLoader = FXMLLoader.this;
-            
+
             if (isCyclic(FXMLLoader.this, fxmlLoader)) {
                 throw new IOException(
                         String.format(
@@ -1090,17 +1129,7 @@
 
             Object value;
             if (root == null) {
-                value = (builderFactory == null) ? null : builderFactory.getBuilder(type);
-
-                if (value == null) {
-                    try {
-                        value = type.newInstance();
-                    } catch (InstantiationException exception) {
-                        throw new LoadException(exception);
-                    } catch (IllegalAccessException exception) {
-                        throw new LoadException(exception);
-                    }
-                }
+                throw new LoadException("Root hasn't been set. Use method setRoot() before load.");
             } else {
                 if (!type.isAssignableFrom(root.getClass())) {
                     throw new LoadException("Root is not an instance of "
@@ -1578,7 +1607,7 @@
     private ClassLoader classLoader = defaultClassLoader;
     private boolean staticLoad = false;
     private LoadListener loadListener = null;
-    
+
     private FXMLLoader parentLoader;
 
     private XMLStreamReader xmlStreamReader = null;
@@ -1642,7 +1671,7 @@
     public static final String RELATIVE_PATH_PREFIX = "@";
     public static final String RESOURCE_KEY_PREFIX = "%";
     public static final String EXPRESSION_PREFIX = "$";
-    public static final String BINDING_EXPRESSION_PREFIX = "{";
+    public static final String BINDING_EXPRESSION_PREFIX = "${";
     public static final String BINDING_EXPRESSION_SUFFIX = "}";
 
     public static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{";
@@ -1831,20 +1860,20 @@
                     location.toExternalForm());
         }
         return false;
-    }            
-    
+    }
+
     private boolean isCyclic(
-                            FXMLLoader currentLoader, 
+                            FXMLLoader currentLoader,
                             FXMLLoader node) {
         if (currentLoader == null) {
             return false;
         }
         if (currentLoader.equals(node)) {
             return true;
-        }        
+        }
         return isCyclic(currentLoader.parentLoader, node);
     }
-        
+
     /**
      * Returns the controller associated with the root object.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/RT_26449Test.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.fxml;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+public class RT_26449Test {
+    @Test(expected=LoadException.class)
+    public void testRootNotSet() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_26449.fxml"));
+        fxmlLoader.load();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/RT_27529Test.java	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.fxml;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.ResourceBundle;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class RT_27529Test {
+    
+    @Test
+    public void testListAndArrayWithResources() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_1.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        Widget widget = (Widget)fxmlLoader.load();
+        assertEquals(Arrays.asList(new String[]{"a", "b", "c"}), widget.getStyles());
+        assertTrue(Arrays.equals(new String[]{"a", "b", "c"}, widget.getNames()));
+        assertTrue(Arrays.equals(new float[] {1.0f, 2.0f, 3.0f}, widget.getRatios()));
+    }
+    
+    @Test
+    public void testListAndArrayWithEscapes() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_2.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+        fxmlLoader.load();
+            
+        Widget widget = (Widget)fxmlLoader.getNamespace().get("widget1");
+        assertEquals(Arrays.asList(new String[]{"@a", "%b", "$c", "@c", "%d", "$e"}), widget.getStyles());
+        assertTrue(Arrays.equals(  new String[]{"@a", "%b", "$c", "@c", "%d", "$e"}, widget.getNames()));
+    }
+    
+    @Test
+    public void testListAndArrayWithRelativePath() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_3.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        Widget widget = (Widget)fxmlLoader.load();
+        assertEquals(Arrays.asList(new String[]{
+            new URL(fxmlLoader.getLocation(), "a").toString(),
+            new URL(fxmlLoader.getLocation(), "b").toString(),
+            new URL(fxmlLoader.getLocation(), "c").toString()}), widget.getStyles());
+    }
+    
+    @Test
+    public void testListAndArrayWithReference() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_4.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        fxmlLoader.load();
+        Widget widget = (Widget)fxmlLoader.getNamespace().get("widget1");
+        assertEquals(Arrays.asList(new String[]{"ABC", "ABC"}), widget.getStyles());
+        assertTrue(Arrays.equals(new String[]{"ABC", "ABC"}, widget.getNames()));
+        assertTrue(Arrays.equals(new float[] {1.0f, 1.0f}, widget.getRatios()));
+    }
+}
--- a/javafx-fxml/test/javafx/fxml/Widget.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-fxml/test/javafx/fxml/Widget.java	Wed Jan 16 11:42:20 2013 -0800
@@ -52,6 +52,7 @@
     private ArrayList<String> styles = new ArrayList<String>();
     private ArrayList<String> values = new ArrayList<String>();
     private float[] ratios = new float[]{};
+    private String[] names = new String[]{};
 
     public static final String ALIGNMENT_KEY = "alignment";
     public static final int TEN = 10;
@@ -144,6 +145,15 @@
     public void setRatios(float[] ratios) {
         this.ratios = Arrays.copyOf(ratios, ratios.length);
     }
+    
+    public String[] getNames() {
+        return Arrays.copyOf(names, names.length);
+    }
+
+    public void setNames(String[] names) {
+        this.names = Arrays.copyOf(names, names.length);
+    }
+
 
     public static Alignment getAlignment(Widget widget) {
         return (Alignment)widget.getProperties().get(ALIGNMENT_KEY);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_26449.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<?import javafx.scene.control.*?>
+
+<fx:root type="javafx.scene.layout.VBox" fx:id="default_root" xmlns:fx="http://javafx.com/fxml">
+    <Label text="Label in VBox"/>
+</fx:root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529.properties	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,6 @@
+itema=a
+itemb=b
+itemc=c
+ratio1=1.0
+ratio2=2.0
+ratio3=3.0
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_1.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<?import javafx.fxml.*?>
+
+<Widget styles="%itema, %itemb, %itemc" names="%itema, %itemb, %itemc" ratios="%ratio1, %ratio2, %ratio3"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_2.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<?import javafx.fxml.*?>
+<?import java.lang.*?>
+<Widget xmlns:fx="http://javafx.com/fxml">
+    <Widget fx:id="widget1" 
+            styles="@@a, %%b, $$c, \@c, \%d, \$e" 
+            names="@@a, %%b, $$c, \@c, \%d, \$e,"
+            ratios="1.0, 2.0, 3.0"/>
+</Widget>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_3.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<?import javafx.fxml.*?>
+
+<Widget styles="@a, @b, @c" ratios="1.0, 2.0, 3.0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_4.fxml	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<?import javafx.fxml.*?>
+<?import java.lang.*?>
+
+<Widget xmlns:fx="http://javafx.com/fxml">
+    <fx:define>
+        <String fx:id="str" fx:value="ABC"/>
+        <Float fx:id="flt" fx:value="1.0f"/>
+    </fx:define>
+    <Widget fx:id="widget1" 
+            styles="$str, $str" 
+            names="$str, $str"
+            ratios="$flt, $flt"/>
+</Widget>
--- a/javafx-geom/src/com/sun/javafx/geom/transform/GeneralTransform3D.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-geom/src/com/sun/javafx/geom/transform/GeneralTransform3D.java	Wed Jan 16 11:42:20 2013 -0800
@@ -248,10 +248,8 @@
     /**
      * Sets the value of this transform to a perspective projection transform.
      * This transform maps points from Eye Coordinates (EC)
-     * to Clipping Coordinates (CC).  Note that unlike the similar function
-     * in OpenGL, the clipping coordinates generated by the resulting
-     * transform are in a right-handed coordinate system. Also note that the
-     * field of view is specified in radians.
+     * to Clipping Coordinates (CC).
+     * Note that the field of view is specified in radians.
      *
      * @param fovy specifies the field of view in the y direction, in radians
      *
@@ -280,9 +278,6 @@
 
         mat[0] = cotangent / aspect;
         mat[5] = cotangent;
-        // TODO: resolve whether perspective matrices are right-handed (ala Java 3D)
-        // or left-handed (ala OpenGL). Currently we assume OpenGL-style left-handed
-        // matrices. (RT-26887)
         mat[10] = -(zFar + zNear) / deltaZ;
         mat[11] = -2.0 * zNear * zFar / deltaZ;
         mat[14] = -1.0;
--- a/javafx-sg-common/src/com/sun/javafx/sg/PGRegion.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-sg-common/src/com/sun/javafx/sg/PGRegion.java	Wed Jan 16 11:42:20 2013 -0800
@@ -58,8 +58,9 @@
      * @param shape    The shape, may be null.
      * @param scaleShape whether to scale the shape
      * @param positionShape whether to center the shape
+     * @param cacheShape whether to attempt region caching for the shape-based region
      */
-    public void updateShape(Object shape, boolean scaleShape, boolean positionShape);
+    public void updateShape(Object shape, boolean scaleShape, boolean positionShape, boolean cacheShape);
 
     /**
      * The opaque insets as specified either by the user, or as determined by
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Wed Jan 16 11:42:20 2013 -0800
@@ -130,6 +130,11 @@
     private boolean centerShape = true;
 
     /**
+     * Whether we should attempt to use region caching for a region with a shape.
+     */
+    private boolean cacheShape = false;
+
+    /**
      * A cached set of the opaque insets as given to us during synchronization. We hold
      * on to this so that we can determine the opaque insets in the computeOpaqueRegion method.
      */
@@ -172,10 +177,11 @@
      * @param scaleShape whether to scale the shape
      * @param positionShape whether to center the shape
      */
-    @Override public void updateShape(Object shape, boolean scaleShape, boolean positionShape) {
+    @Override public void updateShape(Object shape, boolean scaleShape, boolean positionShape, boolean cacheShape) {
         this.shape = shape == null ? null : ((NGShape) ((javafx.scene.shape.Shape)shape).impl_getPGNode()).getShape();
         this.scaleShape = scaleShape;
         this.centerShape = positionShape;
+        this.cacheShape = cacheShape;
         invalidateOpaqueRegion();
     }
 
@@ -228,7 +234,7 @@
 
         float top=0, right=0, bottom=0, left=0;
         final List<BackgroundFill> fills = background.getFills();
-        backgroundCanBeCached = !PrismSettings.disableRegionCaching && !fills.isEmpty();
+        backgroundCanBeCached = !PrismSettings.disableRegionCaching && !fills.isEmpty() && (shape == null || cacheShape);
         if (backgroundCanBeCached) {
             for (int i = 0, max = fills.size(); i < max; i++) {
                 final BackgroundFill fill = fills.get(i);
--- a/javafx-ui-charts/src/javafx/scene/chart/BubbleChart.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-charts/src/javafx/scene/chart/BubbleChart.java	Wed Jan 16 11:42:20 2013 -0800
@@ -108,7 +108,6 @@
                         StackPane region = (StackPane)item.getNode();
                         if (region.getShape() == null) {
                             ellipse = new Ellipse(getDoubleValue(item.getExtraValue(), 1), getDoubleValue(item.getExtraValue(), 1));
-                            region.setShape(ellipse);
                         } else if (region.getShape() instanceof Ellipse) {
                             ellipse = (Ellipse)region.getShape();
                         } else {
@@ -123,6 +122,7 @@
                         region.setShape(ellipse);
                         region.setScaleShape(false);
                         region.setCenterShape(false);
+                        region.setCacheShape(false);
                         // position the bubble
                         bubble.setLayoutX(x);
                         bubble.setLayoutY(y);
--- a/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Wed Jan 16 11:42:20 2013 -0800
@@ -24,13 +24,15 @@
  */
 package javafx.scene.chart;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
+import javafx.animation.Animation;
 import javafx.animation.FadeTransition;
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.DoublePropertyBase;
@@ -51,21 +53,24 @@
 import javafx.geometry.Side;
 import javafx.scene.Node;
 import javafx.scene.layout.Region;
-import javafx.scene.shape.*;
+import javafx.scene.shape.Arc;
+import javafx.scene.shape.ArcTo;
+import javafx.scene.shape.ArcType;
+import javafx.scene.shape.ClosePath;
+import javafx.scene.shape.LineTo;
+import javafx.scene.shape.MoveTo;
+import javafx.scene.shape.Path;
 import javafx.scene.text.Text;
 import javafx.scene.transform.Scale;
 import javafx.util.Duration;
-
 import com.sun.javafx.charts.Legend;
 import com.sun.javafx.charts.Legend.LegendItem;
 import com.sun.javafx.collections.NonIterableChange;
+import com.sun.javafx.css.CssMetaData;
 import com.sun.javafx.css.StyleableBooleanProperty;
 import com.sun.javafx.css.StyleableDoubleProperty;
-import com.sun.javafx.css.CssMetaData;
 import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.SizeConverter;
-import java.util.ArrayList;
-import javafx.animation.*;
 
 /**
  * Displays a PieChart. The chart content is populated by pie slices based on
@@ -334,7 +339,7 @@
         // check if symbol has already been created
         if (arcRegion == null) {
             arcRegion = new Region();
-            arcRegion.setPickOnBounds(false); 
+            arcRegion.setPickOnBounds(false);
             item.setNode(arcRegion);
         }
         // Note: not sure if we want to add or check, ie be more careful and efficient here
@@ -601,6 +606,7 @@
                         arcRegion.setShape(arc);
                         arcRegion.setScaleShape(false);
                         arcRegion.setCenterShape(false);
+                        arcRegion.setCacheShape(false);
                     }
                 }
                 double size = (isClockwise()) ? (-scale * Math.abs(item.getCurrentPieValue())) : (scale * Math.abs(item.getCurrentPieValue()));
--- a/javafx-ui-common/src/com/sun/javafx/application/PlatformImpl.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/com/sun/javafx/application/PlatformImpl.java	Wed Jan 16 11:42:20 2013 -0800
@@ -60,6 +60,12 @@
     private static Set<FinishListener> finishListeners =
             new CopyOnWriteArraySet<FinishListener>();
     private final static Object runLaterLock = new Object();
+    private static Boolean isGraphicsSupported;
+    private static Boolean isControlsSupported;
+    private static Boolean isWebSupported;
+    private static Boolean isSWTSupported;
+    private static Boolean isSwingSupported;
+    private static Boolean isFXMLSupported;
 
     /**
      * Set a flag indicating whether this application should show up in the
@@ -336,8 +342,53 @@
         }
     }
 
+    private static Boolean checkForClass(String classname) {
+        try {
+            Class.forName(classname, false, PlatformImpl.class.getClassLoader());
+            return Boolean.TRUE;
+        } catch (ClassNotFoundException cnfe) {
+            return Boolean.FALSE;
+        }
+    }
+
     public static boolean isSupported(ConditionalFeature feature) {
-        return Toolkit.getToolkit().isSupported(feature);
+        switch (feature) {
+            case GRAPHICS:
+                if (isGraphicsSupported == null) {
+                    isGraphicsSupported = checkForClass("javafx.stage.Stage");
+                }
+                return isGraphicsSupported;
+            case CONTROLS:
+                if (isControlsSupported == null) {
+                    isControlsSupported = checkForClass(
+                            "javafx.scene.control.Control");
+                }
+                return isControlsSupported;
+            case WEB:
+                if (isWebSupported == null) {
+                    isWebSupported = checkForClass("javafx.scene.web.WebView");
+                }
+                return isWebSupported;
+            case SWT:
+                if (isSWTSupported == null) {
+                    isSWTSupported = checkForClass("javafx.embed.swt.FXCanvas");
+                }
+                return isSWTSupported;
+            case SWING:
+                if (isSwingSupported == null) {
+                    isSwingSupported = checkForClass(
+                            "javafx.embed.swing.JFXPanel");
+                }
+                return isSwingSupported;
+            case FXML:
+                if (isFXMLSupported == null) {
+                    isFXMLSupported = checkForClass("javafx.fxml.FXMLLoader")
+                            && checkForClass("javax.xml.stream.XMLInputFactory");
+                }
+                return isFXMLSupported;
+            default:
+                return Toolkit.getToolkit().isSupported(feature);
+        }
     }
 
     public static interface FinishListener {
--- a/javafx-ui-common/src/javafx/application/ConditionalFeature.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/application/ConditionalFeature.java	Wed Jan 16 11:42:20 2013 -0800
@@ -38,6 +38,46 @@
 public enum ConditionalFeature {
 
     /**
+     * Indicates that JavaFX classes providing graphics capabilities are
+     * available on this platform.
+     */
+    GRAPHICS,
+
+    /**
+     * Indicates that JavaFX classes providing UI controls are available on
+     * this platform.
+     */
+    CONTROLS,
+
+    /**
+     * Indicates that the javafx.scene.web packages is available on this
+     * platform.
+     */
+    WEB,
+
+    /**
+     * Indicates that SWT integration is available on the platform. This tests
+     * for SWT integration with JavaFX, but does not test for the presence of
+     * the full SWT library.
+     */
+    SWT,
+
+    /* Indicates that the Swing library is present in the Java Runtime
+     * Environment and that Swing integration with JavaFX is available on the
+     * platform.
+     */
+    SWING,
+
+
+    /* Indicates that XML libraries are present in the JRE and that the FXML
+     * API is available on the platform. Note that it is possible for FXML APIs
+     * to be present but unusable if the underlying Java Runtime Environment
+     * does not have XML support. In this case
+     * Platform.isSupported(ConditionalFeature.FXML) wll return false.
+     */
+    FXML,
+
+    /**
      * Indicates that 3D is available on the platform.
      * If an application attempts to use 3D transforms or a 3D camera on a
      * platform that does not support 3D, then the transform or camera is
--- a/javafx-ui-common/src/javafx/scene/Scene.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/Scene.java	Wed Jan 16 11:42:20 2013 -0800
@@ -92,7 +92,6 @@
 import com.sun.javafx.cursor.CursorFrame;
 import com.sun.javafx.event.EventQueue;
 import com.sun.javafx.geom.PickRay;
-import com.sun.javafx.geom.transform.Affine2D;
 import com.sun.javafx.geom.transform.BaseTransform;
 import sun.util.logging.PlatformLogger;
 import com.sun.javafx.perf.PerformanceTracker;
@@ -325,7 +324,7 @@
                     return parent.getChildren(); //was impl_getChildren
                 }
                 public Object renderToImage(Scene scene, Object platformImage) {
-                    return scene.renderToImage(platformImage);
+                    return scene.snapshot(null).impl_getPlatformImage();
                 }
             });
             Toolkit.setSceneAccessor(new Toolkit.SceneAccessor() {
@@ -1029,51 +1028,6 @@
         return root;
     }
 
-    /**
-     * This method is superseded by {@link #snapshot(javafx.scene.image.WritableImage)}
-     *
-     * WARNING: This method is not part of the public API and is
-     * subject to change!  It is intended for use by the designer tool only.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: RT-21222 has been filed to track this
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public Object renderToImage(Object platformImage) {
-        return renderToImage(platformImage, 1.0f);
-    }
-
-    /**
-     * Renders this {@code Scene} to the given platform-specific image
-     * (e.g. a {@code BufferedImage} in the case of the Swing profile)
-     * using the specified scaling factor.
-     * If {@code platformImage} is null, a new platform-specific image
-     * is returned.
-     * If the contents of the scene have not changed since the last time
-     * this method was called, this method returns null.
-     *
-     * WARNING: This method is not part of the public API and is
-     * subject to change!  It is intended for use by the designer tool only.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    @Deprecated
-    public Object renderToImage(Object platformImage, float scale) {
-        if (!paused) {
-            Toolkit.getToolkit().checkFxUserThread();
-        }
-
-        // NOTE: that we no longer use the passed in platform image. Since this
-        // API is deprecated and will be removed in 3.0 this is not a concern.
-        // Also, we used to return a TK image loader and now we return
-        // the actual TK PlatformImage.
-        return doSnapshot(null, scale).impl_getPlatformImage();
-    }
-
     private void doLayoutPassWithoutPulse(int maxAttempts) {
         for (int i = 0; dirtyLayoutRoots.size() > 0 && i != maxAttempts; ++i) {
             layoutDirtyRoots();
@@ -1165,7 +1119,7 @@
     /**
      * Implementation method for snapshot
      */
-    private WritableImage doSnapshot(WritableImage img, float scale) {
+    private WritableImage doSnapshot(WritableImage img) {
         // TODO: no need to do CSS, layout or sync in the deferred case,
         // if this scene is attached to a visible stage
         doCSSLayoutSyncForSnapshot(getRoot());
@@ -1173,13 +1127,6 @@
         double w = getWidth();
         double h = getHeight();
         BaseTransform transform = BaseTransform.IDENTITY_TRANSFORM;
-        if (scale != 1.0f) {
-            Affine2D tx = new Affine2D();
-            tx.scale(scale, scale);
-            transform = tx;
-            w *= scale;
-            h *= scale;
-        }
 
         return doSnapshot(this, 0, 0, w, h,
                 getRoot(), transform, isDepthBuffer(),
@@ -1268,7 +1215,7 @@
             Toolkit.getToolkit().checkFxUserThread();
         }
 
-        return  doSnapshot(image, 1.0f);
+        return doSnapshot(image);
     }
 
     /**
@@ -1330,7 +1277,7 @@
         // any of them have been rendered.
         final Runnable snapshotRunnable = new Runnable() {
             @Override public void run() {
-                WritableImage img = doSnapshot(theImage, 1.0f);
+                WritableImage img = doSnapshot(theImage);
 //                System.err.println("Calling snapshot callback");
                 SnapshotResult result = new SnapshotResult(img, Scene.this, null);
                 try {
--- a/javafx-ui-common/src/javafx/scene/doc-files/cssref.html	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/doc-files/cssref.html	Wed Jan 16 11:42:20 2013 -0800
@@ -3700,7 +3700,7 @@
           <td>&nbsp;</td>
         </tr>
         <tr>
-          <td class="propertyname">-fx-page-information-visible:</td>
+          <td class="propertyname">-fx-page-information-visible</td>
           <td class="value"><a href="#typesize" class="typelink">&lt;boolean&gt;</a></td>
           <td>true</td>
           <td>&nbsp;</td>
--- a/javafx-ui-common/src/javafx/scene/image/Image.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/image/Image.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1018,57 +1018,6 @@
     }
 
     /**
-     * This method converts a JavaFX Image to the specified image class or
-     * to an image of the same class and the same format as specified image.
-     * If the specified image class is not supported, then null will be returned.
-     *
-     * @param imgType either a Class object that specifies the type of image,
-     *      or an actual image object of the desired type and format.
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public Object impl_toExternalImage(Object imgType) {
-        return Toolkit.getToolkit().toExternalImage(impl_getPlatformImage(), imgType);
-    }
-
-    /**
-     * This method converts the specified image to a JavaFX Image.
-     * If the specified image class is not supported, then null will be returned.
-     *
-     * @param extImage - an image to convert.
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public static Image impl_fromExternalImage(Object extImage) {
-        return impl_isExternalFormatSupported(extImage.getClass())
-                ? new Image(extImage)
-                : null;
-    }
-
-    /**
-     * This method indicates whether conversion to/from the specified external
-     * format is possible.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public static boolean impl_isExternalFormatSupported(Class format) {
-        return Toolkit.getToolkit().isExternalFormatSupported(format);
-    }
-
-    /**
      * Indicates whether image is animated.
      */
     boolean isAnimation() {
--- a/javafx-ui-common/src/javafx/scene/layout/Region.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/layout/Region.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1046,13 +1046,13 @@
         }
         return centerShape;
     }
+
     /**
-     * Defines whether the shape is centered within the Region's width or height.
-     * {@code true} means the shape centered within the Region's width and height,
-     * {@code false} means the shape is positioned at its source position.
+     * Defines a hint to the system indicating that the Shape used to define the region's
+     * background is stable and would benefit from caching.
      *
      * @default true
-     * @css position-shape      true | false
+     * @css -fx-cache-shape      true | false
      */
     private BooleanProperty cacheShape = null;
     public final void setCacheShape(boolean value) { cacheShapeProperty().set(value); }
@@ -1864,7 +1864,7 @@
         // the shape must be specified before the background which is before the border.
         final boolean shapeChanged = impl_isDirty(DirtyBits.REGION_SHAPE);
         if (shapeChanged) {
-            pg.updateShape(_shape, isScaleShape(), isCenterShape());
+            pg.updateShape(_shape, isScaleShape(), isCenterShape(), isCacheShape());
         }
 
         final boolean backgroundChanged = impl_isDirty(DirtyBits.SHAPE_FILL);
--- a/javafx-ui-common/src/javafx/scene/text/Text.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/text/Text.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1159,7 +1159,6 @@
             if (impl_mode != Mode.FILL && getStrokeType() != StrokeType.INSIDE) {
                 return super.impl_computeGeomBounds(bounds, tx);
             }
-
             TextLayout layout = getTextLayout();
             bounds = layout.getBounds(getTextSpan(), bounds);
             BaseBounds spanBounds = getSpanBounds();
@@ -1187,7 +1186,20 @@
         float width = textBounds.getWidth();
         float height = textBounds.getHeight();
         float wrappingWidth = (float)getWrappingWidth();
-        if (wrappingWidth > width) width = wrappingWidth;
+        if (wrappingWidth > width) {
+            width = wrappingWidth;
+        } else {
+            /* The following adjustment is necessary for the text bounds to be
+             * relative to the same location as the mirrored bounds returned
+             * by layout.getBounds().
+             */
+            if (wrappingWidth > 0) {
+                NodeOrientation orientation = getEffectiveNodeOrientation();
+                if (orientation == NodeOrientation.RIGHT_TO_LEFT) {
+                    x -= width - wrappingWidth;
+                }
+            }
+        }
         textBounds = new RectBounds(x, y, x + width, y + height);
 
         /* handle stroked text */
--- a/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Wed Jan 16 11:42:20 2013 -0800
@@ -447,68 +447,6 @@
         return lastAsyncImageLoader;
     }
 
-    // lets test following:  ;)
-    // 
-    //  public static boolean impl_isExternalFormatSupported(Class format) {
-    //    return Toolkit.getToolkit().isExternalFormatSupported(format);
-    // }
-    @Test
-    public void isExternalFormatSupportedTest() {
-        toolkit.externalFormatClass = StubToolkit.class;
-        assertFalse(Image.impl_isExternalFormatSupported(null));
-        assertTrue(Image.impl_isExternalFormatSupported(StubToolkit.class));
-        toolkit.externalFormatClass = ImageTest.class;
-        assertFalse(Image.impl_isExternalFormatSupported(StubToolkit.class));
-        assertTrue(Image.impl_isExternalFormatSupported(ImageTest.class));
-    }
-
-    // lets test 
-    //    public Object impl_toExternalImage(Object imgType) {
-    //        return Toolkit.getToolkit().toExternalImage(getPlatformImage(), imgType);
-    //    }
-    @Test
-    public void impl_toExternalImageTest() {
-        final Object fakePlatformImage = "fakePlatformImage";
-        registerImage(fakePlatformImage, 200, 500);
-        final Image image = Image.impl_fromPlatformImage(fakePlatformImage);
-
-        StubPlatformImage spi = (StubPlatformImage) image.impl_getPlatformImage();
-        assertTrue(spi.getSource() == fakePlatformImage);
-
-        final Object format = "image format object";
-        final Object password = "password";
-
-        toolkit.toExternalImagePassword = password;
-
-        Object extImage = image.impl_toExternalImage(format);
-        Object[] data = (Object[]) extImage;
-
-        assertTrue(
-                data.length == 3
-                && data[0] == spi
-                && data[1] == format
-                && data[2] == password);
-    }
-
-    // lets test 
-    //    public Object impl_fromExternalImage(Object image)
-    // it is more comlex
-    // we have to be sure impl_isExternalFormatSupported for image.class.
-    // and until it is not "null" returned
-    @Test
-    public void impl_fromExternalImageTest() {
-        toolkit.externalFormatClass = ImageTest.class;
-        final Object fakeExternalImage = "fakeExternalImage";
-        registerImage(fakeExternalImage, 123, 456);
-
-        assertFalse(Image.impl_isExternalFormatSupported(fakeExternalImage.getClass()));
-        assertNull(Image.impl_fromExternalImage(fakeExternalImage));
-
-        toolkit.externalFormatClass = fakeExternalImage.getClass();
-        final Image image = Image.impl_fromExternalImage(fakeExternalImage);
-        verifyLoadedImage(image, 0, 0, false, false, 123, 456);
-    }
-    
     @Test
     public void createImageFromClasspathTest() {
         final String url = "javafx/scene/image/test.png";
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ColorPickerBehavior.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ColorPickerBehavior.java	Wed Jan 16 11:42:20 2013 -0800
@@ -83,7 +83,6 @@
     }
 
     @Override protected void callAction(String name) {
-        ColorPicker colorPicker = (ColorPicker)getControl();
         if (OPEN_ACTION.equals(name)) {
             show();
         } else if(CLOSE_ACTION.equals(name)) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Wed Jan 16 11:42:20 2013 -0800
@@ -348,9 +348,10 @@
                     // to indicate the text can be dragged, etc.
                 } else if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
                     switch (e.getClickCount()) {
-                      case 1: skin.positionCaret(hit, false, false); break;
-                      case 2: mouseDoubleClick(hit); break;
-                      case 3: mouseTripleClick(hit); break;
+                        case 1: skin.positionCaret(hit, false, false); break;
+                        case 2: mouseDoubleClick(hit); break;
+                        case 3: mouseTripleClick(hit); break;
+                        default: // no-op
                     }
                 } else if (e.isShiftDown() && !(e.isControlDown() || e.isAltDown() || e.isMetaDown()) && e.getClickCount() == 1) {
                     // didn't click inside the selection, so select
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java	Wed Jan 16 11:42:20 2013 -0800
@@ -60,45 +60,7 @@
  * Text field behavior.
  */
 public class TextFieldBehavior extends TextInputControlBehavior<TextField> {
-    public static final int SCROLL_RATE = 15;
     private TextFieldSkin skin;
-    private HorizontalDirection scrollDirection = null;
-    private Timeline scrollSelectionTimeline = new Timeline();
-    private EventHandler<ActionEvent> scrollSelectionHandler = new EventHandler<ActionEvent>() {
-        @Override
-        public void handle(ActionEvent event) {
-            TextField textField = getControl();
-
-            IndexRange selection = textField.getSelection();
-            int start = selection.getStart();
-            int end = selection.getEnd();
-
-            switch (scrollDirection) {
-                case RIGHT: {
-                    if (end < textField.getLength()) {
-                        end++;
-                        textField.selectRange(start, end);
-                    }
-
-                    break;
-                }
-
-                case LEFT: {
-                    if (start > 0) {
-                        start--;
-                        textField.selectRange(start, end);
-                    }
-
-                    break;
-                }
-
-                default: {
-                    throw new RuntimeException();
-                }
-            }
-        }
-    };
-
     private ContextMenu contextMenu;
     private TwoLevelFocusBehavior tlFocus;
 
@@ -110,10 +72,6 @@
             contextMenu.getStyleClass().add("text-input-context-menu");
         }
 
-        // Initialize scroll timeline
-        scrollSelectionTimeline.setCycleCount(Timeline.INDEFINITE);
-        List<KeyFrame> scrollTimelineKeyFrames = scrollSelectionTimeline.getKeyFrames();
-        scrollTimelineKeyFrames.add(new KeyFrame(Duration.millis(SCROLL_RATE), scrollSelectionHandler));
         handleFocusChange();
 
         // Register for change events
@@ -278,6 +236,7 @@
                         case 1: mouseSingleClick(hit); break;
                         case 2: mouseDoubleClick(hit); break;
                         case 3: mouseTripleClick(hit); break;
+                        default: // no-op
                     }
                 } else if (e.isShiftDown() && !(e.isControlDown() || e.isAltDown() || e.isMetaDown()) && e.getClickCount() == 1) {
                     // didn't click inside the selection, so select
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/AccordionSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/AccordionSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -39,6 +39,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import javafx.geometry.Insets;
 
 public class AccordionSkin extends BehaviorSkinBase<Accordion, AccordionBehavior> {
 
@@ -78,7 +79,7 @@
 
         initTitledPaneListeners(accordion.getPanes());
         getChildren().setAll(accordion.getPanes());
-        requestLayout();
+        getSkinnable().requestLayout();
 
         registerChangeListener(getSkinnable().widthProperty(), "WIDTH");
         registerChangeListener(getSkinnable().heightProperty(), "HEIGHT");
@@ -88,9 +89,9 @@
     protected void handleControlPropertyChanged(String property) {
         super.handleControlPropertyChanged(property);
         if ("WIDTH".equals(property)) {
-            clipRect.setWidth(getWidth());
+            clipRect.setWidth(getSkinnable().getWidth());
         } else if ("HEIGHT".equals(property)) {
-            clipRect.setHeight(getHeight());
+            clipRect.setHeight(getSkinnable().getHeight());
         }
     }
 
@@ -122,7 +123,9 @@
                 h += snapSize(pane.minHeight(width));
             }
         }
-        return h + snapSpace(getInsets().getTop()) + snapSpace(getInsets().getBottom());
+        
+        Insets insets = getSkinnable().getInsets();
+        return h + snapSpace(insets.getTop()) + snapSpace(insets.getBottom());
     }
 
     @Override protected void layoutChildren(final double x, double y,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/AsciiBoard.txt	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,5 @@
+[`|~ ][1|! ][2|@ ][3|# ][4|\$ ][5|% ][6|^ ][7|& ][8|* ][9|( ][0|) ][-|_ ][=|+ ][$backspace  ]
+[$tab  ][q ][w ][e ][r ][t ][y ][u ][i ][o ][p ][\[|{ ][\]|} ][\\|\| ]
+[$caps   ][a ][s ][d ][f ][g ][h ][j ][k ][l ][;|: ]['|" ][$enter  ]
+[$shift    ][z ][x ][c ][v ][b ][n ][m ][,|< ][.|> ][/|? ][$shift   ]
+[$hide   ][$SymbolBoard  ][$space               ][$SymbolBoard  ][$hide  ]
\ No newline at end of file
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ButtonSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ButtonSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -122,7 +122,7 @@
         defaultAcceleratorKeyCodeCombination = 
                 new KeyCodeCombination(acceleratorCode);
 
-        if (value == false) {
+        if (! value) {
             /*
             ** first check of there's a default button already
             */
@@ -134,12 +134,6 @@
                 getSkinnable().getParent().getScene().getAccelerators().remove(defaultAcceleratorKeyCodeCombination);
             }
         }
-        else {
-            /*
-            ** first check of there's a default button already
-            */
-            Runnable oldDefault = getSkinnable().getParent().getScene().getAccelerators().get(defaultAcceleratorKeyCodeCombination);
-        }
         getSkinnable().getParent().getScene().getAccelerators().put(defaultAcceleratorKeyCodeCombination, defaultButtonRunnable);
     }
 
@@ -147,10 +141,9 @@
 
     private void setCancelButton(boolean value) {
         KeyCode acceleratorCode = KeyCode.ESCAPE;
-        cancelAcceleratorKeyCodeCombination =
-                new KeyCodeCombination(acceleratorCode);
+        cancelAcceleratorKeyCodeCombination = new KeyCodeCombination(acceleratorCode);
         
-        if (value == false) {
+        if (! value) {
             /*
             ** first check of there's a default button already
             */
@@ -161,12 +154,6 @@
                 */
                 getSkinnable().getParent().getScene().getAccelerators().remove(cancelAcceleratorKeyCodeCombination);
             }
-        }
-        else {
-            /*
-            ** first check of there's a default button already
-            */
-            Runnable oldDefault = getSkinnable().getParent().getScene().getAccelerators().get(cancelAcceleratorKeyCodeCombination);
         }        
         getSkinnable().getParent().getScene().getAccelerators().put(cancelAcceleratorKeyCodeCombination, cancelButtonRunnable);
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CellSkinBase.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CellSkinBase.java	Wed Jan 16 11:42:20 2013 -0800
@@ -38,7 +38,6 @@
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.ReadOnlyDoubleProperty;
 import javafx.beans.value.WritableValue;
-import javafx.scene.control.IndexedCell;
 import javafx.scene.control.SkinBase;
 
 
@@ -67,9 +66,7 @@
     private DoubleProperty cellSizePropertyImpl() {
         if (cellSize == null) {
             cellSize = new StyleableDoubleProperty(DEFAULT_CELL_SIZE) {
-
-                @Override
-                public void set(double value) {
+                @Override public void set(double value) {
 //                    // Commented this out due to RT-19794, because otherwise
 //                    // cellSizeSet would be false when the default caspian.css
 //                    // cell size was set. This would lead to 
@@ -77,22 +74,19 @@
 //                    // of the cell (which is about 22px), rather than use the 
 //                    // value provided by caspian.css (which is 24px).
 //                    // cellSizeSet = true;//value != DEFAULT_CELL_SIZE;
-                     super.set(value);
-                    requestLayout();
+                    super.set(value);
+                    getSkinnable().requestLayout();
                 }
                 
-                @Override
-                public Object getBean() {
+                @Override public Object getBean() {
                     return CellSkinBase.this;
                 }
 
-                @Override
-                public String getName() {
+                @Override public String getName() {
                     return "cellSize";
                 }
 
-                @Override
-                public CssMetaData getCssMetaData() {
+                @Override public CssMetaData getCssMetaData() {
                     return StyleableProperties.CELL_SIZE;
                 }
             }; 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CheckBoxSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CheckBoxSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -40,13 +40,12 @@
  */
 public class CheckBoxSkin extends LabeledSkinBase<CheckBox, ButtonBehavior<CheckBox>> {
 
-    private StackPane box;
+    private final StackPane box = new StackPane();
     private StackPane innerbox;
 
     public CheckBoxSkin(CheckBox checkbox) {
         super(checkbox, new ButtonBehavior<CheckBox>(checkbox));
 
-        box = new StackPane();
         box.getStyleClass().setAll("box");
         innerbox = new StackPane();
         innerbox.getStyleClass().setAll("mark");
@@ -67,14 +66,15 @@
     }
 
     @Override protected double computePrefHeight(double width) {
+        Insets insets = getSkinnable().getInsets();
         return Math.max(super.computePrefHeight(width - box.prefWidth(-1)),
-                        getInsets().getTop() + box.prefHeight(-1) + getInsets().getBottom());
+                        insets.getTop() + box.prefHeight(-1) + insets.getBottom());
     }
 
 
     @Override protected void layoutChildren(final double x, final double y,
             final double w, final double h) {
-        Insets padding = getInsets();
+        Insets padding = getSkinnable().getInsets();
 
         final double boxWidth = box.prefWidth(-1);
         final double boxHeight = box.prefHeight(-1);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ChoiceBoxSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ChoiceBoxSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -52,6 +52,7 @@
 
 import com.sun.javafx.scene.control.behavior.ChoiceBoxBehavior;
 import javafx.collections.WeakListChangeListener;
+import javafx.geometry.Insets;
 
 
 /**
@@ -62,7 +63,7 @@
     public ChoiceBoxSkin(ChoiceBox control) {
         super(control, new ChoiceBoxBehavior(control));
         initialize();
-        requestLayout();
+        control.requestLayout();
         registerChangeListener(control.selectionModelProperty(), "SELECTION_MODEL");
         registerChangeListener(control.showingProperty(), "SHOWING");
         registerChangeListener(control.itemsProperty(), "ITEMS");
@@ -98,7 +99,7 @@
                         addPopupItem(obj, i);
                         i++;
                     }
-                    requestLayout(); // RT-18052
+                    getSkinnable().requestLayout(); // RT-18052
                     return;
                 }
                 for (int i = c.getFrom(); i < c.getTo(); i++) {
@@ -110,7 +111,7 @@
             // RT-21891 weird initial appearance: need a better fix for this instead
             // of having to rely on impl_processCSS. 
             popup.getScene().getRoot().impl_processCSS(true); 
-            requestLayout(); // RT-18052 resize of choicebox should happen immediately.
+            getSkinnable().requestLayout(); // RT-18052 resize of choicebox should happen immediately.
         }
     };
     
@@ -330,25 +331,29 @@
         // open button width/height
         double obw = openButton.prefWidth(-1);
 
-        label.resizeRelocate(getInsets().getLeft(), getInsets().getTop(), w, h);
+        ChoiceBox control = getSkinnable();
+        Insets insets = control.getInsets();
+        label.resizeRelocate(insets.getLeft(), insets.getTop(), w, h);
         openButton.resize(obw, openButton.prefHeight(-1));
-        positionInArea(openButton, getWidth() - getInsets().getRight() - obw,
-                getInsets().getTop(), obw, h, /*baseline ignored*/0, HPos.CENTER, VPos.CENTER);
+        positionInArea(openButton, control.getWidth() - insets.getRight() - obw,
+                insets.getTop(), obw, h, /*baseline ignored*/0, HPos.CENTER, VPos.CENTER);
     }
 
     @Override protected double computeMinWidth(double height) {
         final double boxWidth = label.minWidth(-1) + openButton.minWidth(-1);
         final double popupWidth = popup.minWidth(-1);
-        return getInsets().getLeft() + Math.max(boxWidth, popupWidth)
-                + getInsets().getRight();
+        final Insets insets = getSkinnable().getInsets();
+        return insets.getLeft() + Math.max(boxWidth, popupWidth)
+                + insets.getRight();
     }
 
     @Override protected double computeMinHeight(double width) {
         final double displayHeight = label.minHeight(-1);
         final double openButtonHeight = openButton.minHeight(-1);
-        return getInsets().getTop()
+        final Insets insets = getSkinnable().getInsets();
+        return insets.getTop()
                 + Math.max(displayHeight, openButtonHeight)
-                + getInsets().getBottom();
+                + insets.getBottom();
     }
 
     @Override protected double computePrefWidth(double height) {
@@ -360,16 +365,18 @@
                 popupWidth = (new Text(((MenuItem)popup.getItems().get(0)).getText())).prefWidth(-1);
             }
         }
-        return (popup.getItems().size() == 0) ? 50 : getInsets().getLeft() + Math.max(boxWidth, popupWidth)
-                + getInsets().getRight();
+        final Insets insets = getSkinnable().getInsets();
+        return (popup.getItems().size() == 0) ? 50 : insets.getLeft() + Math.max(boxWidth, popupWidth)
+                + insets.getRight();
     }
 
     @Override protected double computePrefHeight(double width) {
         final double displayHeight = label.prefHeight(-1);
         final double openButtonHeight = openButton.prefHeight(-1);
-        return getInsets().getTop()
+        final Insets insets = getSkinnable().getInsets();
+        return insets.getTop()
                 + Math.max(displayHeight, openButtonHeight)
-                + getInsets().getBottom();
+                + insets.getBottom();
     }
     
     @Override protected double computeMaxHeight(double width) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ColorPalette.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ColorPalette.java	Wed Jan 16 11:42:20 2013 -0800
@@ -205,6 +205,7 @@
                     case ENTER:
                         processSelectKey(ke);
                         break;
+                    default: // no-op
                 }
             }
         });
@@ -538,7 +539,6 @@
     class ColorPickerGrid extends GridPane {
 
         private final List<ColorSquare> squares;
-        Window owner;
 
         public ColorPickerGrid(Color initPaint) {
             getStyleClass().add("color-picker-grid");
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -137,7 +137,7 @@
             updateDisplayArea();
         }
         
-        final Insets padding = getInsets();
+        final Insets padding = getSkinnable().getInsets();
         final Insets arrowButtonPadding = arrowButton.getInsets();
 
         final double arrowWidth = snapSize(arrow.prefWidth(-1));
@@ -152,7 +152,8 @@
         if (isButton()) return;
         
         arrowButton.resize(arrowButtonWidth, h);
-        positionInArea(arrowButton, getWidth() - padding.getRight() - arrowButtonWidth, 0, 
+        positionInArea(arrowButton, 
+                getSkinnable().getWidth() - padding.getRight() - arrowButtonWidth, 0, 
                 arrowButtonWidth, h, 0, HPos.CENTER, VPos.CENTER);
     }
     
@@ -167,8 +168,8 @@
         
         final double totalWidth = (displayNode == null) ? 0 : (displayNode.prefWidth(height) 
                 + arrowButtonWidth);
-        return getInsets().getLeft() + totalWidth +
-                + getInsets().getRight();
+        final Insets padding = getSkinnable().getInsets();
+        return padding.getLeft() + totalWidth + padding.getRight();
     }
     
     @Override protected double computePrefHeight(double width) {
@@ -194,7 +195,7 @@
             ph = displayNode.prefHeight(width);
         }
 
-        final Insets padding = getInsets();
+        final Insets padding = getSkinnable().getInsets();
         return padding.getTop()+ ph + padding.getBottom();
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -91,7 +91,7 @@
     private final ListChangeListener listViewItemsListener = new ListChangeListener() {
         @Override public void onChanged(ListChangeListener.Change c) {
             itemCountDirty = true;
-            requestLayout();
+            getSkinnable().requestLayout();
         }
     };
     
@@ -256,7 +256,7 @@
         }
         
         itemCountDirty = true;
-        requestLayout();
+        getSkinnable().requestLayout();
     }
     
     @Override public Node getPopupContent() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxPopupControl.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxPopupControl.java	Wed Jan 16 11:42:20 2013 -0800
@@ -32,6 +32,7 @@
 import javafx.event.Event;
 import javafx.event.EventHandler;
 import javafx.geometry.HPos;
+import javafx.geometry.NodeOrientation;
 import javafx.geometry.Point2D;
 import javafx.geometry.VPos;
 import javafx.scene.Node;
@@ -84,7 +85,9 @@
     }
     
     private Point2D getPrefPopupPosition() {
-        return com.sun.javafx.Utils.pointRelativeTo(getSkinnable(), getPopupContent(), HPos.CENTER, VPos.BOTTOM, -7, -10, false);
+        double dx = (getPopupContent().getLayoutBounds().getWidth() - getPopup().getWidth()) / 2;
+        dx += (getSkinnable().getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) ? -1 : 1;
+        return com.sun.javafx.Utils.pointRelativeTo(getSkinnable(), getPopupContent(), HPos.CENTER, VPos.BOTTOM, dx, -10, false);
     }
     
     private void positionAndShowPopup() {
@@ -93,6 +96,7 @@
         }
         
         Point2D p = getPrefPopupPosition();
+        getPopup().getScene().setNodeOrientation(getSkinnable().getEffectiveNodeOrientation());
         getPopup().show(getSkinnable().getScene().getWindow(), p.getX(), p.getY());
     }
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/EmailBoard.txt	Wed Jan 16 11:42:20 2013 -0800
@@ -0,0 +1,5 @@
+[`|~ ][1|! ][2|, ][3|# ][4|\$ ][5|% ][6|^ ][7|& ][8|* ][9|( ][0|) ][-|_ ][=|+ ][$backspace  ]
+[$tab  ][q ][w ][e ][r ][t ][y ][u ][i ][o ][p ][\[|{ ][\]|} ][\\|\| ]
+[$caps   ][a ][s ][d ][f ][g ][h ][j ][k ][l ][;|: ]['|" ][$enter  ]
+[$shift    ][z ][x ][c ][v ][b ][n ][m ][@|< ][.|> ][/|? ][$shift   ]
+[$hide ][$.org  ][$.net  ][$space           ][$.com  ][$oracle.com   ][$hide ]
\ No newline at end of file
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVK.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVK.java	Wed Jan 16 11:42:20 2013 -0800
@@ -49,18 +49,48 @@
 import com.sun.javafx.css.CssMetaData;
 import com.sun.javafx.css.converters.BooleanConverter;
 
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.event.EventHandler;
+import javafx.scene.control.Control;
+import javafx.scene.input.KeyEvent;
+
+
 public class FXVK extends Control {
 
+    public enum Type {
+        TEXT,
+        NUMERIC,
+        EMAIL,
+    }
+
+    private final ObjectProperty<Type> type = new SimpleObjectProperty<Type>(this, "type");
+    public final Type getType() { return type.get(); }
+    public final void setType(Type value) { type.set(value); }
+    public final ObjectProperty<Type> typeProperty() { return type; }
+
+
+    private final ObjectProperty<EventHandler<KeyEvent>> onAction =
+            new SimpleObjectProperty<EventHandler<KeyEvent>>(this, "onAction");
+    public final void setOnAction(EventHandler<KeyEvent> value) { onAction.set(value); }
+    public final EventHandler<KeyEvent> getOnAction() { return onAction.get(); }
+    public final ObjectProperty<EventHandler<KeyEvent>> onActionProperty() { return onAction; }
+
+
     final static String[] VK_TYPE_NAMES = new String[] { "text", "numeric", "url", "email" };
     public final static String VK_TYPE_PROP_KEY = "vkType";
 
     String[] chars;
 
-    FXVK() {
-        setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
-        getStyleClass().setAll(DEFAULT_STYLE_CLASS);
+    public FXVK() {
+        this(Type.TEXT);
     }
 
+    public FXVK(Type type) {
+        this.type.set(type);
+        setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
+        getStyleClass().add(DEFAULT_STYLE_CLASS);
+    }
 
     final ObjectProperty<Node> attachedNodeProperty() {
         if (attachedNode == null) {
@@ -76,46 +106,29 @@
         }
         return attachedNode;
     }
+
     private ObjectProperty<Node> attachedNode;
     final void setAttachedNode(Node value) { attachedNodeProperty().setValue(value); }
     final Node getAttachedNode() { return attachedNode == null ? null : attachedNode.getValue(); }
-
-
-    int vkType;
     static FXVK vk;
-    private static HashMap<Integer, FXVK> vkMap = new HashMap<Integer, FXVK>();
 
     public static void attach(final Node textInput) {
         int type = 0;
         Object typeValue = textInput.getProperties().get(VK_TYPE_PROP_KEY);
+        String typeStr = "";
         if (typeValue instanceof String) {
-            String typeStr = ((String)typeValue).toLowerCase();
-            for (int i = 0; i < VK_TYPE_NAMES.length; i++) {
-                if (typeStr.equals(VK_TYPE_NAMES[i])) {
-                    type = i;
-                    break;
-                }
-            }
+            typeStr = ((String)typeValue).toLowerCase();
         }
 
-        vk = vkMap.get(type);
         if (vk == null) {
-            vk = new FXVK();
-            vk.vkType = type;
+            vk = new FXVK(Type.TEXT);
             vk.setSkin(new FXVKSkin(vk));
-            vkMap.put(type, vk);
-        }
-
-        for (FXVK v : vkMap.values()) {
-            if (v != vk) {
-                v.setAttachedNode(null);
-            }
         }
         vk.setAttachedNode(textInput);
     }
 
     public static void detach() {
-        for (FXVK vk : vkMap.values()) {
+        if (vk != null) {
             vk.setAttachedNode(null);
         }
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVKSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/FXVKSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -1,4 +1,4 @@
-/*
+ /*
  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -53,6 +53,8 @@
 import javafx.geometry.Pos;
 import javafx.geometry.Rectangle2D;
 import javafx.geometry.VPos;
+import javafx.geometry.Side;
+
 import javafx.scene.Group;
 import javafx.scene.Node;
 import javafx.scene.Parent;
@@ -62,6 +64,8 @@
 import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.*;
+import javafx.scene.image.*;
+
 import javafx.stage.*;
 import javafx.util.Duration;
 
@@ -76,8 +80,60 @@
 
 import static com.sun.javafx.scene.control.skin.resources.EmbeddedResources.*;
 
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javafx.event.EventHandler;
+import javafx.event.EventType;
+import javafx.geometry.Insets;
+import javafx.geometry.VPos;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.Region;
+import javafx.scene.text.Text;
+import com.sun.javafx.scene.control.behavior.BehaviorBase;
+import java.net.URL;
+
+
 public class FXVKSkin extends BehaviorSkinBase<FXVK, BehaviorBase<FXVK>> {
 
+    private static final int GAP = 6;
+
+    private List<List<Key>> board;
+    private int numCols;
+
+    private boolean capsDown = false;
+    private boolean shiftDown = false;
+
+    void clearShift() {
+        shiftDown = false;
+        updateKeys();
+    }
+
+    void pressShift() {
+        shiftDown = !shiftDown;
+        updateKeys();
+    }
+
+    void pressCaps() {
+        capsDown = !capsDown;
+        shiftDown = false;
+        updateKeys();
+    }
+
+    private void updateKeys() {
+        for (List<Key> row : board) {
+            for (Key key : row) {
+                key.update(capsDown, shiftDown);
+            }
+        }
+    }
+
+
     /**
      * If true, places the virtual keyboard(s) in a new root wrapper
      * on the scene instead of in a popup. The children of the wrapper
@@ -102,7 +158,6 @@
     private final static boolean USE_SECONDARY_POPUP = false;
 
     private static Region oldRoot;
-    private static RootWrapper newRoot;
     private static Timeline slideRootTimeline;
 
     private static Popup vkPopup;
@@ -114,12 +169,10 @@
 
     private static FXVK secondaryVK;
     private static Timeline secondaryVKDelay;
-    private static CharKey secondaryVKKey;
 
     private Node attachedNode;
 
     FXVK fxvk;
-    Control[][] keyRows;
 
     enum State { NORMAL, SHIFTED, SHIFT_LOCK, NUMERIC; };
 
@@ -127,8 +180,6 @@
 
     static final double VK_WIDTH = 640;
     static final double VK_HEIGHT = 243;
-//     static final double VK_WIDTH = 480;
-//     static final double VK_HEIGHT = 326;
     static final double VK_PORTRAIT_HEIGHT = 326;
     static final double VK_SLIDE_MILLIS = 250;
     static final double PREF_KEY_WIDTH = 56;
@@ -138,11 +189,6 @@
     double keyWidth = PREF_KEY_WIDTH;
     double keyHeight = PREF_KEY_HEIGHT;
 
-    private ShiftKey shiftKey;
-    private SymbolKey symbolKey;
-
-    private VBox vbox;
-
     // Proxy for read-only Window.yProperty() so we can animate.
     private static DoubleProperty winY = new SimpleDoubleProperty();
     static {
@@ -163,10 +209,23 @@
     });
 
 
+    @Override protected void handleControlPropertyChanged(String propertyReference) {
+        // With Java 8 (or is it 7?) I can do switch on strings instead
+        if (propertyReference == "type") {
+            // The type has changed, so we will need to rebuild the entire keyboard.
+            // This happens whenever the user switches from one keyboard layout to
+            // another, such as by pressing the "ABC" key on a numeric layout.
+            rebuild();
+        }
+    }
+
     public FXVKSkin(final FXVK fxvk) {
         super(fxvk, new BehaviorBase<FXVK>(fxvk));
         this.fxvk = fxvk;
 
+        registerChangeListener(fxvk.typeProperty(), "type");
+        rebuild();
+
         fxvk.setFocusTraversable(false);
 
         fxvk.attachedNodeProperty().addListener(new InvalidationListener() {
@@ -179,53 +238,20 @@
                     return;
                 }
 
-                if (inScene) {
-                    if (oldRoot != null) {
-                        translatePane(oldRoot, 0);
-                    }
-                }
+                if (attachedNode != null) {
+                    final Scene scene = attachedNode.getScene();
+                    //fxvk.getStyleClass().setAll("virtual-keyboard");
 
-                if (attachedNode != null) {
-                    if (keyRows == null) {
-                        createKeys();
-                    }
-
-                    final Scene scene = attachedNode.getScene();
                     fxvk.setVisible(true);
 
                     if (fxvk != secondaryVK) {
-                        if (secondaryVKDelay == null) {
-                            secondaryVKDelay = new Timeline();
-                        }
-                        KeyFrame kf = new KeyFrame(Duration.millis(500), new EventHandler<ActionEvent>() {
-                            @Override public void handle(ActionEvent event) {
-                                if (secondaryVKKey != null) {
-                                    showSecondaryVK(secondaryVKKey);
-                                }
-                            }
-                        });
-                        secondaryVKDelay.getKeyFrames().setAll(kf);
-
-                      if (inScene) {
-                            if (newRoot == null) {
-                                oldRoot = (Region)scene.getRoot();
-                                newRoot = new RootWrapper(oldRoot);
-                                scene.setRoot(newRoot);
-                            }
-
-                            newRoot.vkGroup.getChildren().setAll(fxvk);
-                            newRoot.updateTimelines();
-
-                            Bounds bounds = newRoot.vkGroup.getLayoutBounds();
-                            double y = newRoot.vkGroup.getLayoutY();
-                            if (bounds.getHeight() > 0 &&
-                                (y == 0 || y > scene.getHeight() - bounds.getHeight())) {
-                                slideOutTimeline.stop();
-                                slideInTimeline.playFromStart();
-                            }
-                      } else {
                         if (vkPopup == null) {
                             vkPopup = new Popup();
+                            vkPopup.setAutoFix(false);
+
+                            Scene popupScene = vkPopup.getScene();
+                            popupScene.getStylesheets().add(getClass().getResource("caspian/fxvk.css").toExternalForm());
+
 
                             // RT-21860 - This is causing
                             // IllegalStateException: The window must be focused when calling grabFocus()
@@ -239,11 +265,12 @@
                                 com.sun.javafx.Utils.getScreen(attachedNode).getBounds().getHeight();
                             double screenVisualHeight =
                                 com.sun.javafx.Utils.getScreen(attachedNode).getVisualBounds().getHeight();
+
                             screenVisualHeight = Math.min(screenHeight, screenVisualHeight + 4 /*??*/);
 
                             slideInTimeline.getKeyFrames().setAll(
                                 new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
-                                             new KeyValue(winY, screenVisualHeight - fxvk.prefHeight(-1),
+                                             new KeyValue(winY, screenHeight - VK_HEIGHT,
                                                           Interpolator.EASE_BOTH)));
                             slideOutTimeline.getKeyFrames().setAll(
                                 new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
@@ -257,6 +284,8 @@
                                 public void run() {
                                     Rectangle2D screenBounds =
                                         com.sun.javafx.Utils.getScreen(attachedNode).getBounds();
+
+                                        
                                     vkPopup.show(attachedNode,
                                                  (screenBounds.getWidth() - fxvk.prefWidth(-1)) / 2,
                                                  screenBounds.getHeight() - fxvk.prefHeight(-1));
@@ -277,25 +306,11 @@
                             winY.set(vkPopup.getY());
                             slideInTimeline.playFromStart();
                         }
-                      }
-
-                        if (inScene) {
-                            Platform.runLater(new Runnable() {
-                                public void run() {
-                                    if (attachedNode != null) {
-                                        double nodeBottom =
-                                            attachedNode.localToScene(attachedNode.getBoundsInLocal()).getMaxY() + 2;
-                                        if (fxvk.getLayoutY() > 0 && nodeBottom > fxvk.getLayoutY()) {
-                                            translatePane(oldRoot, fxvk.getLayoutY() - nodeBottom);
-                                        }
-                                    }
-                                }
-                            });
-                        }
 
                         if (oldNode == null || oldNode.getScene() != attachedNode.getScene()) {
-                            if (!inScene) { 
-                                fxvk.setPrefWidth(VK_WIDTH);
+                            if (!inScene) {
+                                double width = com.sun.javafx.Utils.getScreen(attachedNode).getBounds().getWidth();
+                                fxvk.setPrefWidth(width);
                             }
                             fxvk.setMinWidth(USE_PREF_SIZE);
                             fxvk.setMaxWidth(USE_PREF_SIZE);
@@ -305,6 +320,7 @@
                     }
                 } else {
                     if (fxvk != secondaryVK) {
+
                         slideInTimeline.stop();
                         if (!inScene) {
                             winY.set(vkPopup.getY());
@@ -322,704 +338,463 @@
         });
     }
 
-    private static void translatePane(Parent pane, double y) {
-        if (slideRootTimeline == null) {
-            slideRootTimeline = new Timeline();
-        } else {
-            slideRootTimeline.stop();
+    /**
+     * Replaces all children of this VirtualKeyboardSkin based on the keyboard
+     * type set on the VirtualKeyboard.
+     */
+    private void rebuild() {
+        String boardName;
+        FXVK.Type type = getSkinnable().getType();
+        switch (type) {
+            case NUMERIC:
+                boardName = "SymbolBoard";
+                break;
+            case TEXT:
+                boardName = "AsciiBoard";
+                break;
+            case EMAIL:
+                boardName = "EmailBoard";
+                break;
+            default:
+                throw new AssertionError("Unhandled Virtual Keyboard type");
         }
 
-        slideRootTimeline.getKeyFrames().setAll(
-            new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
-                         new KeyValue(pane.translateYProperty(), y, Interpolator.EASE_BOTH)));
-        slideRootTimeline.playFromStart();
+        board = loadBoard(boardName);
+        getChildren().clear();
+        numCols = 0;
+        for (List<Key> row : board) {
+            for (Key key : row) {
+                numCols = Math.max(numCols, key.col + key.colSpan);
+            }
+            getChildren().addAll(row);
+        }
     }
 
-    private void createKeys() {
-        getChildren().clear();
+    // This skin is designed such that it gives equal widths to all columns. So
+    // the pref width is just some hard-coded value (although I could have maybe
+    // done it based on the pref width of a text node with the right font).
+    @Override protected double computePrefWidth(double height) {
+        final Insets insets = getSkinnable().getInsets();
+        return insets.getLeft() + (56 * numCols) + insets.getRight();
+    }
 
-        if (fxvk.chars != null) {
-            // Secondary popup
-            int nKeys = fxvk.chars.length;
-            if (nKeys > 1) {
-                // Reorder to make letter keys appear before symbols
-                String[] array = new String[nKeys];
-                int ind = 0;
-                for (String str : fxvk.chars) {
-                    if (Character.isLetter(str.charAt(0))) {
-                        array[ind++] = str;
-                    }
+    // Pref height is just some value. This isn't overly important.
+    @Override protected double computePrefHeight(double width) {
+        final Insets insets = getSkinnable().getInsets();
+        return insets.getTop() + (80 * 5) + insets.getBottom();
+    }
+
+    // Lays the buttons comprising the current keyboard out. The first row is always
+    // a "short" row (about 2/3 in height of a normal row), followed by 4 normal rows.
+    @Override
+    protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {
+        // I have fixed width columns, all the same.
+        final double colWidth = ((contentWidth - ((numCols - 1) * GAP)) / numCols);
+        double rowHeight = ((contentHeight - (4 * GAP)) / 5); // 5 rows per keyboard
+        // The first row is 2/3 the height
+        double firstRowHeight = rowHeight * .666;
+        rowHeight += ((rowHeight * .333) / 4);
+
+        double rowY = contentY;
+        double h = firstRowHeight;
+        for (List<Key> row : board) {
+            for (Key key : row) {
+                double startX = contentX + (key.col * (colWidth + GAP));
+                double width = (key.colSpan * (colWidth + GAP)) - GAP;
+                key.resizeRelocate((int)(startX + .5),
+                                   (int)(rowY + .5),
+                                   width, h);
+            }
+            rowY += h + GAP;
+            h = rowHeight;
+        }
+    }
+
+
+    /**
+     * A Key on the virtual keyboard. This is simply a Region. Some information
+     * about the key relative to other keys on the layout is given by the col
+     * and colSpan fields.
+     */
+    private class Key extends Region {
+        int col = 0;
+        int colSpan = 1;
+        protected final Text text;
+        protected final Region icon;
+
+        protected Key() {
+            icon = new Region();
+            text = new Text();
+            text.setTextOrigin(VPos.TOP);
+            getChildren().setAll(text, icon);
+            getStyleClass().setAll("key");
+            addEventHandler(MouseEvent.ANY, new EventHandler<MouseEvent>() {
+                @Override public void handle(MouseEvent event) {
+                    if (event.getEventType() == MouseEvent.MOUSE_PRESSED)
+                        press();
+                    else if (event.getEventType() == MouseEvent.MOUSE_RELEASED)
+                        release();
                 }
-                for (String str : fxvk.chars) {
-                    if (!Character.isLetter(str.charAt(0))) {
-                        array[ind++] = str;
-                    }
-                }
-
-                int nRows = (int)Math.floor(Math.sqrt(Math.max(1, nKeys - 2)));
-                int nKeysPerRow = (int)Math.ceil(nKeys / (double)nRows);
-                keyRows = new Control[nRows][];
-                for (int i = 0; i < nRows; i++) {
-                    keyRows[i] =
-                        makeKeyRow((String[])Arrays.copyOfRange(array, i * nKeysPerRow,
-                                                                Math.min((i + 1) * nKeysPerRow, nKeys)));
-                }
-            } else {
-                keyRows = new Control[0][];
-            }
-        } else {
-            // Read keyboard layout from resource bundle
-            ArrayList<Control[]> rows = new ArrayList<Control[]>();
-            ArrayList<String> row = new ArrayList<String>();
-            ArrayList<Double> keyWidths = new ArrayList<Double>();
-            String typeString = FXVK.VK_TYPE_NAMES[fxvk.vkType];
-            int r = 0;
-            try {
-                String format = "FXVK."+typeString+".row%d.key%02d";
-                while (getBundle().containsKey(String.format(format, ++r, 1))) {
-                    int c = 0;
-                    String keyChars;
-                    while (getBundle().containsKey(String.format(format, r, ++c))) {
-                        row.add(getString(String.format(format, r, c)));
-                        Double w = -1.0;
-                        String widthLookup = String.format(format+".width", r, c);
-                        if (getBundle().containsKey(widthLookup)) {
-                            try {
-                                w = new Double(getString(widthLookup));
-                            } catch (NumberFormatException ex) {
-                                System.err.println(widthLookup+"="+getString(widthLookup));
-                                System.err.println(ex);
-                            }
-                        }
-                        keyWidths.add(w);
-                    }
-                    rows.add(makeKeyRow(row, keyWidths));
-                    row.clear();
-                    keyWidths.clear();
-                }
-            } catch (Exception ex) {
-                ex.printStackTrace();
-            }
-            keyRows = rows.toArray(new Control[rows.size()][]);
+            });
+        }
+        protected void press() { }
+        protected void release() {
+            clearShift();
         }
 
-        vbox = new VBox();
-        vbox.setId("vbox");
-        getChildren().add(vbox);
+        public void update(boolean capsDown, boolean shiftDown) { }
 
-        //double primaryFontSize = 16 * keyWidth / PREF_KEY_WIDTH;
-        //double secondaryFontSize = 8 * keyWidth / PREF_KEY_WIDTH;
+        @Override protected void layoutChildren() {
+            final Insets insets = getSkinnable().getInsets();
+            final double left = insets.getLeft();
+            final double top = insets.getTop();
+            final double width = getWidth() - left - insets.getRight();
+            final double height = getHeight() - top - insets.getBottom();
 
-        for (Control[] row : keyRows) {
-            HBox hbox = new HBox();
-            hbox.setId("hbox");
-            // Primary keyboard has centered keys, secondary has left aligned keys.
-            hbox.setAlignment((fxvk.chars != null) ? Pos.CENTER_LEFT : Pos.CENTER);
-            vbox.getChildren().add(hbox);
-            for (Control c : row) {
-                if (enableCaching) {
-                    c.setCache(true);
-                }
-                hbox.getChildren().add(c);
-                HBox.setHgrow(c, Priority.ALWAYS);
-                if (c instanceof Key) {
-                    Key key = (Key)c;
-                    int textLen = key.getText().length();
-                    if (textLen == 1 || !key.getClass().getSimpleName().equals("CharKey")) {
-                        //key.setStyle("-fx-font-size: "+primaryFontSize+"px;");
-                    } else {
-                        //key.setStyle("-fx-font-size: "+(primaryFontSize* Math.min(1.0, 3.0/textLen))+"px;");
-                        key.setGraphicTextGap(key.getGraphicTextGap() + 2*textLen);
-                    }
-                    if (key.getGraphic() instanceof Label) {
-                        //((Label)key.getGraphic()).setStyle("-fx-font-size: "+secondaryFontSize+"px;");
-                    }
-                }
+            text.setVisible(icon.getBackground() == null);
+            double contentPrefWidth = text.prefWidth(-1);
+            double contentPrefHeight = text.prefHeight(-1);
+            text.resizeRelocate(
+                    (int) (left + ((width - contentPrefWidth) / 2) + .5),
+                    (int) (top + ((height - contentPrefHeight) / 2) + .5),
+                    (int) contentPrefWidth,
+                    (int) contentPrefHeight);
+
+            icon.resizeRelocate(left-8, top-8, width+16, height+16);
+        }
+
+    }
+
+    /**
+     * Any key on the keyboard which will send a KeyEvent to the client. This
+     * class just maintains the state and logic for firing an event, using the
+     * "chars" and "code" as the values sent in the event. A subclass must set
+     * these appropriately.
+     */
+    private class TextInputKey extends Key {
+        protected String chars = "";
+
+        protected void press() {
+            Node target = fxvk.getAttachedNode();
+            if (target instanceof EventTarget) {
+                target.fireEvent(event(KeyEvent.KEY_PRESSED));
+            }
+        }
+        protected void release() {
+            Node target = fxvk.getAttachedNode();
+            if (target instanceof EventTarget) {
+                target.fireEvent(event(KeyEvent.KEY_TYPED));
+                target.fireEvent(event(KeyEvent.KEY_RELEASED));
+            }
+            super.release();
+        }
+
+        protected KeyEvent event(EventType<KeyEvent> type) {
+            try {
+                Field fld = FXRobotHelper.class.getDeclaredField("inputAccessor");
+                fld.setAccessible(true);
+                FXRobotInputAccessor inputAccessor = (FXRobotInputAccessor)fld.get(null);
+
+                return inputAccessor.createKeyEvent(type, KeyCode.UNDEFINED, chars, "",
+                                      shiftDown, false, false, false);
+            } catch (Exception e) {
+                System.err.println(e);
+            }
+
+            return null;
+        }
+    }
+
+    /**
+     * A key used for letters a-z, and handles responding to the shift & caps lock
+     * keys, such that lowercase or uppercase letters are entered.
+     */
+    private class LetterKey extends TextInputKey {
+        private LetterKey(String letter) {
+            this.chars = letter;
+            text.setText(this.chars);
+        }
+
+        public void update(boolean capsDown, boolean shiftDown) {
+            final boolean capital = capsDown || shiftDown;
+            if (capital) {
+                this.chars = this.chars.toUpperCase();
+                text.setText(this.chars);
+            } else {
+                this.chars = this.chars.toLowerCase();
+                text.setText(this.chars);
             }
         }
     }
 
+    /**
+     * A key which has a number or symbol on it, such as the "1" key which can also
+     * enter the ! character when shift is pressed. Also used for purely symbolic
+     * keys such as [.
+     */
+    private class SymbolKey extends TextInputKey {
+        private final String letterChars;
+        private final String altChars;
 
-    private Control[] makeKeyRow(String... obj) {
-        return makeKeyRow(Arrays.asList(obj), null);
-    }
-
-    private Control[] makeKeyRow(List<String> keyList, List<Double> widths) {
-        Control[] keyRow = new Control[keyList.size()];
-        for (int i = 0; i < keyRow.length; i++) {
-            String str = keyList.get(i);
-            Double w = 1.0;
-            if (widths != null && widths.get(i) > 0) {
-                w = widths.get(i);
-            }
-            if ("BACKSPACE".equals(str)) {
-                CommandKey backspaceKey = new CommandKey("\u232b", BACK_SPACE, w);
-                backspaceKey.setId("backspace-key");
-// Workaround until we can load -fx-graphic from caspian.css
-setIcon(backspaceKey, "fxvk-backspace-button.png");
-                keyRow[i] = backspaceKey;
-            } else if ("ENTER".equals(str)) {
-                CommandKey enterKey = new CommandKey("\u21b5", ENTER, w);
-                enterKey.setId("enter-key");
-// Workaround until we can load -fx-graphic from caspian.css
-setIcon(enterKey, "fxvk-enter-button.png");
-                keyRow[i] = enterKey;
-            } else if ("SHIFT".equals(str)) {
-                shiftKey = new ShiftKey(w);
-                shiftKey.setId("shift-key");
-// Workaround until we can load -fx-graphic from caspian.css
-setIcon(shiftKey, "fxvk-shift-button.png");
-                keyRow[i] = shiftKey;
-            } else if ("SYM".equals(str)) {
-                symbolKey = new SymbolKey("!#123 ABC", w);
-                symbolKey.setId("symbol-key");
-                keyRow[i] = symbolKey;
-            } else {
-                keyRow[i] = new CharKey((String)keyList.get(i), w);
-            }
-        }
-        return keyRow;
-    }
-
-    private void setState(State state) {
-        this.state = state;
-
-        shiftKey.setPressState(state == State.SHIFTED || state == State.SHIFT_LOCK);
-        shiftKey.setDisable(state == State.NUMERIC);
-        shiftKey.setId((state == State.SHIFT_LOCK) ? "capslock-key" : "shift-key");
-
-// Workaround until we can load -fx-graphic from caspian.css
-switch (state) {
-    case NUMERIC: setIcon(shiftKey, null); break;
-    case SHIFT_LOCK: setIcon(shiftKey, "fxvk-capslock-button.png"); break;
-    default: setIcon(shiftKey, "fxvk-shift-button.png");
-}
-        if (fxvk == secondaryVK) {
-            ((FXVKSkin)primaryVK.getSkin()).updateLabels();
-        } else {
-            updateLabels();
-        }
-    }
-
-// Workaround until we can load -fx-graphic from caspian.css
-private void setIcon(Key key, String fileName) {
-    if (fileName != null) {
-        String url = getClass().getResource("caspian/"+fileName).toExternalForm();
-        key.setGraphic(new javafx.scene.image.ImageView(url));
-    } else {
-        key.setGraphic(null);
-    }
-}
-
-    private void updateLabels() {
-        for (Control[] row : keyRows) {
-            for (Control button : row) {
-                if (button instanceof CharKey) {
-                    CharKey key = (CharKey)button;
-                    String txt = key.chars[0];
-                    String alt = (key.chars.length > 1) ? key.chars[1] : "";
-                    if (key.chars.length > 1 && state == State.NUMERIC) {
-                        txt = key.chars[1];
-                        if (key.chars.length > 2 && !Character.isLetter(key.chars[2].charAt(0))) {
-                            alt = key.chars[2];
-                        } else {
-                            alt = "";
-                        }
-                    } else if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
-                        txt = txt.toUpperCase();
-                    }
-                    key.setText(txt);
-                    if (key.graphic != null) {
-                        key.graphic.setText(alt);
-                    }
-                }
-            }
-        }
-        if (symbolKey != null) {
-            symbolKey.setText(symbolKey.chars[(state == State.NUMERIC) ? 1 : 0]);
-        }
-    }
-
-    private void fireKeyEvent(Node target, EventType<? extends KeyEvent> eventType,
-                           KeyCode keyCode, String keyChar, String keyText,
-                           boolean shiftDown, boolean controlDown,
-                           boolean altDown, boolean metaDown) {
-        try {
-            Field fld = FXRobotHelper.class.getDeclaredField("inputAccessor");
-            fld.setAccessible(true);
-            FXRobotInputAccessor inputAccessor = (FXRobotInputAccessor)fld.get(null);
-            target.fireEvent(inputAccessor.createKeyEvent(eventType,
-                                                          keyCode, keyChar, keyText,
-                                                          shiftDown, controlDown,
-                                                          altDown, metaDown));
-        } catch (Exception e) {
-            System.err.println(e);
-        }
-    }
-
-
-
-    private class Key extends Button {
-        private double keyWidth;
-
-        private Key(String text, double keyWidth) {
-            super(text);
-
-            this.keyWidth = keyWidth;
-
-            getStyleClass().add("key");
-            setFocusTraversable(false);
-
-            setMinHeight(USE_PREF_SIZE);
-            setPrefHeight(keyHeight);
+        private SymbolKey(String letter, String alt) {
+            this.chars = letter;
+            this.letterChars = this.chars;
+            this.altChars = alt;
+            text.setText(this.letterChars);
         }
 
-    }
-
-    private class CharKey extends Key {
-        String str;
-        String[] chars;
-        Label graphic;
-
-        EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>() {
-            @Override public void handle(ActionEvent e) {
-                if (fxvk != secondaryVK && secondaryPopup != null && secondaryPopup.isShowing()) {
-                    return;
-                }
-
-                Node target = fxvk.getAttachedNode();
-                if (target instanceof EventTarget) {
-                    String txt = getText();
-                    if (txt.length() > 1 && txt.contains(" ")) {
-                        //txt = txt.split(" ")[shift ? 1 : 0];
-                        txt = txt.split(" ")[0];
-                    }
-                    for (int i = 0; i < txt.length(); i++) {
-                        String str = txt.substring(i, i+1);
-                        fireKeyEvent(target, KeyEvent.KEY_TYPED, null, str, str,
-                                  state == State.SHIFTED, false, false, false);
-                    }
-
-                    if (state == State.SHIFTED) {
-                        setState(State.NORMAL);
-                    }
-                }
-
-                if (fxvk == secondaryVK) {
-                    showSecondaryVK(null);
-                }
-            }
-        };
-
-        CharKey(String str, double width) {
-            super(null, width);
-
-            this.str = str;
-            setOnAction(actionHandler);
-
-            if (fxvk != secondaryVK) {
-                setOnMousePressed(new EventHandler<MouseEvent>() {
-                    @Override public void handle(MouseEvent event) {
-                        showSecondaryVK(null);
-                        secondaryVKKey = CharKey.this;
-                        secondaryVKDelay.playFromStart();
-                    }
-                });
-
-                setOnMouseReleased(new EventHandler<MouseEvent>() {
-                    @Override public void handle(MouseEvent event) {
-                        secondaryVKDelay.stop();
-                    }
-                });
-            }
-
-            if (str.length() == 1) {
-                chars = new String[] { str };
+        public void update(boolean capsDown, boolean shiftDown) {
+            if (shiftDown && altChars != null) {
+                this.chars = altChars;
+                text.setText(this.chars);
             } else {
-                chars = str.split(" ");
-                for (int i = 0; i < chars.length; i++) {
-                    chars[i] = FXVKCharEntities.get(chars[i]);
-                }
-            }
-            setContentDisplay(ContentDisplay.TOP);
-            setGraphicTextGap(-16);
-            setText(chars[0]);
-            setId(chars[0]);
-            if (getText().length() > 1) {
-                getStyleClass().add("multi-char-key");
-            }
-
-            graphic = new Label((chars.length > 1) ? chars[1] : " ");
-            graphic.setPrefWidth(keyWidth - 6);
-            graphic.setMinWidth(USE_PREF_SIZE);
-            graphic.setPrefHeight(keyHeight / 2 - 8);
-            setGraphic(graphic);
-        }
-    }
-
-    private class CommandKey extends Key {
-        KeyCode code;
-
-        EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>() {
-            @Override public void handle(ActionEvent e) {
-                showSecondaryVK(null);
-                Node target = fxvk.getAttachedNode();
-                if (target instanceof EventTarget) {
-                    String txt = getText();
-                    fireKeyEvent(target, KeyEvent.KEY_PRESSED, code, null, null,
-                              false, false, false, false);
-                    if (state == State.SHIFTED) {
-                        setState(State.NORMAL);
-                    }
-                }
-            }
-        };
-
-        CommandKey(String label, KeyCode code, double width) {
-            super(label, width);
-            this.code = code;
-            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
-            getStyleClass().add("special-key");
-            setOnAction(actionHandler);
-        }
-    }
-
-    private class ShiftKey extends Key {
-        EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>() {
-            long lastTime = -1L;
-
-            @Override public void handle(ActionEvent e) {
-                showSecondaryVK(null);
-                long time = System.currentTimeMillis();
-                if (lastTime > 0L && time - lastTime < 600L) {
-                    setState(State.SHIFT_LOCK);
-                } else if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
-                    setState(State.NORMAL);
-                } else {
-                    setState(State.SHIFTED);
-                }
-                lastTime = time;
-            }
-        };
-
-        ShiftKey(double width) {
-            super("\u21d1", width);
-            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
-            getStyleClass().add("special-key");
-            setFocusTraversable(false);
-            setOnAction(actionHandler);
-        }
-
-        private void setPressState(boolean pressed) {
-            setPressed(pressed);
-        }
-    }
-
-    private class SymbolKey extends Key {
-        String str;
-        String[] chars;
-
-        EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>() {
-            @Override public void handle(ActionEvent e) {
-                setState((state == State.NUMERIC) ? State.NORMAL : State.NUMERIC);
-                showSecondaryVK(null);
-            }
-        };
-
-        SymbolKey(String str, double width) {
-            super(null, width);
-            this.str = str;
-            getStyleClass().add("special-key");
-
-            if (str.length() == 1) {
-                chars = new String[] { str };
-            } else {
-                chars = str.split(" ");
-            }
-            setText(chars[0]);
-
-            setOnAction(actionHandler);
-        }
-    }
-
-    @Override public void layoutChildren(final double x, final double y,
-            final double w, final double h) {
-        double kw, kh;
-        Insets insets = getInsets();
-        if (vbox == null) {
-            createKeys();
-        }
-        HBox hbox = (HBox)vbox.getChildren().get(0);
-        double hGap = hbox.getSpacing();
-
-        double maxWidth = 0;
-        int maxNKeys = 0;
-        for (Node vnode : vbox.getChildren()) {
-            hbox = (HBox)vnode;
-            int nKeys = 0;
-            double totalWidth = 0;
-            for (Node hnode : hbox.getChildren()) {
-                Key key = (Key)hnode;
-                nKeys++;
-                totalWidth += key.keyWidth;
-            }
-
-            maxNKeys = Math.max(maxNKeys, nKeys);
-            maxWidth = Math.max(maxWidth, totalWidth);
-        }
-
-
-        if (fxvk == secondaryVK) {
-            kw = PREF_PORTRAIT_KEY_WIDTH;
-            kh = ((FXVKSkin)primaryVK.getSkin()).keyHeight;
-        } else {
-            kw = (hbox.getWidth() - (maxNKeys - 1) * hGap) / Math.max(maxWidth, 10.0);
-            kh = (getHeight() - insets.getTop() - insets.getBottom() - (keyRows.length - 1) * vbox.getSpacing()) / keyRows.length;
-        }
-
-        if (keyWidth != kw || keyHeight != kh) {
-            keyWidth = kw;
-            keyHeight = kh;
-            createKeys();
-        }
-
-        super.layoutChildren(x, y, w, h);
-
-        for (Node vnode : vbox.getChildren()) {
-            hbox = (HBox)vnode;
-            int nKeys = 0;
-            int nSpecialKeys = 0;
-            double totalWidth = 0;
-            for (Node hnode : hbox.getChildren()) {
-                Key key = (Key)hnode;
-                nKeys++;
-                if (key.keyWidth > 1.0) {
-                    nSpecialKeys++;
-                }
-                totalWidth += key.keyWidth;
-            }
-
-            double slop = hbox.getWidth() - (nKeys - 1) * hGap - totalWidth * kw;
-            for (Node hnode : hbox.getChildren()) {
-                Key key = (Key)hnode;
-                // Add slop if not landscape numerical keyboard. (Better if specified in props).
-                if ((fxvk.vkType != 1 || fxvk.getStyleClass().contains("fxvk-portrait")) &&
-                    slop > 0 && key.keyWidth > 1.0) {
-
-                    key.setPrefWidth(key.keyWidth * keyWidth + slop / nSpecialKeys);
-                } else {
-                    key.setPrefWidth(key.keyWidth * keyWidth);
-                }
+                this.chars = letterChars;
+                text.setText(this.chars);
             }
         }
     }
 
-    private void showSecondaryVK(final CharKey key) {
-        if (key != null) {
-            primaryVK = fxvk;
-            final Node textInput = primaryVK.getAttachedNode();
+    /**
+     * One of several TextInputKeys which have super powers, such as "Tab" and
+     * "Return" and "Backspace". These keys still send events to the client,
+     * but may also have additional state related functionality on the keyboard
+     * such as the "Shift" key.
+     */
+    private class SuperKey extends TextInputKey {
+        private SuperKey(String letter, String code) {
+            this.chars = code;
+            text.setText(letter);
+            getStyleClass().add("special");
+        }
+    }
 
-            if (secondaryVK == null) {
-                secondaryVK = new FXVK();
-                secondaryVK.getStyleClass().addAll("fxvk-secondary", "fxvk-portrait");
-                secondaryVK.setSkin(new FXVKSkin(secondaryVK));
-                secondaryPopup = new Popup();
-                secondaryPopup.setAutoHide(true);
-                secondaryPopup.getContent().add(secondaryVK);
-                // TODO: call to impl_processCSS is probably not needed here
-                secondaryVK.impl_processCSS(false);
-            }
+    /**
+     * Some keys actually do need to use KeyCode for pressed / released events,
+     * and BackSpace is one of them.
+     */
+    private class KeyCodeKey extends SuperKey {
+        private KeyCode code;
 
-            if (state == State.NUMERIC) {
-                ArrayList<String> symbols = new ArrayList<String>();
-                for (String ch : key.chars) {
-                    if (!Character.isLetter(ch.charAt(0))) {
-                        symbols.add(ch);
-                    }
+        private KeyCodeKey(String letter, String c, KeyCode code) {
+            super(letter, c);
+            this.code = code;
+        }
+
+        protected KeyEvent event(EventType<KeyEvent> type) {
+            if (type == KeyEvent.KEY_PRESSED || type == KeyEvent.KEY_RELEASED) {
+                try {
+                    Field fld = FXRobotHelper.class.getDeclaredField("inputAccessor");
+                    fld.setAccessible(true);
+                    FXRobotInputAccessor inputAccessor = (FXRobotInputAccessor)fld.get(null);
+
+                    return inputAccessor.createKeyEvent(type, code, chars, chars,
+                                          shiftDown, false, false, false);
+                } catch (Exception e) {
+                    System.err.println(e);
                 }
-                secondaryVK.chars = symbols.toArray(new String[symbols.size()]);
+                return null;
             } else {
-                ArrayList<String> secondaryChars = new ArrayList<String>();
-                // Add all letters
-                for (String ch : key.chars) {
-                    if (Character.isLetter(ch.charAt(0))) {
-                        if (state == State.SHIFTED || state == State.SHIFT_LOCK) {
-                            secondaryChars.add(ch.toUpperCase());
-                        } else {
-                            secondaryChars.add(ch);
-                        }
-                    }
-                }
-                // Add secondary character if not a letter
-                if (key.chars.length > 1 &&
-                    !Character.isLetter(key.chars[1].charAt(0))) {
-                    secondaryChars.add(key.chars[1]);
-                }
-                secondaryVK.chars = secondaryChars.toArray(new String[secondaryChars.size()]);
-            }
-
-            if (secondaryVK.chars.length > 1) {
-                if (secondaryVK.getSkin() != null) {
-                    ((FXVKSkin)secondaryVK.getSkin()).createKeys();
-                }
-
-                secondaryVK.setAttachedNode(textInput);
-                FXVKSkin primarySkin = (FXVKSkin)primaryVK.getSkin();
-                FXVKSkin secondarySkin = (FXVKSkin)secondaryVK.getSkin();
-                Insets insets = secondarySkin.getInsets();
-                int nKeys = secondaryVK.chars.length;
-                int nRows = (int)Math.floor(Math.sqrt(Math.max(1, nKeys - 2)));
-                int nKeysPerRow = (int)Math.ceil(nKeys / (double)nRows);
-                HBox hbox = (HBox)vbox.getChildren().get(0);
-                final double w = insets.getLeft() + insets.getRight() +
-                                 nKeysPerRow * PREF_PORTRAIT_KEY_WIDTH + (nKeysPerRow - 1) * hbox.getSpacing();
-                final double h = insets.getTop() + insets.getBottom() +
-                                 nRows * primarySkin.keyHeight + (nRows-1) * vbox.getSpacing();
-                secondaryVK.setPrefWidth(w);
-                secondaryVK.setMinWidth(USE_PREF_SIZE);
-                secondaryVK.setPrefHeight(h);
-                secondaryVK.setMinHeight(USE_PREF_SIZE);
-                Platform.runLater(new Runnable() {
-                    public void run() {
-                        // Position popup on screen
-                        Point2D nodePoint =
-                            com.sun.javafx.Utils.pointRelativeTo(key, w, h, HPos.CENTER, VPos.TOP,
-                                                                 5, -3, true);
-                        double x = nodePoint.getX();
-                        double y = nodePoint.getY();
-                        Scene scene = key.getScene();
-                        x = Math.min(x, scene.getWindow().getX() + scene.getWidth() - w);
-                        secondaryPopup.show(key.getScene().getWindow(), x, y);
-                    }
-                });
-            }
-        } else {
-            if (secondaryVK != null) {
-                secondaryVK.setAttachedNode(null);
-                secondaryPopup.hide();
+                return super.event(type);
             }
         }
     }
 
+    /**
+     * These keys only manipulate the state of the keyboard and never
+     * send key events to the client. For example, "Hide", "Caps Lock",
+     * etc are all KeyboardStateKeys.
+     */
+    private class KeyboardStateKey extends Key {
+        private KeyboardStateKey(String t) {
+            text.setText(t);
+            getStyleClass().add("special");
+        }
+    }
 
-    static class RootWrapper extends Pane {
-        Group vkGroup;
-        double dragStartY;
+    /**
+     * A special type of KeyboardStateKey used for switching from the current
+     * virtual keyboard layout to a new one.
+     */
+    private final class SwitchBoardKey extends KeyboardStateKey {
+        private FXVK.Type type;
 
-        RootWrapper(final Region oldRoot) {
-            getChildren().add(oldRoot);
-            getChildren().add(vkGroup = new Group());
-            prefWidthProperty().bind(oldRoot.prefWidthProperty());
-            prefHeightProperty().bind(oldRoot.prefHeightProperty());
-
-
-            addEventHandler(MOUSE_PRESSED, new EventHandler<MouseEvent>() {
-                @Override public void handle(MouseEvent e) {
-                    dragStartY = e.getY() - oldRoot.getTranslateY();
-                    e.consume();
-                }
-            });
-
-            addEventHandler(MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
-                @Override public void handle(MouseEvent e) {
-                    if (vkGroup.isVisible()) {
-                        double y =
-                            Math.min(0, Math.max(e.getY() - dragStartY,
-                                                 vkGroup.getLayoutY() - oldRoot.getHeight()));
-                        oldRoot.setTranslateY(y);
-                    }
-                    e.consume();
-                }
-            });
+        private SwitchBoardKey(String displayName, FXVK.Type type) {
+            super(displayName);
+            this.type = type;
         }
 
-        @Override protected double computePrefWidth(double height) {
-            return oldRoot.prefWidth(height);
+        @Override protected void release() {
+            super.release();
+            getSkinnable().setType(type);
         }
+    }
 
-        @Override protected double computePrefHeight(double width) {
-            return oldRoot.prefHeight(width);
-        }
+    private List<List<Key>> loadBoard(String boardName) {
+        try {
+            List<List<Key>> rows = new ArrayList<List<Key>>(5);
+            List<Key> keys = new ArrayList<Key>(20);
 
-        private void updateTimelines() {
-            double rootHeight = getHeight();
-            double vkHeight = vkGroup.getLayoutBounds().getHeight();
+            InputStream asciiBoardFile = FXVKSkin.class.getResourceAsStream(boardName + ".txt");
+            BufferedReader reader = new BufferedReader(new InputStreamReader(asciiBoardFile));
+            String line;
+            // A pointer to the current column. This will be incremented for every string
+            // of text, or space.
+            int c = 0;
+            // The col at which the key will be placed
+            int col = 0;
+            // The number of columns that the key will span
+            int colSpan = 1;
+            // Whether the "chars" is an identifier, like $shift or $SymbolBoard, etc.
+            boolean identifier = false;
+            // The textual content of the Key
+            String chars = "";
+            String alt = null;
 
-            slideInTimeline.getKeyFrames().setAll(
-                new KeyFrame(Duration.ZERO,
-                             new KeyValue(vkGroup.visibleProperty(), true),
-                             new KeyValue(vkGroup.layoutYProperty(), rootHeight)),
-                new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
-                             new KeyValue(vkGroup.visibleProperty(), true),
-                             new KeyValue(vkGroup.layoutYProperty(),
-                                          Math.floor(rootHeight - vkHeight),
-                                          Interpolator.EASE_BOTH)));
+            while ((line = reader.readLine()) != null) {
+                // A single line represents a single row of buttons
+                for (int i=0; i<line.length(); i++) {
+                    char ch = line.charAt(i);
 
-            slideOutTimeline.getKeyFrames().setAll(
-                new KeyFrame(Duration.ZERO,
-                             new KeyValue(vkGroup.layoutYProperty(),
-                                          Math.floor(rootHeight - vkHeight))),
-                new KeyFrame(Duration.millis(VK_SLIDE_MILLIS),
-                             new KeyValue(vkGroup.layoutYProperty(),
-                                          rootHeight,
-                                          Interpolator.EASE_BOTH),
-                             new KeyValue(vkGroup.visibleProperty(), false)));
-        }
+                    // Process the char
+                    if (ch == ' ') {
+                        c++;
+                    } else if (ch == '[') {
+                        // Start of a key
+                        col = c;
+                        chars = "";
+                        alt = null;
+                        identifier = false;
+                    } else if (ch == ']') {
+                        // End of a key
+                        colSpan = c - col;
+                        Key key;
+                        if (identifier) {
+                            if ("$shift".equals(chars)) {
+                                key = new KeyboardStateKey("shift") {
+                                    @Override protected void release() {
+                                        pressShift();
+                                    }
+                                };
+                                key.getStyleClass().add("shift");
+                            } else if ("$backspace".equals(chars)) {
+                                key = new KeyCodeKey("backspace", "\b", KeyCode.BACK_SPACE);
+                                key.getStyleClass().add("backspace");
 
-        @Override public void layoutChildren() {
-            if (getScene() != null && getScene().getWindow() != null &&
-                getWidth() > getScene().getWindow().getWidth()) {
-                // Too soon to layout keyboard
-                return;
-            }
-
-            final double rootWidth = getWidth();
-            final double rootHeight = getHeight();
-            final double vkHeight = (rootWidth > rootHeight) ? VK_HEIGHT : VK_PORTRAIT_HEIGHT;
-
-            boolean attached = false;
-            boolean resized = false;
-            for (Node child : vkGroup.getChildren()) {
-                if (child instanceof FXVK && !child.getStyleClass().contains("fxvk-secondary")) {
-                    final FXVK fxvk = (FXVK)child;
-                    attached = (attached || fxvk.getAttachedNode() != null);
-                    if (rootWidth > rootHeight) {
-                        fxvk.getStyleClass().remove("fxvk-portrait");
-                    } else {
-                        if (!fxvk.getStyleClass().contains("fxvk-portrait")) {
-                            fxvk.getStyleClass().add("fxvk-portrait");
-                        }
-                    }
-
-                    if (fxvk.getWidth() != rootWidth || fxvk.getHeight() != vkHeight) {
-                        slideInTimeline.stop();
-                        slideOutTimeline.stop();
-                        fxvk.setPrefWidth(rootWidth);
-                        fxvk.setPrefHeight(vkHeight);
-                        vkGroup.setLayoutY(attached ? (rootHeight - vkHeight) : rootHeight);
-                        resized = true;
-                    }
-
-                    if (vkGroup.isVisible()) {
-                        Platform.runLater(new Runnable() {
-                            public void run() {
-                                Node attachedNode = fxvk.getAttachedNode();
-                                if (attachedNode != null) {
-                                    double oldRootY = oldRoot.getTranslateY();
-                                    double nodeBottom =
-                                        attachedNode.localToScene(attachedNode.getBoundsInLocal()).getMaxY() + 2;
-                                    if (nodeBottom > rootHeight - vkHeight) {
-                                        translatePane(oldRoot, rootHeight - vkHeight - nodeBottom + oldRootY);
+                            } else if ("$enter".equals(chars)) {
+                                key = new KeyCodeKey("enter", "\n", KeyCode.ENTER);
+                                key.getStyleClass().add("enter");
+                            } else if ("$tab".equals(chars)) {
+                                key = new KeyCodeKey("tab", "\t", KeyCode.TAB);
+                            } else if ("$caps".equals(chars)) {
+                                key = new KeyboardStateKey("caps lock") {
+                                    @Override protected void release() {
+                                        pressCaps();
                                     }
+                                };
+                                key.getStyleClass().add("caps");
+                            } else if ("$space".equals(chars)) {
+                                key = new LetterKey(" ");
+                            } else if ("$clear".equals(chars)) {
+                                key = new SuperKey("clear", "");
+                            } else if ("$.org".equals(chars)) {
+                                key = new SuperKey(".org", ".org");
+                            } else if ("$.com".equals(chars)) {
+                                key = new SuperKey(".com", ".com");
+                            } else if ("$.net".equals(chars)) {
+                                key = new SuperKey(".net", ".net");
+                            } else if ("$oracle.com".equals(chars)) {
+                                key = new SuperKey("oracle.com", "oracle.com");
+                            } else if ("$gmail.com".equals(chars)) {
+                                key = new SuperKey("gmail.com", "gmail.com");
+                            } else if ("$hide".equals(chars)) {
+                                key = new KeyboardStateKey("Hide") {
+                                    @Override protected void release() {
+                                        slideInTimeline.stop();
+                                        if (!inScene) {
+                                            winY.set(vkPopup.getY());
+                                        }
+                                        slideOutTimeline.playFromStart();
+                                    }
+                                };
+                                key.getStyleClass().add("hide");
+                            } else if ("$undo".equals(chars)) {
+                                key = new SuperKey("undo", "");
+                            } else if ("$redo".equals(chars)) {
+                                key = new SuperKey("redo", "");
+                            } else {
+                                // The name is the name of a board to show
+                                String name = chars.substring(1);
+                                if (name.equals("AsciiBoard")) {
+                                    key = new SwitchBoardKey("ABC", FXVK.Type.TEXT);
+                                } else if (name.equals("EmailBoard")) {
+                                    key = new SwitchBoardKey("ABC.com", FXVK.Type.EMAIL);
+                                } else if (name.equals("SymbolBoard")) {
+                                    key = new SwitchBoardKey("#+=", FXVK.Type.NUMERIC);
+                                } else {
+                                    throw new AssertionError("Unknown keyboard '" + name + "'");
                                 }
                             }
-                        });
+                        } else {
+                            boolean isLetter = false;
+                            try {
+                                KeyCode code = KeyCode.getKeyCode(chars.toUpperCase());
+                                isLetter = code == null ? false : code.isLetterKey();
+                            } catch (Exception e) { }
+                            key = isLetter ? new LetterKey(chars) : new SymbolKey(chars, alt);
+                        }
+                        key.col = col;
+                        key.colSpan = colSpan;
+                        if (rows.isEmpty()) {
+                            key.getStyleClass().add("short");
+                        }
+                        for (String sc : key.getStyleClass()) {
+                            key.text.getStyleClass().add(sc + "-text");
+                            key.icon.getStyleClass().add(sc + "-icon");
+                        }
+                        keys.add(key);
+                    } else {
+                        // Normal textual characters. Read all the way up to the
+                        // next ] or space
+                        for (int j=i; j<line.length(); j++) {
+                            char c2 = line.charAt(j);
+                            boolean e = false;
+                            if (c2 == '\\') {
+                                j++;
+                                i++;
+                                e = true;
+                                c2 = line.charAt(j);
+                            }
+
+                            if (c2 == '$' && !e) {
+                                identifier = true;
+                            }
+
+                            if (c2 == '|' && !e) {
+                                chars = line.substring(i, j);
+                                i = j + 1;
+                            } else if ((c2 == ']' || c2 == ' ') && !e) {
+                                if (chars.isEmpty()) {
+                                    chars = line.substring(i, j);
+                                } else {
+                                    alt = line.substring(i, j);
+                                }
+                                i = j-1;
+                                break;
+                            }
+                        }
+                        c++;
                     }
                 }
+
+                c = 0;
+                col = 0;
+                rows.add(keys);
+                keys = new ArrayList<Key>(20);
             }
-            if (vkGroup.getLayoutY() == 0) {
-                vkGroup.setLayoutY(rootHeight);
-            }
+            return rows;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Collections.emptyList();
         }
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Wed Jan 16 11:42:20 2013 -0800
@@ -103,7 +103,7 @@
     final InvalidationListener graphicPropertyChangedListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
             invalidText = true;
-            requestLayout();
+            getSkinnable().requestLayout();
         }
     };
 
@@ -200,7 +200,7 @@
             // it will already have fit all available height and a change to vpos
             // has no effect. Or it is too short (i.e. it all fits) and we don't
             // have to worry about truncation. So just call request layout.
-            requestLayout();
+            getSkinnable().requestLayout();
         } else if ("MNEMONIC_PARSING".equals(p)) {
             textMetricsChanged();
         } else if ("TEXT".equals(p)) {
@@ -228,35 +228,35 @@
     }
 
     protected double topPadding() {
-        return snapSpace(getInsets().getTop());
+        return snapSize(getSkinnable().getInsets().getTop());
     }
 
     protected double topLabelPadding() {
-        return snapSpace(getSkinnable().getLabelPadding().getTop());
+        return snapSize(getSkinnable().getLabelPadding().getTop());
     }
 
     protected double bottomPadding() {
-        return snapSpace(getInsets().getBottom());
+        return snapSize(getSkinnable().getInsets().getBottom());
     }
 
     protected double bottomLabelPadding() {
-        return snapSpace(getSkinnable().getLabelPadding().getBottom());
+        return snapSize(getSkinnable().getLabelPadding().getBottom());
     }
 
     protected double leftPadding() {
-        return snapSpace(getInsets().getLeft());
+        return snapSize(getSkinnable().getInsets().getLeft());
     }
 
     protected double leftLabelPadding() {
-        return snapSpace(getSkinnable().getLabelPadding().getLeft());
+        return snapSize(getSkinnable().getLabelPadding().getLeft());
     }
 
     protected double rightPadding() {
-        return snapSpace(getInsets().getRight());
+        return snapSize(getSkinnable().getInsets().getRight());
     }
 
     protected double rightLabelPadding() {
-        return snapSpace(getSkinnable().getLabelPadding().getRight());
+        return snapSize(getSkinnable().getLabelPadding().getRight());
     }
 
 
@@ -267,7 +267,7 @@
      */
     private void textMetricsChanged() {
         invalidText = true;
-        requestLayout();
+        getSkinnable().requestLayout();
     }
 
     /*
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -140,7 +140,7 @@
             flow.recreateCells();
         } else if ("PARENT".equals(p)) {
             if (getSkinnable().getParent() != null && getSkinnable().isVisible()) {
-                requestLayout();
+                getSkinnable().requestLayout();
             }
         } else if ("FOCUS_TRAVERSABLE".equals(p)) {
             flow.setFocusTraversable(getSkinnable().isFocusTraversable());
@@ -151,7 +151,7 @@
     private final ListChangeListener listViewItemsListener = new ListChangeListener() {
         @Override public void onChanged(Change c) {
             itemCountDirty = true;
-            requestLayout();
+            getSkinnable().requestLayout();
         }
     };
     
@@ -170,7 +170,7 @@
         }
 
         itemCountDirty = true;
-        requestLayout();
+        getSkinnable().requestLayout();
     }
     
     private int itemCount = -1;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuBarSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -510,10 +510,10 @@
                         currentMenuBarStage = null;
                         setSystemMenu(stage);
 
-                        requestLayout();
+                        getSkinnable().requestLayout();
                         javafx.application.Platform.runLater(new Runnable() {
                             public void run() {
-                                requestLayout();
+                                getSkinnable().requestLayout();
                             }
                         });
                         return;
@@ -724,7 +724,7 @@
             });
             updateActionListeners(menu, true);
         }
-        requestLayout();
+        getSkinnable().requestLayout();
     }
     
     /*
@@ -912,11 +912,11 @@
 
     // Return empty insets when "container" is empty, which happens
     // when using the system menu bar.
-    @Override public Insets getInsets() {
-        if (container.getChildren().size() == 0) {
-            return new Insets(0, 0, 0, 0);
+    private Insets getInsets() {
+        if (container.getChildren().isEmpty()) {
+            return Insets.EMPTY;
         } else {
-            return super.getInsets();
+            return getSkinnable().getInsets();
         }
     }
 
@@ -931,19 +931,23 @@
     }
 
     @Override protected double computeMinWidth(double height) {
-        return container.minWidth(height) + getInsets().getLeft() + getInsets().getRight();
+        Insets insets = getInsets();
+        return container.minWidth(height) + insets.getLeft() + insets.getRight();
     }
 
     @Override protected double computePrefWidth(double height) {
-        return container.prefWidth(height) + getInsets().getLeft() + getInsets().getRight();
+        Insets insets = getInsets();
+        return container.prefWidth(height) + insets.getLeft() + insets.getRight();
     }
 
     @Override protected double computeMinHeight(double width) {
-        return container.minHeight(width) + getInsets().getTop() + getInsets().getBottom();
+        Insets insets = getInsets();
+        return container.minHeight(width) + insets.getTop() + insets.getBottom();
     }
 
     @Override protected double computePrefHeight(double width) {
-        return container.prefHeight(width) + getInsets().getTop() + getInsets().getBottom();
+        Insets insets = getInsets();
+        return container.prefHeight(width) + insets.getTop() + insets.getBottom();
     }
 
     // grow horizontally, but not vertically
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuButtonSkinBase.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/MenuButtonSkinBase.java	Wed Jan 16 11:42:20 2013 -0800
@@ -113,7 +113,7 @@
         getChildren().clear();
         getChildren().addAll(label, arrowButton);
 
-        requestLayout();
+        getSkinnable().requestLayout();
         
         control.getItems().addListener(new ListChangeListener() {
             @Override public void onChanged(Change c) {
@@ -221,7 +221,7 @@
 
         } else if ("MNEMONIC_PARSING".equals(p)) {
             label.setMnemonicParsing(getSkinnable().isMnemonicParsing());
-            requestLayout();
+            getSkinnable().requestLayout();
         }
     }
 
@@ -232,7 +232,7 @@
      **************************************************************************/
 
     @Override protected double computePrefWidth(double height) {
-        final Insets padding = getInsets();
+        final Insets padding = getSkinnable().getInsets();
         return padding.getLeft()
                 + label.prefWidth(height)
                 + snapSize(arrowButton.prefWidth(height))
@@ -240,7 +240,7 @@
     }
 
     @Override protected double computePrefHeight(double width) {
-        final Insets padding = getInsets();
+        final Insets padding = getSkinnable().getInsets();
         return padding.getTop()
                 + Math.max(label.prefHeight(width), snapSize(arrowButton.prefHeight(-1)))
                 + padding.getBottom();
@@ -279,7 +279,7 @@
                                     Event.fireEvent(menuitem, new Event(MenuItem.MENU_VALIDATION_EVENT));
                                 }
                                 Menu target = (Menu)menuitem.getParentMenu();
-                                if(target.getOnMenuValidation() != null) {
+                                if(target!= null && target.getOnMenuValidation() != null) {
                                     Event.fireEvent(target, new Event(MenuItem.MENU_VALIDATION_EVENT));
                                 }
                                 if (!menuitem.isDisable()) menuitem.fire();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PaginationSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -166,6 +166,9 @@
     private int direction;
 
     private void initializeSwipeAndTouchHandlers() {
+        final Pagination control = getSkinnable();
+        final Insets controlPadding = control.getInsets();
+                    
         getSkinnable().setOnTouchPressed(new EventHandler<TouchEvent>() {
             @Override public void handle(TouchEvent e) {
                 if (touchEventId == -1) {
@@ -199,7 +202,7 @@
                 }
 
                 if (touchThresholdBroken) {
-                    double width = getWidth() - (getInsets().getLeft() + getInsets().getRight());
+                    double width = control.getWidth() - (controlPadding.getLeft() + controlPadding.getRight());
                     double currentPaneX;
                     double nextPaneX;
 
@@ -281,7 +284,7 @@
                     final double velocity = quick ? (double)drag / time : touchVelocity; // pixels/ms
                     // calculate distance we would travel at this speed for 500ms of travel
                     final double distance = (velocity * 500);
-                    final double width = getWidth() - (getInsets().getLeft() + getInsets().getRight());
+                    final double width = control.getWidth() - (controlPadding.getLeft() + controlPadding.getRight());
 
                     // The swipe distance travelled.
                     final double threshold = Math.abs(distance/width);
@@ -534,7 +537,7 @@
             arrowsVisible = new StyleableBooleanProperty(DEFAULT_ARROW_VISIBLE) {
                 @Override
                 protected void invalidated() {
-                    requestLayout();
+                    getSkinnable().requestLayout();
                 }
 
                 @Override
@@ -564,7 +567,7 @@
             pageInformationVisible = new StyleableBooleanProperty(DEFAULT_PAGE_INFORMATION_VISIBLE) {
                 @Override
                 protected void invalidated() {
-                    requestLayout();
+                    getSkinnable().requestLayout();
                 }
 
                 @Override
@@ -594,7 +597,7 @@
             pageInformationAlignment = new StyleableObjectProperty<Side>(Side.BOTTOM) {
                 @Override
                 protected void invalidated() {
-                    requestLayout();
+                    getSkinnable().requestLayout();
                 }
 
                 @Override
@@ -624,7 +627,7 @@
             tooltipVisible = new StyleableBooleanProperty(DEFAULT_TOOLTIP_VISIBLE) {
                 @Override
                 protected void invalidated() {
-                    requestLayout();
+                    getSkinnable().requestLayout();
                 }
 
                 @Override
@@ -671,46 +674,51 @@
             navigation.initializePageIndicators();
             navigation.updatePageIndicators();
         } else if ("WIDTH".equals(p)) {
-            clipRect.setWidth(getWidth());
+            clipRect.setWidth(getSkinnable().getWidth());
         } else if ("HEIGHT".equals(p)) {
-            clipRect.setHeight(getHeight());
+            clipRect.setHeight(getSkinnable().getHeight());
         }
         
-        requestLayout();
+        getSkinnable().requestLayout();
     }
 
     @Override protected double computeMinWidth(double height) {
-        double left = snapSpace(getInsets().getLeft());
-        double right = snapSpace(getInsets().getRight());
+        Insets padding = getSkinnable().getInsets();
+        double left = snapSpace(padding.getLeft());
+        double right = snapSpace(padding.getRight());
         double navigationWidth = navigation.isVisible() ? snapSize(navigation.minWidth(height)) : 0;
         return left + Math.max(currentStackPane.minWidth(height), navigationWidth) + right;
     }
 
     @Override protected double computeMinHeight(double width) {
-        double top = snapSpace(getInsets().getTop());
-        double bottom = snapSpace(getInsets().getBottom());
+        Insets padding = getSkinnable().getInsets();
+        double top = snapSpace(padding.getTop());
+        double bottom = snapSpace(padding.getBottom());
         double navigationHeight = navigation.isVisible() ? snapSize(navigation.minHeight(width)) : 0;
         return top + currentStackPane.minHeight(width) + navigationHeight + bottom;
     }
 
     @Override protected double computePrefWidth(double height) {
-        double left = snapSpace(getInsets().getLeft());
-        double right = snapSpace(getInsets().getRight());
+        Insets padding = getSkinnable().getInsets();
+        double left = snapSpace(padding.getLeft());
+        double right = snapSpace(padding.getRight());
         double navigationWidth = navigation.isVisible() ? snapSize(navigation.prefWidth(height)) : 0;
         return left + Math.max(currentStackPane.prefWidth(height), navigationWidth) + right;
     }
 
     @Override protected double computePrefHeight(double width) {
-        double top = snapSpace(getInsets().getTop());
-        double bottom = snapSpace(getInsets().getBottom());
+        Insets padding = getSkinnable().getInsets();
+        double top = snapSpace(padding.getTop());
+        double bottom = snapSpace(padding.getBottom());
         double navigationHeight = navigation.isVisible() ? snapSize(navigation.prefHeight(width)) : 0;
         return top + currentStackPane.prefHeight(width) + navigationHeight + bottom;
     }
 
     @Override protected void layoutChildren(final double x, final double y,
             final double w, final double h) {
-        double left = snapSpace(getInsets().getLeft());
-        double top = snapSpace(getInsets().getTop());
+        Insets padding = getSkinnable().getInsets();
+        double left = snapSpace(padding.getLeft());
+        double top = snapSpace(padding.getTop());
         double navigationHeight = navigation.isVisible() ? snapSize(navigation.prefHeight(-1)) : 0;
         double stackPaneHeight = snapSize(h - navigationHeight);
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/PopupControlSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.javafx.scene.control.skin;
-
-import javafx.event.Event;
-import javafx.event.EventHandler;
-import javafx.scene.Node;
-import javafx.scene.Parent;
-import javafx.scene.Scene;
-import javafx.scene.control.PopupControl;
-import javafx.scene.control.Skin;
-import javafx.stage.Popup;
-import javafx.stage.Window;
-
-/**
- * PoppedUp Controls are different from other controls in that some, or all, of
- * their visuals are hosted in a Popup. Because the Popup is not itself a member
- * of the scenegraph, we need to manage sending certain messages such as
- * processing of CSS and layout between the "base" or "anchor" scenegraph and
- * the popup scenegraph. This class manages these details.
- * <p>
- * Subclasses of PopupControlSkin may want to provide a Region which represents
- * the Control in the base scenegraph, and must provide a Region which
- * represents this control in the popup. These regions will be mapped in
- * as appropriate by this class.
- * <p>
- * The popup associated with this skin is defined as a protected variable. By
- * default a new Popup instance is created for each PopupControlSkin instance,
- * though subclasses may reuse popups (c.f. TooltipSkin).
- * <p>
- * The popup is shown or hidden based on the {@code showing} variable. It is
- * the responsibility of the subclass to make sure this variable is updated
- * as appropriate based on state on the Control or on other state.
- * <p>
- * When {@code showing} changes to true, the showPopup() function will be
- * called. The implementation of that function relies on the {@code screenX} and
- * {@code screenY} variables for positioning of the popup. Subclasses should
- * ensure that these variables are setup correctly.
- * <p>
- * When {@code showing) changes to false, then the hidePopup() function will
- * be called.
- */
-public class PopupControlSkin<C extends PopupControl> implements Skin<C>{
-
-    /**
-    * This var keeps a count of visible Popup controls other than the tooltip
-    * There should only be at most one visible popup control at any given time
-    */
-    private static int visiblePopupControlCount=0;
-
-    /**
-     * The visual representation for the Control in the "base" scenegraph. This
-     * may be null if there is no base representation (such as with a Tooltip).
-     */
-    protected Node content;
-
-    /**
-     * The visual representation for the Control in the popup. This must be
-     * specified.
-     */
-    protected Node popupContent;
-
-    /**
-     * Indicates whether the popup should be showing or hidden. It is the
-     * responsibility of subclasses to bind this showing variable to the
-     * appropriate var on the control
-     */
-    protected boolean showing = false;
-
-    protected void setShowing(boolean value) {
-       boolean oldValue = showing;
-       showing = value;
-       showHidePopup(oldValue);
-    }
-
-    protected void showHidePopup(boolean oldValue) {
-        if (showing) {
-            visiblePopupControlCount++;
-            showPopup();
-        } else if (oldValue) {
-            visiblePopupControlCount--;
-            hidePopup();
-        }
-    }
-
-    /**
-     * The popup menu which will be used. The subclass generally doesn't need
-     * to access this variable, except for Tooltip, which does so to make sure
-     * that the shared popup is used.
-     */
-    protected Popup popup;
-
-    /**
-     * The screenX position at which to show the popup.
-     */
-    protected double screenX;
-
-    /**
-     * The screenY position at which to show the popup.
-     */
-    protected double screenY;
-
-    protected void onAutoHide() {
-        // do nothing subclasses can override. 
-    }
-    protected void showPopup() {
-        if (popup == null) {
-            popup = new Popup();
-            popup.setAutoHide(true);
-            popup.setAutoFix(true);
-            popup.setOnAutoHide(new EventHandler<Event>() {
-                @Override public void handle(Event evt) {
-                    onAutoHide();
-                }
-            });
-        }
-
-        // Call show before setting the content. In order for popupContent
-        // to be styled, the popupContent must be in a Scene and the Scene
-        // must be in a Window.
-        final Scene scene = content == null ? null : content.getScene();
-        final Window win = scene == null ? null : scene.getWindow();
-        // TODO: do we need this test?
-        if (win == null) return;
-        popup.show(content, screenX, screenY);
-
-        // Adding content here triggers Popup.invokeDimensions()
-        popup.getContent().setAll(popupContent);
-
-        if (popupContent instanceof Parent) {
-            ((Parent) popupContent).requestLayout();
-        }
-//        getSkinnable().autosize();
-        popupContent.autosize();
-    }
-
-    protected void hidePopup() {
-        if (popup != null) {
-            popup.hide();
-            // null the popup to reclaim memory
-            popup.getContent().clear();
-            popup = null;
-        }
-    }
-
-    /* ************************************************************************
-     *                    Skin Implementation                                 *
-     **************************************************************************/
-
-    @Override public Node getNode() {
-        // subclasses should override
-        return null;
-    }
-
-    @Override public void dispose() {
-       // do nothing subclasses should override
-    }
-
-    @Override public C getSkinnable() {
-        // subclasses should override
-        return null;
-    }
-}
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ProgressBarSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ProgressBarSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -51,6 +51,7 @@
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.value.WritableValue;
+import javafx.geometry.Insets;
 import javafx.scene.control.SkinBase;
 
 
@@ -251,7 +252,7 @@
                         if (getSkinnable().impl_isTreeVisible()) {
                             indeterminateTimeline.play();
                         }
-                        requestLayout();
+                        getSkinnable().requestLayout();
                     }
                 }
             }
@@ -259,7 +260,8 @@
         control.sceneProperty().addListener(sceneListener);
 
 
-        barWidth = ((int) (control.getWidth() - getInsets().getLeft() - getInsets().getRight()) * 2 * Math.min(1, Math.max(0, control.getProgress()))) / 2.0F;
+        final Insets padding = getSkinnable().getInsets();
+        barWidth = ((int) (control.getWidth() - padding.getLeft() - padding.getRight()) * 2 * Math.min(1, Math.max(0, control.getProgress()))) / 2.0F;
 
         InvalidationListener listener = new InvalidationListener() {
             @Override public void invalidated(Observable valueModel) {
@@ -276,7 +278,7 @@
         getSkinnable().setClip(clipRectangle);
 
         initialize();
-        requestLayout();
+        getSkinnable().requestLayout();
     }
 
     private void initialize() {
@@ -325,7 +327,9 @@
     private void createIndeterminateTimeline() {
         if (indeterminateTimeline != null) indeterminateTimeline.stop();
 
-        final double w = getWidth() - (getInsets().getLeft() + getInsets().getRight());
+        ProgressBar control = getSkinnable();
+        Insets padding = control.getInsets();
+        final double w = control.getWidth() - (padding.getLeft() + padding.getRight());
         final double startX = getIndeterminateBarEscape()? -getIndeterminateBarLength() : 0;
         final double endX = getIndeterminateBarEscape()? w : w - getIndeterminateBarLength();
 
@@ -361,14 +365,15 @@
 
     private void updateProgress() {
         ProgressBar control = getSkinnable();
-        barWidth = ((int) (control.getWidth() - getInsets().getLeft() - getInsets().getRight()) * 2 * Math.min(1, Math.max(0, control.getProgress()))) / 2.0F;
-        requestLayout();
+        Insets padding = control.getInsets();
+        barWidth = ((int) (control.getWidth() - padding.getLeft() - padding.getRight()) * 2 * Math.min(1, Math.max(0, control.getProgress()))) / 2.0F;
+        getSkinnable().requestLayout();
     }
 
     @Override
     public double getBaselineOffset() {
         double height = getSkinnable().getHeight();        
-        return getInsets().getTop() + height;
+        return getSkinnable().getInsets().getTop() + height;
     }
     
     @Override public void dispose() {
@@ -390,11 +395,14 @@
      **************************************************************************/
 
     @Override protected double computePrefWidth(double height) {
-        return Math.max(100, getInsets().getLeft() + bar.prefWidth(getWidth()) + getInsets().getRight());
+        ProgressBar control = getSkinnable();
+        Insets padding = control.getInsets();
+        return Math.max(100, padding.getLeft() + bar.prefWidth(control.getWidth()) + padding.getRight());
     }
 
     @Override protected double computePrefHeight(double width) {
-        return getInsets().getTop() + bar.prefHeight(width) + getInsets().getBottom();
+        Insets padding = getSkinnable().getInsets();
+        return padding.getTop() + bar.prefHeight(width) + padding.getBottom();
     }
 
     @Override protected double computeMaxWidth(double height) {
@@ -407,18 +415,21 @@
 
     @Override protected void layoutChildren(final double x, final double y,
             final double w, final double h) {
-        boolean isIndeterminate = getSkinnable().isIndeterminate();
+        
+        final ProgressBar control = getSkinnable();
+        final Insets padding = control.getInsets();
+        boolean isIndeterminate = control.isIndeterminate();
 
         // Prevent the indeterminate bar from drawing outside the skin
         if (clipRectangle != null) {
-            clipRectangle.setWidth(getWidth());
-            clipRectangle.setHeight(getHeight());
+            clipRectangle.setWidth(control.getWidth());
+            clipRectangle.setHeight(control.getHeight());
         }
 
         track.resizeRelocate(x, y, w, h);
 
         bar.resizeRelocate(x, y, isIndeterminate? getIndeterminateBarLength() : barWidth,
-                   getHeight() - (getInsets().getTop() + getInsets().getBottom()));
+                   control.getHeight() - (padding.getTop() + padding.getBottom()));
 
         // things should be invisible only when well below minimum length
         track.setVisible(true);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ProgressIndicatorSkin.java	Thu Jan 10 10:01:15 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ProgressIndicatorSkin.java	Wed Jan 16 11:42:20 2013 -0800
@@ -24,18 +24,28 @@
  */
 package com.sun.javafx.scene.control.skin;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
 import javafx.animation.Timeline;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.value.WritableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.NodeOrientation;
 import javafx.geometry.VPos;
-import javafx.scene.Group;
+import javafx.scene.Node;
 import javafx.scene.control.ProgressIndicator;
+import javafx.scene.control.SkinBase;
+import javafx.scene.layout.Pane;
 import javafx.scene.layout.Region;
 import javafx.scene.layout.StackPane;
 import javafx.scene.paint.Color;
@@ -43,26 +53,20 @@
 import javafx.scene.shape.Arc;
 import javafx.scene.shape.ArcType;
 import javafx.scene.shape.Circle;
-import javafx.scene.shape.SVGPath;
-import javafx.scene.text.Font;
 import javafx.scene.text.Text;
-import javafx.scene.transform.Rotate;
 import javafx.scene.transform.Scale;
 import javafx.util.Duration;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.sun.javafx.Utils;
+import com.sun.javafx.css.CssMetaData;
+import com.sun.javafx.css.Origin;
+import com.sun.javafx.css.StyleableBooleanProperty;
+import com.sun.javafx.css.StyleableIntegerProperty;
 import com.sun.javafx.css.StyleableObjectProperty;
-import com.sun.javafx.css.CssMetaData;
+import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.PaintConverter;
+import com.sun.javafx.css.converters.SizeConverter;
 import com.sun.javafx.scene.control.behavior.ProgressIndicatorBehavior;
 import com.sun.javafx.scene.control.skin.resources.ControlResources;
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.value.WritableValue;
-import javafx.scene.control.SkinBase;
+import javafx.geometry.Insets;
 
 public class ProgressIndicatorSkin extends BehaviorSkinBase<ProgressIndicator, ProgressIndicatorBehavior<ProgressIndicator>> {
 
@@ -80,13 +84,6 @@
         doneText.getStyleClass().add("text");
     }
 
-
-    private static final ObservableList<String> paths;
-    static {
-        paths = FXCollections.<String>observableArrayList();
-        paths.addAll("M 18.19152 4.2642355 L 15.734064 5.984965 L 15.734064 5.984965 C  16.55803 7.1617074 17.0 8.563462 17.0 10.0 L 20.0 10.0 C  20.0 7.9478035 19.368612 5.9452963 18.19152 4.2642355 Z", "M 11.736482 0.15192246 L 11.215537 3.1063457 L 11.215537 3.1063457 C  12.63025 3.3557978 13.933962 4.034467 14.949747 5.0502524 L 10.0 10.0 L 17.071068 2.9289322 C  15.619946 1.4778103 13.757501 0.5082826 11.736482 0.15192246 Z", "M 10.0 0.0 C  7.9478035 0.0 5.9452963 0.6313881 4.2642355 1.8084795 L 5.984965 4.265936 L 5.984965 4.265936 C  7.1617074 3.4419718 8.563462 3.0 10.0 3.0 L 10.0 0.0 Z", "M 2.9289322 2.9289322 C  1.4778103 4.380054 0.5082826 6.2424994 0.15192246 8.263518 L 3.1063457 8.784463 L 3.1063457 8.784463 C  3.3557978 7.3697495 4.034467 6.0660377 5.0502524 5.0502524 L 5.0502524 5.0502524 L 2.9289322 2.9289322 Z", "M 0.0 10.0 C  0.0 12.0521965 0.6313881 14.054704 1.8084795 15.7357645 L 10.0 10.0 L 4.265936 14.015035 C  3.4419718 12.838292 3.0 11.436538 3.0 10.0 Z", "M 10.0 10.0 L 8.784463 16.893654 C  7.3697495 16.644201 6.0660377 15.965533 5.050253 14.949747 L 5.0502524 14.949747 L 2.9289322 17.071068 C  4.380054 18.52219 6.2424994 19.491718 8.263518 19.848078 L 10.0 10.0 Z", "M 10.0 10.0 L 14.015035 15.734064 C  12.838292 16.55803 11.436538 17.0 10.0 17.0 L 10.0 20.0 C  12.0521965 20.0 14.054704 19.368612 15.7357645 18.19152 L 10.0 10.0 Z", "M 10.0 10.0 L 16.893654 11.215537 C  16.644201 12.63025 15.965533 13.933962 14.949747 14.949747 L 17.071068 17.071068 C  18.52219 15.619946 19.491718 13.757501 19.848078 11.736482 L 10.0 10.0 Z");
-    }
-
     private IndeterminateSpinner spinner;
     private DeterminateIndicator determinateIndicator;
     private boolean timelineNulled = false;
@@ -111,7 +108,7 @@
             @Override public void invalidated(Observable valueModel) {
                 if (getSkinnable().isIndeterminate() && timelineNulled && spinner == null) {
                     timelineNulled = false;
-                    spinner = new IndeterminateSpinner(getSkinnable(), ProgressIndicatorSkin.this);
+                    spinner = new IndeterminateSpinner(getSkinnable(), ProgressIndicatorSkin.this, spinEnabled.get(), progressColor.get());
                     getChildren().add(spinner);
                 }
                 
@@ -144,12 +141,12 @@
                 else {
                     if (getSkinnable().getScene() != null && getSkinnable().isIndeterminate()) {
                         timelineNulled = false;
-                        spinner = new IndeterminateSpinner(getSkinnable(), ProgressIndicatorSkin.this);
+                        spinner = new IndeterminateSpinner(getSkinnable(), ProgressIndicatorSkin.this, spinEnabled.get(), progressColor.get());
                         getChildren().add(spinner);
                         if (getSkinnable().impl_isTreeVisible()) {
                             spinner.indeterminateTimeline.play();
                         }
-                        requestLayout();
+                        getSkinnable().requestLayout();
                     }
                 }
             }
@@ -157,7 +154,7 @@
         control.sceneProperty().addListener(sceneListener);
 
         initialize();
-        requestLayout();
+        getSkinnable().requestLayout();
     }
 
     private void initialize() {
@@ -167,7 +164,7 @@
             // clean up determinateIndicator
             determinateIndicator = null;
             // create spinner
-            spinner = new IndeterminateSpinner(control, this);
+            spinner = new IndeterminateSpinner(control, this, spinEnabled.get(), progressColor.get());
             getChildren().clear();
             getChildren().add(spinner);
             if (getSkinnable().impl_isTreeVisible()) {
@@ -180,7 +177,7 @@
                 spinner = null;
             }
             // create determinateIndicator
-            determinateIndicator = new com.sun.javafx.scene.control.skin.ProgressIndicatorSkin.DeterminateIndicator(control, this);
+            determinateIndicator = new com.sun.javafx.scene.control.skin.ProgressIndicatorSkin.DeterminateIndicator(control, this, progressColor.get());
             getChildren().clear();
             getChildren().add(determinateIndicator);
         }
@@ -188,7 +185,6 @@
     
     @Override public void dispose() {
         super.dispose();
-        
         if (spinner != null) {
             spinner.indeterminateTimeline.stop();
             spinner = null;
@@ -213,7 +209,6 @@
      **************************************************************************/
 
     static class DeterminateIndicator extends Region {
-        private Font font;
         private double textGap = 2.0F;
 
         // only update progress text on whole percentages
@@ -227,10 +222,9 @@
         private StackPane indicator;
         private StackPane progress;
         private StackPane tick;
-        Arc arcShape;
-        Arc arcProgress;
+        private Arc arcShape;
 
-        public DeterminateIndicator(ProgressIndicator control, ProgressIndicatorSkin s) {
+        public DeterminateIndicator(ProgressIndicator control, ProgressIndicatorSkin s, Paint fillOverride) {
             this.control = control;
             this.skin = s;
             
@@ -261,24 +255,14 @@
             arcShape.setType(ArcType.ROUND);
             arcShape.setStartAngle(90.0F);
 
-            arcProgress = new Arc();
-            arcProgress.setType(ArcType.ROUND);
-            arcPr