changeset 5949:6dfa55f03e62

Sync up SceneBuilder changes
author Yves Joan <yves.joan@oracle.com>
date Tue, 10 Dec 2013 08:36:28 +0100
parents 9bbe05e11f94
children 02682ee93895
files apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/CssPanelDelegate.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/DocumentWindowController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderApp.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderTest.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/about/AboutWindowController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/i18n/SceneBuilderApp.properties apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanel.css apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanel.fxml apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBar.fxml apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBarController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessageBarController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessagePanelController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/Preferences.fxml apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesRecordDocument.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesRecordGlobal.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesWindowController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preview/BackgroundColor.fxml apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preview/BackgroundColorDialogController.java apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/selectionbar/SelectionBarController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorPlatform.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/DragController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/AbstractDragSource.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/DocumentDragSource.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/ExternalDragSource.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/LibraryDragSource.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/target/ContainerXYDropTarget.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/target/GridPaneDropTarget.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/i18n/SceneBuilderKit.properties apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DeleteObjectSelectionJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DuplicateSelectionJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/PasteJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/GridSnapshot.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/GridSnapshotItem.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/InsertColumnConstraintsJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/InsertColumnJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/MoveCellContentJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/MoveColumnContentJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/v2/CompositeJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/AbstractDecoration.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanel.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/HudWindow.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/GridPaneDriver.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneMosaic.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractCurveHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractNodeHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TabHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TableColumnHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TreeTableColumnHandles.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/NodePring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TabPring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TableColumnPring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TreeTableColumnPring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/resizer/ImageViewResizer.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/rudder/ResizeRudder.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/HBoxTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/NodeTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TabTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TableColumnTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TreeTableColumnTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/VBoxTring.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/ResizeGesture.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/SelectAndMoveGesture.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/MovingGuideRenderer.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/ResizingGuideRenderer.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/mode/EditModeController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/BoundsUtils.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/LineEquation.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/Picker.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/RegionRectangle.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssContentMaker.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanel.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/AbstractHierarchyPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/treeview/HierarchyTreeCell.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AnchorPaneConstraintsEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AutoSuggestEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BooleanEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BoundedDoubleEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/ControllerClassEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/CursorEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/EnumEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/GenericEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/I18nStringEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/ImageEditor.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/ImageEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/InsetsEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/PropertyEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/RotateEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/StringAutoSuggestEditor.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/StyleClassEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/StyleEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/StylesheetEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/popupeditors/PaintPopupEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/popupeditors/PopupEditor.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/library/ImportDialog.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/library/ImportDialog.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/library/LibraryPanel.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/library/LibraryPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/util/AbstractFxmlPanelController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/search/Search.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/selection/ObjectSelectionGroup.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/selection/Selection.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMObject.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/glossary/ControllerClass.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/library/BuiltinLibrary.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/library/util/JarExplorer.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/Metadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/property/value/ColumnConstraintsPropertyMetadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/property/value/DoublePropertyMetadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/property/value/EnumerationPropertyMetadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/property/value/RowConstraintsPropertyMetadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/metadata/property/value/paint/PaintPropertyMetadata.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/CssInternal.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/GridBounds.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/PaintPicker.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/PaintPicker.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/PaintPicker.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/PaintPickerController.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/colorpicker/ColorPicker.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/colorpicker/ColorPicker.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/colorpicker/ColorPicker.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPicker.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPicker.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPicker.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPickerStop.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPickerStop.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/gradientpicker/GradientPickerStop.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/images/chequers.png apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/images/stop-indicator.png apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/rotator/RotatorControl.css apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/rotator/RotatorControl.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/rotator/RotatorControl.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/rotator/rotate-handle.png apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/slider/SliderControl.fxml apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/control/paintpicker/slider/SliderControl.java
diffstat 143 files changed, 8101 insertions(+), 1490 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/CssPanelDelegate.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app;
+
+import com.oracle.javafx.scenebuilder.kit.editor.panel.css.CssPanelController;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelController;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelController.SectionId;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
+import javafx.application.Platform;
+
+/**
+ * Implements the interface with the css panel.
+ */
+public class CssPanelDelegate extends CssPanelController.Delegate {
+
+    private final InspectorPanelController inspectorController;
+    private final DocumentWindowController documentWindowController;
+
+    public CssPanelDelegate(InspectorPanelController inspectorController, DocumentWindowController documentWindowController) {
+        this.inspectorController = inspectorController;
+        this.documentWindowController = documentWindowController;
+    }
+
+    @Override
+    public void revealInspectorEditor(ValuePropertyMetadata propMeta) {
+        if (inspectorController == null || documentWindowController == null
+                || propMeta == null) {
+            return;
+        }
+
+        // Show the inspector if it is hidden
+        if (!documentWindowController.isRightPanelVisible()) {
+            documentWindowController.performControlAction(DocumentWindowController.DocumentControlAction.TOGGLE_RIGHT_PANEL);
+        }
+        // Expand the inspector section
+        String inspectorSection = propMeta.getInspectorPath().getSectionTag();
+        if (inspectorSection.equalsIgnoreCase("properties")) { //NOI18N
+            inspectorController.setExpandedSection(SectionId.PROPERTIES);
+        } else if (inspectorSection.equalsIgnoreCase("layout")) {//NOI18N
+            inspectorController.setExpandedSection(SectionId.LAYOUT);
+        } else if (inspectorSection.equalsIgnoreCase("code")) {//NOI18N
+            inspectorController.setExpandedSection(SectionId.CODE);
+        }
+
+        // Need to delay the focus to the editor, so that the section is actually expanded first.
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                // Need to delay in frame +2 since the TitledPane is built in frame +1 when node selected.
+                // And positioning the scrollBar while the content is building does not work.
+                Platform.runLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        inspectorController.setFocusToEditor(propMeta.getName());
+                    }
+                });
+            }
+        });
+    }
+
+}
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/DocumentWindowController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/DocumentWindowController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,6 +35,7 @@
 import com.oracle.javafx.scenebuilder.app.info.InfoPanelController;
 import com.oracle.javafx.scenebuilder.app.menubar.MenuBarController;
 import com.oracle.javafx.scenebuilder.app.message.MessageBarController;
+import com.oracle.javafx.scenebuilder.app.preview.BackgroundColorDialogController;
 import com.oracle.javafx.scenebuilder.app.preview.PreviewWindowController;
 import com.oracle.javafx.scenebuilder.app.selectionbar.SelectionBarController;
 import com.oracle.javafx.scenebuilder.app.template.FxmlTemplates;
@@ -45,6 +46,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.panel.hierarchy.AbstractHierarchyPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.hierarchy.HierarchyPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelController;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelController.SectionId;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.library.LibraryPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.util.AbstractFxmlWindowController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.util.dialog.AbstractModalDialog.ButtonID;
@@ -78,6 +80,7 @@
 import javafx.scene.layout.StackPane;
 import javafx.scene.layout.VBox;
 import javafx.stage.FileChooser;
+import javafx.stage.Window;
 import javafx.stage.WindowEvent;
 
 /**
@@ -104,12 +107,14 @@
         TOGGLE_RIGHT_PANEL,
         TOGGLE_GUIDES_VISIBILITY,
         SHOW_PREVIEW_WINDOW,
+        CHOOSE_BACKGROUND_COLOR,
         EDIT_INCLUDED_FILE,
         REVEAL_INCLUDED_FILE,
         ADD_SCENE_STYLE_SHEET,
         SET_RESOURCE,
         REMOVE_RESOURCE,
-        REVEAL_RESOURCE
+        REVEAL_RESOURCE,
+        HELP
     }
     
     public enum ActionStatus {
@@ -120,10 +125,11 @@
     private final EditorController editorController = new EditorController();
     private final MenuBarController menuBarController = new MenuBarController(this);
     private final ContentPanelController contentPanelController = new ContentPanelController(editorController);
-    private final CssPanelController cssPanelController = new CssPanelController(editorController);
     private final AbstractHierarchyPanelController hierarchyPanelController = new HierarchyPanelController(editorController);
     private final InfoPanelController infoPanelController = new InfoPanelController(editorController);
     private final InspectorPanelController inspectorPanelController = new InspectorPanelController(editorController);
+    private final CssPanelDelegate cssPanelDelegate = new CssPanelDelegate(inspectorPanelController, this);
+    private final CssPanelController cssPanelController = new CssPanelController(editorController, cssPanelDelegate);
     private final LibraryPanelController libraryPanelController = new LibraryPanelController(editorController);
     private final SelectionBarController selectionBarController = new SelectionBarController(editorController);
     private final MessageBarController messageBarController = new MessageBarController(editorController);
@@ -276,6 +282,10 @@
                 result = true;
                 break;
                 
+            case CHOOSE_BACKGROUND_COLOR:
+                result = false;
+                break;
+                
             case SAVE_FILE:
                 result = editorController.canUndo();
                 break;
@@ -300,7 +310,7 @@
             case GOTO_PROPERTIES:
             case GOTO_LAYOUT:
             case GOTO_CODE:
-                result = false; // Should be true at the end
+                result = true;
                 break;
                 
             case EDIT_INCLUDED_FILE:
@@ -319,6 +329,10 @@
                 result = true;
                 break;
                 
+            case HELP:
+                result = true;
+                break;
+                
             default:
                 result = false;
                 assert false;
@@ -339,6 +353,10 @@
                 previewWindowController.openWindow();
                 break;
                 
+            case CHOOSE_BACKGROUND_COLOR:
+                performChooseBackgroundColor(getStage());
+                break;
+                
             case SAVE_FILE:
                 performSaveOrSaveAsAction();
                 break;
@@ -360,9 +378,19 @@
                 break;
                 
             case GOTO_CONTENT:
+                contentPanelController.getGlassLayer().requestFocus();
+                break;
+
             case GOTO_PROPERTIES:
+                performGoToSection(SectionId.PROPERTIES);
+                break;
+                
             case GOTO_LAYOUT:
+                performGoToSection(SectionId.LAYOUT);
+                break;
+                
             case GOTO_CODE:
+                performGoToSection(SectionId.CODE);
                 break;
                 
             case TOGGLE_LEFT_PANEL: 
@@ -429,6 +457,10 @@
                 resourceController.performRevealResource();
                 break;
                 
+            case HELP:
+                performHelp();
+                break;
+                
             default:
                 assert false;
                 break;
@@ -710,6 +742,11 @@
         getStage().setTitle(makeTitle(editorController.getFxomDocument()));
     }
     
+    private void performChooseBackgroundColor(Window owner) {
+        final BackgroundColorDialogController bcdc 
+                = new BackgroundColorDialogController(owner);
+        bcdc.openWindow();
+    }
     
     ActionStatus performSaveOrSaveAsAction() {
         final ActionStatus result;
@@ -733,6 +770,10 @@
         });
     }
     
+    private void performGoToSection(SectionId sectionId) {
+        inspectorPanelController.setExpandedSection(sectionId);
+    }
+    
     private ActionStatus performSaveAction() {
         final FXOMDocument fxomDocument = editorController.getFxomDocument();
         assert fxomDocument != null;
@@ -1024,4 +1065,17 @@
         
         return result;
     }
+    
+        
+    private void performHelp() {
+        try {
+            EditorPlatform.open(EditorPlatform.DOCUMENTATION_URL);
+        } catch (IOException ioe) {
+            final ErrorDialog errorDialog = new ErrorDialog(null);
+            errorDialog.setMessage(I18N.getString("alert.help.failure.message", EditorPlatform.DOCUMENTATION_URL));
+            errorDialog.setDetails(I18N.getString("alert.messagebox.failure.details"));
+            errorDialog.setDebugInfoWithThrowable(ioe);
+            errorDialog.showAndWait();
+        }
+    }
 }
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderApp.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderApp.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,7 +35,9 @@
 import com.oracle.javafx.scenebuilder.app.about.AboutWindowController;
 import com.oracle.javafx.scenebuilder.app.i18n.I18N;
 import com.oracle.javafx.scenebuilder.app.menubar.MenuBarController;
-import com.oracle.javafx.scenebuilder.app.preferences.PreferencesDialogController;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesController;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesWindowController;
 import com.oracle.javafx.scenebuilder.app.template.FxmlTemplates;
 import com.oracle.javafx.scenebuilder.app.template.TemplateDialogController;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
@@ -64,8 +66,9 @@
  *
  */
 public class SceneBuilderApp extends Application implements AppPlatform.AppNotificationHandler {
-    
+
     public enum ApplicationControlAction {
+
         ABOUT,
         NEW_FILE,
         NEW_ALERT_DIALOG,
@@ -85,14 +88,14 @@
 
     private static SceneBuilderApp singleton;
     private final List<DocumentWindowController> windowList = new ArrayList<>();
-    private final PreferencesDialogController preferencesDialogController
-            = new PreferencesDialogController();
-    private final AboutWindowController aboutWindowController 
+    private final PreferencesWindowController preferencesWindowController
+            = new PreferencesWindowController();
+    private final AboutWindowController aboutWindowController
             = new AboutWindowController();
     private UserLibrary userLibrary;
     private MenuBarController defaultSystemMenuBarController; // Mac only
     private File nextInitialDirectory;
-    
+
 
     /*
      * Public
@@ -102,11 +105,11 @@
     }
 
     public void performControlAction(ApplicationControlAction a, DocumentWindowController source) {
-        switch(a) {
+        switch (a) {
             case ABOUT:
                 aboutWindowController.openWindow();
                 break;
-                
+
             case NEW_FILE:
                 final DocumentWindowController newWindow = makeNewWindow();
                 newWindow.loadWithDefaultContent();
@@ -131,21 +134,32 @@
             case OPEN_FILE:
                 performOpenFile(source);
                 break;
-                
+
             case CLOSE_FRONT_WINDOW:
                 performCloseFrontWindow();
                 break;
-                
+
             case SHOW_PREFERENCES:
-                preferencesDialogController.showAndWait();
+                preferencesWindowController.openWindow();
                 break;
-            
+
             case EXIT:
                 performExit();
                 break;
         }
     }
-    
+
+    public void performOpenRecent(DocumentWindowController source, final File fxmlFile) {
+        assert fxmlFile != null && fxmlFile.exists();
+
+        final List<File> fxmlFiles = new ArrayList<>();
+        fxmlFiles.add(fxmlFile);
+        performOpenFiles(fxmlFiles, source);
+        // Update recent items
+        final PreferencesController pc = PreferencesController.getSingleton();
+        final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+        recordGlobal.addRecentItems(fxmlFiles);
+    }
 
     public void documentWindowRequestClose(DocumentWindowController fromWindow) {
         closeWindow(fromWindow);
@@ -154,14 +168,14 @@
     public UserLibrary getUserLibrary() {
         return userLibrary;
     }
-    
+
     public List<DocumentWindowController> getDocumentWindowControllers() {
         return Collections.unmodifiableList(windowList);
     }
-    
+
     public DocumentWindowController lookupDocumentWindowControllers(URL fxmlLocation) {
         assert fxmlLocation != null;
-        
+
         DocumentWindowController result = null;
         try {
             final URI fxmlURI = fxmlLocation.toURI();
@@ -172,47 +186,46 @@
                     break;
                 }
             }
-        } catch(URISyntaxException x) {
+        } catch (URISyntaxException x) {
             // Should not happen
             throw new RuntimeException("Bug in " + getClass().getSimpleName(), x); //NOI18N
         }
-        
+
         return result;
     }
-    
+
     public void toggleDebugMenu() {
         final boolean visible;
-        
+
         if (windowList.isEmpty()) {
             visible = false;
         } else {
             final DocumentWindowController dwc = windowList.get(0);
             visible = dwc.getMenuBarController().isDebugMenuVisible();
         }
-        
-        for (DocumentWindowController dwc : windowList)  {
+
+        for (DocumentWindowController dwc : windowList) {
             dwc.getMenuBarController().setDebugMenuVisible(!visible);
         }
-        
+
         if (defaultSystemMenuBarController != null) {
             defaultSystemMenuBarController.setDebugMenuVisible(!visible);
         }
     }
-       
+
     public void updateNextInitialDirectory(File chosenFile) {
         assert chosenFile != null;
-        
+
         final Path chosenFolder = chosenFile.toPath().getParent();
         if (chosenFolder != null) {
             nextInitialDirectory = chosenFolder.toFile();
         }
     }
-    
+
     public File getNextInitialDirectory() {
         return nextInitialDirectory;
     }
-    
-    
+
     /*
      * Application
      */
@@ -220,7 +233,7 @@
     public void start(Stage stage) throws Exception {
         assert singleton == null;
         singleton = this;
-        
+
         try {
             if (AppPlatform.requestStart(this, getParameters()) == false) {
                 // Start has been denied because another instance is running.
@@ -231,8 +244,8 @@
             //      AppPlatform.requestStart() has/will invoke(d) handleLaunch().
             //      start() has now finished its job and should imply return.
             // }
-            
-        } catch(IOException x) {
+
+        } catch (IOException x) {
             final ErrorDialog errorDialog = new ErrorDialog(null);
             errorDialog.setTitle(I18N.getString("alert.title.start"));
             errorDialog.setMessage(I18N.getString("alert.start.failure.message"));
@@ -246,27 +259,26 @@
     /*
      * AppPlatform.AppNotificationHandler
      */
-    
     @Override
     public void handleLaunch(List<String> files) {
-        
+
         // On Mac, AppPlatform disables implicit exit.
         // So we need to set a default system menu bar.
         if (Platform.isImplicitExit() == false) {
             defaultSystemMenuBarController = new MenuBarController(null);
             Deprecation.setDefaultSystemMenuBar(defaultSystemMenuBarController.getMenuBar());
         }
-        
+
         // Creates the user library
         userLibrary = new UserLibrary(AppPlatform.getUserLibraryFolder());
         userLibrary.startWatching();
-        
+
         if (files.isEmpty()) {
             // Creates an empty document
             final DocumentWindowController newWindow = makeNewWindow();
             newWindow.loadWithDefaultContent();
             newWindow.openWindow();
-        
+
             // Show ScenicView Tool when the JVM is started with option -Dscenic.
             // NetBeans: set it on [VM Options] line in [Run] category of project's Properties.
             if (System.getProperty("scenic") != null) { //NOI18N
@@ -276,19 +288,23 @@
             // Open files passed as arguments by the platform
             handleOpenFilesAction(files);
         }
+
+        // Load java preferences at start time
+        final PreferencesController pc = PreferencesController.getSingleton();
+        final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+        recordGlobal.readFromJavaPreferences();
     }
 
-    
     @Override
     public void handleOpenFilesAction(List<String> files) {
         assert files != null;
         assert files.isEmpty() == false;
-        
+
         final List<File> fileObjs = new ArrayList<>();
         for (String file : files) {
             fileObjs.add(new File(file));
         }
-        
+
         performOpenFiles(fileObjs, null);
     }
 
@@ -304,10 +320,32 @@
 
     @Override
     public void handleQuitAction() {
-        performControlAction(ApplicationControlAction.EXIT, null);
+
+        /*
+         * Note : this callback is called on Mac OS X only when the user
+         * selects the 'Quit App' command in the Application menu.
+         * 
+         * Before calling this callback, FX automatically sends a close event
+         * to each open window ie DocumentWindowController.performCloseAction()
+         * is invoked for each open window.
+         * 
+         * When we arrive here, windowList is empty if the user has confirmed
+         * the close operation for each window : thus exit operation can
+         * be performed. If windowList is not empty,  this means the user has 
+         * cancelled at least one close operation : in that case, exit operation
+         * should be not be executed.
+         */
+        if (windowList.isEmpty()) {
+
+            // Write java preferences at quit time
+            final PreferencesController pc = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+            recordGlobal.writeToJavaPreferences();
+
+            Platform.exit();
+        }
     }
 
-    
     /**
      * Ignored in correctly deployed JavaFX application.
      */
@@ -318,7 +356,6 @@
     /*
      * Private
      */
-    
     public DocumentWindowController makeNewWindow() {
         final DocumentWindowController result = new DocumentWindowController();
         windowList.add(result);
@@ -330,16 +367,14 @@
         windowList.remove(w);
         w.closeWindow();
     }
-    
+
     private static String displayName(String pathString) {
         return Paths.get(pathString).getFileName().toString();
     }
-    
-    
+
     /*
      * Private (control actions)
      */
-    
     private void performOpenFile(DocumentWindowController fromWindow) {
         final FileChooser fileChooser = new FileChooser();
 
@@ -353,9 +388,13 @@
             assert fxmlFiles.isEmpty() == false;
             updateNextInitialDirectory(fxmlFiles.get(0));
             performOpenFiles(fxmlFiles, fromWindow);
+            // Update recent items
+            final PreferencesController pc = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+            recordGlobal.addRecentItems(fxmlFiles);
         }
     }
-    
+
     private void performNewTemplate(ApplicationControlAction action) {
         final DocumentWindowController newTemplateWindow = makeNewWindow();
         final URL url = FxmlTemplates.getContentURL(action);
@@ -367,13 +406,12 @@
         final TemplateDialogController tdc = new TemplateDialogController(action);
         tdc.openWindow();
     }
-    
+
     private void performCloseFrontWindow() {
-        if (preferencesDialogController != null 
-                && preferencesDialogController.getStage().isFocused()) {
-            preferencesDialogController.closeWindow();
-        }
-        else {
+        if (preferencesWindowController != null
+                && preferencesWindowController.getStage().isFocused()) {
+            preferencesWindowController.closeWindow();
+        } else {
             for (DocumentWindowController dwc : windowList) {
                 if (dwc.isFrontDocumentWindow()) {
                     dwc.performCloseFrontDocumentWindow();
@@ -382,13 +420,12 @@
             }
         }
     }
-    
-    
-    private void performOpenFiles(List<File> fxmlFiles, 
+
+    private void performOpenFiles(List<File> fxmlFiles,
             DocumentWindowController fromWindow) {
         assert fxmlFiles != null;
         assert fxmlFiles.isEmpty() == false;
-        
+
         final Map<File, IOException> exceptions = new HashMap<>();
         for (File fxmlFile : fxmlFiles) {
             try {
@@ -412,8 +449,8 @@
                 exceptions.put(fxmlFile, xx);
             }
         }
-        
-        switch(exceptions.size()) {
+
+        switch (exceptions.size()) {
             case 0: { // Good
                 break;
             }
@@ -446,10 +483,9 @@
             }
         }
     }
-    
-    
+
     private void performExit() {
-        
+
         // Collects the documents with pending changes
         final List<DocumentWindowController> pendingDocs = new ArrayList<>();
         for (DocumentWindowController dwc : windowList) {
@@ -458,32 +494,32 @@
                 pendingDocs.add(dwc);
             }
         }
-        
+
         // Notifies the user if some documents are dirty
         final boolean exitConfirmed;
-        switch(pendingDocs.size()) {
+        switch (pendingDocs.size()) {
             case 0: {
                 exitConfirmed = true;
                 break;
             }
-            
+
             case 1: {
                 final DocumentWindowController dwc0 = pendingDocs.get(0);
                 exitConfirmed = dwc0.performCloseAction() == ActionStatus.DONE;
                 break;
             }
-            
+
             default: {
                 assert pendingDocs.size() >= 2;
-                
+
                 final AlertDialog d = new AlertDialog(null);
                 d.setMessage(I18N.getString("alert.review.question.message", pendingDocs.size()));
                 d.setDetails(I18N.getString("alert.review.question.details"));
                 d.setOKButtonTitle(I18N.getString("label.review.changes"));
                 d.setActionButtonTitle(I18N.getString("label.discard.changes"));
                 d.setActionButtonVisible(true);
-            
-                switch(d.showAndWait()) {
+
+                switch (d.showAndWait()) {
                     default:
                     case OK: { // Review
                         int i = 0;
@@ -506,7 +542,7 @@
                 break;
             }
         }
-        
+
         // Exit if confirmed
         if (exitConfirmed) {
             for (DocumentWindowController dwc : new ArrayList<>(windowList)) {
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderTest.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/SceneBuilderTest.java	Tue Dec 10 08:36:28 2013 +0100
@@ -31,6 +31,7 @@
  */
 package com.oracle.javafx.scenebuilder.app;
 
+import com.oracle.javafx.scenebuilder.app.about.AboutWindowController;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.handles.AbstractGenericHandles;
@@ -370,6 +371,19 @@
         return result;
     }
     
+    /**
+     * Returns the version string.
+     * It has the format 'Version: [major].[minor]-b[ii], Changeset: [someValue]'.
+     * <br>A typical value is 'Version: 2.0-b07, Changeset: 8a5ccd834b5f'.
+     * 
+     * @return a version string. It is never null: in the case something weird
+     * would occur when constructing the proper value then what is returned is
+     * 'UNSET'.
+     */
+    public static String getVersionString() {
+        AboutWindowController awc = new AboutWindowController();
+        return awc.getBuildInfo();
+    }
     
     /*
      * Private
@@ -387,6 +401,7 @@
         
         return result;
     }
+    
     private static DocumentWindowController lookupWindowController(Scene documentScene) {
         DocumentWindowController result = null;
         
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/about/AboutWindowController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/about/AboutWindowController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -170,4 +170,12 @@
     public String getBuildJavaVersion() {
         return sbBuildJavaVersion;
     }
+    
+    /**
+     *
+     * @treatAsPrivate
+     */
+    public String getBuildInfo() {
+        return sbBuildInfo;
+    }
 }
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/i18n/SceneBuilderApp.properties	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/i18n/SceneBuilderApp.properties	Tue Dec 10 08:36:28 2013 +0100
@@ -45,6 +45,8 @@
 menu.title.new.complex.app.css = Complex Application - CSS\u2026
 menu.title.new.complex.app.i18n = Complex Application - Localized\u2026
 menu.title.open = Open\u2026
+menu.title.open.recent = Open Recent
+menu.title.open.recent.clear = Clear Menu
 menu.title.save = Save
 menu.title.save.as = Save As\u2026
 menu.title.revert = Revert to Saved
@@ -171,11 +173,13 @@
 prefs.cssanalyzer.columns.order = CSS Analyzer Columns order :
 prefs.cssanalyzer.columns.defaults.first = "Defaults" Column First
 prefs.cssanalyzer.columns.defaults.last = "Defaults" Column Last
+prefs.recent.items = Recent items
 
 # -----------------------------------------------------------------------------
 # Preview Window
 # -----------------------------------------------------------------------------
 preview.constructing = Constructing Preview content ...
+preview.background.color = Background Color
 preview.no.document = No document
 preview.not.node = Not a Node
 scenestylesheet.filechooser.filter.msg = CSS and BSS files
@@ -239,10 +243,15 @@
 # -----------------------------------------------------------------------------
 # Info panel
 # -----------------------------------------------------------------------------
+info.label.assigned = Assigned fx:id
+info.label.component = Component
+info.label.use.fx.root = Use fx:root construct
 # Used after number 1
 info.label.item = item
 # Used after any number greater than 1
 info.label.items = items
+# The parameter is the name of a Java class
+info.tooltip.controller = Your Controller class must extend {0}
 
 # -----------------------------------------------------------------------------
 # Menu Bar
@@ -288,6 +297,7 @@
 alert.reveal.failure.message = Could not reveal ''{0}''
 alert.reveal.failure.details = Reveal operation has failed. Check logs of the operating system.
 alert.copy.failure.message = Could not copy ''{0}''
+alert.help.failure.message = Could not access to ''{0}''
 
 # -----------------------------------------------------------------------------
 # Log Messages
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanel.css	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, 2013, 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.
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                             General appearance                             */
+/* -------------------------------------------------------------------------- */
+
+.text-field,
+.menu-button {
+    -fx-background-radius: 0;
+}
+
+.text-input {
+    -fx-padding: 0.0em 0.417em 0.0em 0.417em; /* 0 5 0 5 */
+}
+
+.menu-button {
+    -fx-padding: -0.083em -0.083em -0.167em -0.083em; /* -1 -1 -2 -1 */
+}
+
+/* Property names are Hyperlinks so we can link to Docs */
+.hyperlink, .hyperlink:visited {
+    -fx-padding: 0.25em 0.417em 0.167em 0em; /* 3 5 2 0 */
+    -fx-text-fill: -fx-text-background-color;
+    -fx-border-width: 0px;
+    -fx-underline: false;
+    /* need to add a background color because of RT-32834 */
+    -fx-background-color: -fx-background;
+    /* Padding so Hyperlinks are same height as controls for vert. alignment */
+    -fx-padding: 0.25em 0.417em 0.167em 0em; /* 3 5 2 0 */
+}
+
+.hyperlink:hover, .hyperlink:visited:hover {
+    -fx-underline: true;
+}
+
+/* -------------------------------------------------------------------------- */
+/*                             Suggested ListView                             */
+/* -------------------------------------------------------------------------- */
+.suggested-list {
+    -fx-font-size: 0.846em;  /* 11 */
+    -fx-pref-width: -1.0;
+    -fx-max-width: -1.0;
+ }
+ 
+/* -------------------------------------------------------------------------- */
+/*                              Cog Menu Button                               */
+/* -------------------------------------------------------------------------- */
+
+.cog-button {
+    -fx-background-color: transparent, transparent;
+    -fx-background-radius: 10, 10;
+    -fx-background-insets: 3 0 3 0, 4 1 4 1;
+    -fx-padding: 0em 0.0em 0em 0.0em;
+}
+.cog-button:hover {
+    -fx-background-color: derive(-fx-background, -25%), -fx-background;
+}
+.cog-button:focused {
+    -fx-background-color: -fx-focus-color, -fx-background;
+}
+.cog-button .arrow-button {
+    -fx-padding:0;
+}
+.cog-button .label {
+    -fx-padding:-2 0 0 0;
+}
+
+.cog-button .arrow {
+    -fx-shape: null;  
+    -fx-padding:0;
+}
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanel.fxml	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanel.fxml	Tue Dec 10 08:36:28 2013 +0100
@@ -31,30 +31,31 @@
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -->
+
 <?import java.lang.*?>
+<?import java.net.*?>
 <?import javafx.geometry.*?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
 
-<VBox id="StackPane" spacing="7.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
+<VBox id="StackPane" spacing="7.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
-    <VBox id="VBox" alignment="CENTER" spacing="0.0">
+    <VBox fx:id="controllerClassVBox" alignment="CENTER" spacing="0.0">
       <children>
-        <Label alignment="CENTER_LEFT" disable="true" maxHeight="-1.0" maxWidth="1.7976931348623157E308" text="Controller Class" />
-        <TextField disable="true" prefWidth="200.0" />
+        <HBox fx:id="controllerAndCogHBox" maxWidth="1.7976931348623157E308" prefHeight="-1.0" prefWidth="-1.0" />
       </children>
     </VBox>
-    <CheckBox disable="true" mnemonicParsing="false" text="Use fx:root" />
+    <CheckBox fx:id="fxrootCheckBox" mnemonicParsing="false" text="%info.label.use.fx.root" />
     <VBox id="VBox" alignment="CENTER" spacing="5.0">
       <children>
-        <Label maxWidth="1.7976931348623157E308" text="Assigned fx:ids" />
+        <Label maxWidth="1.7976931348623157E308" text="%info.label.assigned" />
         <TableView maxHeight="1.7976931348623157E308" VBox.vgrow="ALWAYS">
           <columnResizePolicy>
             <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
           </columnResizePolicy>
           <columns>
-            <TableColumn maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="117.0" resizable="true" sortable="true" text="fx:id" fx:id="leftTableColumn" />
-            <TableColumn maxWidth="1.7976931348623157E308" minWidth="30.0" prefWidth="100.0" sortable="true" text="Component" fx:id="rightTableColumn" />
+            <TableColumn fx:id="leftTableColumn" maxWidth="1.7976931348623157E308" minWidth="30.0" prefWidth="-1.0" resizable="true" sortable="true" text="fx:id" />
+            <TableColumn fx:id="rightTableColumn" maxWidth="1.7976931348623157E308" minWidth="100.0" prefWidth="-1.0" sortable="true" text="%info.label.component" />
           </columns>
           <sortOrder>
             <fx:reference source="leftTableColumn" />
@@ -67,4 +68,7 @@
       </VBox.margin>
     </VBox>
   </children>
+  <stylesheets>
+    <URL value="@InfoPanel.css" />
+  </stylesheets>
 </VBox>
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -33,24 +33,35 @@
 
 import com.oracle.javafx.scenebuilder.app.i18n.I18N;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.ModifyFxControllerJob;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.ControllerClassEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.util.AbstractFxmlPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.GridSelectionGroup;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.glossary.Glossary;
+import java.net.URL;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener;
 import javafx.fxml.FXML;
+import javafx.geometry.Pos;
+import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableView;
+import javafx.scene.control.Tooltip;
 import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
 
 /**
  * 
@@ -60,11 +71,15 @@
     @FXML private TableColumn<IndexEntry,String> leftTableColumn;
     @FXML private TableColumn<IndexEntry,FXOMObject> rightTableColumn;
     @FXML private Label bottomLabel;
+    @FXML private VBox controllerClassVBox;
+    @FXML CheckBox fxrootCheckBox;
+    @FXML HBox controllerAndCogHBox;
     
     private IndexEntry.Type entryType = IndexEntry.Type.FX_ID;
+    private ControllerClassEditor controllerClassEditor;
     
     public InfoPanelController(EditorController editorController) {
-        super(InfoPanelController.class.getResource("InfoPanel.fxml"), editorController); //NOI18N
+        super(InfoPanelController.class.getResource("InfoPanel.fxml"), I18N.getBundle(), editorController); //NOI18N
     }
 
     public IndexEntry.Type getEntryType() {
@@ -93,6 +108,7 @@
     @Override
     protected void jobManagerRevisionDidChange() {
         requestEntriesUpdate();
+        updateAsPerRootNodeStatus();
     }
     
     @Override
@@ -128,6 +144,44 @@
         assert rightTableColumn != null;
         assert leftTableColumn.getTableView() == rightTableColumn.getTableView();
         assert bottomLabel != null;
+        assert controllerClassVBox != null;
+        assert fxrootCheckBox != null;
+        assert controllerAndCogHBox != null;
+        
+        if (controllerClassEditor != null) {
+            controllerClassEditor.reset(getSuggestedControllerClasses());
+        } else {
+            controllerClassEditor = new ControllerClassEditor(getSuggestedControllerClasses());
+        }
+        
+        HBox propNameNode = controllerClassEditor.getPropNameNode();
+        
+        // Make so that the property name appears left justified in the VBox
+        propNameNode.setAlignment(Pos.CENTER_LEFT);
+        controllerClassVBox.getChildren().add(0, propNameNode);
+        
+        // Initialize field with current value, if defined.
+        if (getEditorController().getFxomDocument().getFxomRoot() != null) {
+            controllerClassEditor.setValue(getEditorController().getFxomDocument().getFxomRoot().getFxController());
+        }
+        controllerAndCogHBox.getChildren().add(controllerClassEditor.getValueEditor());
+        controllerAndCogHBox.getChildren().add(controllerClassEditor.getMenu());
+        
+        // Need to react each time value of fx controller is changed
+        controllerClassEditor.valueProperty().addListener(new ChangeListener<Object>() {
+
+            @Override
+            public void changed(ObservableValue<? extends Object> ov, Object t, Object t1) {
+                assert t1 instanceof String;
+                FXOMObject root = getEditorController().getFxomDocument().getFxomRoot();
+                
+                if (root != null) {
+                    final ModifyFxControllerJob job =
+                            new ModifyFxControllerJob(root,(String)t1, getEditorController());
+                    getEditorController().getJobManager().push(job);
+                }
+            }
+        });
         
         leftTableColumn.setCellValueFactory(new PropertyValueFactory<>("key")); //NOI18N
         rightTableColumn.setCellValueFactory(new PropertyValueFactory<>("fxomObject")); //NOI18N
@@ -135,9 +189,10 @@
         rightTableColumn.setCellFactory(new RightCell.Factory());
         
         requestEntriesUpdate();
+        updateAsPerRootNodeStatus();
     }
     
-    
+
     /*
      * Private
      */
@@ -160,8 +215,11 @@
                                 = fxomDocument.collectFxIds();
                         for (Map.Entry<String, FXOMObject> e : fxIds.entrySet()) {
                             final String fxId = e.getKey();
-                            final FXOMObject fxomObject = e.getValue();
-                            newEntries.add(new IndexEntry(fxId, entryType, fxomObject));
+                            // TODO Remove isEmpty test below once DTL-6085 is fixed
+                            if (! fxId.isEmpty()) {
+                                final FXOMObject fxomObject = e.getValue();
+                                newEntries.add(new IndexEntry(fxId, entryType, fxomObject));
+                            }
                         }
                         break;
                     }
@@ -220,13 +278,13 @@
         tableView.getSelectionModel().getSelectedItems().removeListener(tableViewSelectionListener);
     }
     
-        private final ListChangeListener<IndexEntry> tableViewSelectionListener
-            = new ListChangeListener<IndexEntry>() {
-                @Override
-                public void onChanged(ListChangeListener.Change<? extends IndexEntry> change) {
-                    tableSelectionDidChange();
-                }
-            };
+    private final ListChangeListener<IndexEntry> tableViewSelectionListener
+        = new ListChangeListener<IndexEntry>() {
+            @Override
+            public void onChanged(ListChangeListener.Change<? extends IndexEntry> change) {
+                tableSelectionDidChange();
+            }
+        };
     
     private void tableSelectionDidChange() {
         final TableView<IndexEntry> tableView = leftTableColumn.getTableView();
@@ -257,4 +315,35 @@
         
         return result;
     }
+    
+    
+    private List<String> getSuggestedControllerClasses() {
+        Glossary glossary = getEditorController().getGlossary();
+        URL location = null;
+        if (getEditorController().getFxomDocument() != null) {
+            location = getEditorController().getFxomDocument().getLocation();
+        }
+        return glossary.queryControllerClasses(location);
+    }
+
+    // When there is no defined root node we reset and disable the class field
+    // and the fx:root check box.
+    private void updateAsPerRootNodeStatus() {
+        // For now there is no underlying support of fx:root so we keep the
+        // check box disabled
+        fxrootCheckBox.setDisable(true);
+
+        if (getEditorController().getFxomDocument().getFxomRoot() == null) {
+//            fxrootCheckBox.setSelected(false);
+//            fxrootCheckBox.setDisable(true);
+            controllerClassEditor.setDisable(true);
+            controllerClassEditor.setValue(""); //NOI18N
+            
+        } else {
+//            fxrootCheckBox.setDisable(false);
+            String topClassName = getEditorController().getFxomDocument().getGlue().getRootElement().getTagName();
+            fxrootCheckBox.setTooltip(new Tooltip(I18N.getString("info.tooltip.controller", topClassName)));
+            controllerClassEditor.setDisable(false);
+        }
+    }    
 }
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBar.fxml	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBar.fxml	Tue Dec 10 08:36:28 2013 +0100
@@ -38,191 +38,200 @@
 <?scenebuilder-preview-i18n-resource ../i18n/SceneBuilderApp.properties?>
 
 <StackPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
-  <children>
-    <MenuBar fx:id="menuBar">
-      <menus>
-        <Menu fx:id="fileMenu" mnemonicParsing="false" text="%menu.title.file">
-          <items>
-            <MenuItem fx:id="newMenuItem" mnemonicParsing="false" text="%menu.title.new" />
-            <Menu fx:id="newTemplateMenuItem" mnemonicParsing="false" text="%menu.title.new.template">
-              <items>
-                <MenuItem fx:id="newAlertDialogMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog" />
-                <MenuItem fx:id="newBasicAppMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app" />
-                <MenuItem fx:id="newComplexAppMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app" />
-                <SeparatorMenuItem mnemonicParsing="false" />
-                <MenuItem fx:id="newAlertDialogCssMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog.css" />
-                <MenuItem fx:id="newAlertDialogI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog.i18n" />
-                <MenuItem fx:id="newBasicAppCssMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app.css" />
-                <MenuItem fx:id="newBasicAppI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app.i18n" />
-                <MenuItem fx:id="newComplexAppCssMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app.css" />
-                <MenuItem fx:id="newComplexAppI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app.i18n" />
-              </items>
-            </Menu>
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="openMenuItem" mnemonicParsing="false" text="%menu.title.open" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="saveMenuItem" mnemonicParsing="false" text="%menu.title.save" />
-            <MenuItem fx:id="saveAsMenuItem" mnemonicParsing="false" text="%menu.title.save.as" />
-            <MenuItem fx:id="revertMenuItem" mnemonicParsing="false" text="%menu.title.revert" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="revealMenuItem" mnemonicParsing="false" text="Reveal (setup at runtime)" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="closeMenuItem" mnemonicParsing="false" text="%menu.title.close" />
-            <SeparatorMenuItem fx:id="separatorAbovePreferencesMenuItem" mnemonicParsing="false" />
-            <MenuItem fx:id="showPreferencesMenuItem" mnemonicParsing="false" text="%menu.title.preferences" />
-            <MenuItem fx:id="exitMenuItem" mnemonicParsing="false" text="%menu.title.quit" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="%menu.title.edit">
-          <items>
-            <MenuItem fx:id="undoMenuItem" mnemonicParsing="false" text="%menu.title.undo" />
-            <MenuItem fx:id="redoMenuItem" mnemonicParsing="false" text="%menu.title.redo" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="cutMenuItem" mnemonicParsing="false" text="%menu.title.cut" />
-            <MenuItem fx:id="copyMenuItem" mnemonicParsing="false" text="%menu.title.copy" />
-            <MenuItem fx:id="pasteMenuItem" mnemonicParsing="false" text="%menu.title.paste" />
-            <MenuItem fx:id="pasteIntoMenuItem" mnemonicParsing="false" text="%menu.title.paste.into" />
-            <MenuItem fx:id="duplicateMenuItem" mnemonicParsing="false" text="%menu.title.duplicate" />
-            <MenuItem fx:id="deleteMenuItem" mnemonicParsing="false" text="%menu.title.delete" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="selectAllMenuItem" mnemonicParsing="false" text="%menu.title.select.all" />
-            <MenuItem fx:id="selectNoneMenuItem" mnemonicParsing="false" text="%menu.title.select.none" />
-            <MenuItem fx:id="selectParentMenuItem" mnemonicParsing="false" text="%menu.title.select.parent" />
-            <MenuItem fx:id="selectNextMenuItem" mnemonicParsing="false" text="%menu.title.select.next" />
-            <MenuItem fx:id="selectPreviousMenuItem" mnemonicParsing="false" text="%menu.title.select.previous" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="trimMenuItem" mnemonicParsing="false" text="%menu.title.trim" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="%menu.title.view">
-          <items>
-            <MenuItem fx:id="gotoContentMenuItem" mnemonicParsing="false" text="%menu.title.content" />
-            <MenuItem fx:id="gotoPropertiesMenuItem" mnemonicParsing="false" text="%menu.title.properties" />
-            <MenuItem fx:id="gotoLayoutMenuItem" mnemonicParsing="false" text="%menu.title.layout" />
-            <MenuItem fx:id="gotoCodeMenuItem" mnemonicParsing="false" text="%menu.title.code" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="toggleLibraryPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.library.panel" />
-            <MenuItem fx:id="toggleHierarchyPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.document.panel" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="toggleCSSPanelMenuItem" mnemonicParsing="false" text="%menu.title.show.bottom.panel" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="toggleLeftPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.left.panel" />
-            <MenuItem fx:id="toggleRightPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.right.panel" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="toggleOutlinesMenuItem" mnemonicParsing="false" text="%menu.title.show.outlines" />
-            <MenuItem fx:id="toggleSampleDataMenuItem" mnemonicParsing="false" text="%menu.title.show.sample.data" />
-            <MenuItem fx:id="toggleAlignmentGuidesMenuItem" mnemonicParsing="false" text="%menu.title.disable.guides" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <Menu fx:id="zoomMenu" mnemonicParsing="false" text="%menu.title.zoom" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="showSampleControllerMenuItem" mnemonicParsing="false" text="%menu.title.show.sample.controller.skeleton" />
-          </items>
-        </Menu>
-        <Menu fx:id="insertMenu" mnemonicParsing="false" text="%menu.title.insert" />
-        <Menu mnemonicParsing="false" text="%menu.title.modify">
-          <items>
-            <MenuItem fx:id="fitToParentMenuItem" mnemonicParsing="false" text="%menu.title.fit" />
-            <MenuItem fx:id="useComputedSizesMenuItem" mnemonicParsing="false" text="%menu.title.use.computed.sizes" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <Menu mnemonicParsing="false" text="%menu.title.grid">
-              <items>
-                <MenuItem fx:id="selectNextRowMenuItem" mnemonicParsing="false" text="%menu.title.grid.select.next.row" />
-                <MenuItem fx:id="selectNextColumnMenuItem" mnemonicParsing="false" text="%menu.title.grid.select.next.column" />
-                <SeparatorMenuItem mnemonicParsing="false" />
-                <MenuItem fx:id="moveRowAboveMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.row.above" />
-                <MenuItem fx:id="moveRowBelowMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.row.below" />
-                <MenuItem fx:id="moveColumnBeforeMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.column.before" />
-                <MenuItem fx:id="moveColumnAfterMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.column.after" />
-                <SeparatorMenuItem mnemonicParsing="false" />
-                <MenuItem fx:id="addRowAboveMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.row.above" />
-                <MenuItem fx:id="addRowBelowMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.row.below" />
-                <MenuItem fx:id="addColumnBeforeMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.column.before" />
-                <MenuItem fx:id="addColumnAfterMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.column.after" />
-                <SeparatorMenuItem mnemonicParsing="false" />
-                <MenuItem fx:id="increaseRowSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.increase.row.span" />
-                <MenuItem fx:id="decreaseRowSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.decrease.row.span" />
-                <MenuItem fx:id="increaseColumnSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.increase.column.span" />
-                <MenuItem fx:id="decreaseColumnSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.decrease.column.span" />
-              </items>
-            </Menu>
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <Menu fx:id="addEffectMenu" mnemonicParsing="false" text="%menu.title.add.effect" />
-            <Menu fx:id="addPopupControlMenu" mnemonicParsing="false" text="%menu.title.add.popup" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="editIncludedFileMenuItem" mnemonicParsing="false" text="%menu.title.edit.included.default" />
-            <MenuItem fx:id="revealIncludedFileMenuItem" mnemonicParsing="false" text="%menu.title.reveal.included.default" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="%menu.title.arrange">
-          <items>
-            <MenuItem fx:id="bringToFrontMenuItem" mnemonicParsing="false" text="%menu.title.front" />
-            <MenuItem fx:id="sendToBackMenuItem" mnemonicParsing="false" text="%menu.title.back" />
-            <MenuItem fx:id="bringForwardMenuItem" mnemonicParsing="false" text="%menu.title.forward" />
-            <MenuItem fx:id="sendBackwardMenuItem" mnemonicParsing="false" text="%menu.title.backward" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <Menu mnemonicParsing="false" text="%menu.title.wrap">
-              <items>
-                <MenuItem fx:id="wrapInAnchorPaneMenuItem" mnemonicParsing="false" text="AnchorPane" />
-                <MenuItem fx:id="wrapInGridPaneMenuItem" mnemonicParsing="false" text="GridPane" />
-                <MenuItem fx:id="wrapInHBoxMenuItem" mnemonicParsing="false" text="HBox" />
-                <MenuItem fx:id="wrapInPaneMenuItem" mnemonicParsing="false" text="Pane" />
-                <MenuItem fx:id="wrapInScrollPaneMenuItem" mnemonicParsing="false" text="ScrollPane" />
-                <MenuItem fx:id="wrapInSplitPaneMenuItem" mnemonicParsing="false" text="SplitPane" />
-                <MenuItem fx:id="wrapInStackPaneMenuItem" mnemonicParsing="false" text="StackPane" />
-                <MenuItem fx:id="wrapInTabPaneMenuItem" mnemonicParsing="false" text="TabPane" />
-                <MenuItem fx:id="wrapInTitledPaneMenuItem" mnemonicParsing="false" text="TitledPane" />
-                <MenuItem fx:id="wrapInToolBarMenuItem" mnemonicParsing="false" text="ToolBar" />
-                <MenuItem fx:id="wrapInVBoxMenuItem" mnemonicParsing="false" text="VBox" />
-                <MenuItem fx:id="wrapInGroupMenuItem" mnemonicParsing="false" text="Group" />
-              </items>
-            </Menu>
-            <MenuItem fx:id="unwrapMenuItem" mnemonicParsing="false" text="%menu.title.unwrap" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="%menu.title.preview">
-          <items>
-            <MenuItem fx:id="showPreviewMenuItem" mnemonicParsing="false" text="%menu.title.show.preview" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <MenuItem fx:id="chooseBackgroundColorMenuItem" mnemonicParsing="false" text="%menu.title.choose.background.color" />
-            <SeparatorMenuItem mnemonicParsing="false" />
-            <Menu mnemonicParsing="false" text="%menu.title.theme">
-                <items>
-                    <RadioMenuItem fx:id="modenaThemeMenuItem" mnemonicParsing="false" text="%menu.title.theme.modena" />
-                    <RadioMenuItem fx:id="caspianThemeMenuItem" mnemonicParsing="false" text="%menu.title.theme.caspian" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" />
-                </items>
-            </Menu>
-            <Menu mnemonicParsing="false" text="%menu.title.scene.stylesheets">
-              <items>
-                <MenuItem fx:id="addSceneStyleSheetMenuItem" mnemonicParsing="false" text="%menu.title.add.stylesheet" />
-                <Menu fx:id="removeSceneStyleSheetMenu" mnemonicParsing="false" text="%menu.title.remove.stylesheet">
-<items><MenuItem disable="true" mnemonicParsing="false" text="%scenestylesheet.none" />
-</items></Menu>
-                <Menu fx:id="openSceneStyleSheetMenu" mnemonicParsing="false" text="%menu.title.open.stylesheet">
-<items><MenuItem disable="true" mnemonicParsing="false" text="%scenestylesheet.none" />
-</items></Menu>
-              </items>
-            </Menu>
-            <Menu mnemonicParsing="false" text="%menu.title.internationalization">
-              <items>
-                <MenuItem fx:id="setResourceMenuItem" mnemonicParsing="false" text="%menu.title.set.resource" />
-                <MenuItem fx:id="removeResourceMenuItem" mnemonicParsing="false" text="%menu.title.remove.resource" />
-                <MenuItem fx:id="revealResourceMenuItem" mnemonicParsing="false" text="%menu.title.reveal.resource" />
-              </items>
-            </Menu>
-          </items>
-        </Menu>
-        <Menu fx:id="windowMenu" mnemonicParsing="false" text="%menu.title.window">
-          <items>
-            <SeparatorMenuItem mnemonicParsing="false" />
-          </items>
-        </Menu>
-        <Menu mnemonicParsing="false" text="%menu.title.help">
-          <items>
-            <MenuItem fx:id="helpMenuItem" mnemonicParsing="false" text="%menu.title.help" />
-            <MenuItem fx:id="aboutMenuItem" mnemonicParsing="false" text="%menu.title.about" />
-          </items>
-        </Menu>
-      </menus>
-    </MenuBar>
-  </children>
+    <children>
+        <MenuBar fx:id="menuBar">
+            <menus>
+                <Menu fx:id="fileMenu" mnemonicParsing="false" text="%menu.title.file">
+                    <items>
+                        <MenuItem fx:id="newMenuItem" mnemonicParsing="false" text="%menu.title.new" />
+                        <Menu fx:id="newTemplateMenuItem" mnemonicParsing="false" text="%menu.title.new.template">
+                            <items>
+                                <MenuItem fx:id="newAlertDialogMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog" />
+                                <MenuItem fx:id="newBasicAppMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app" />
+                                <MenuItem fx:id="newComplexAppMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app" />
+                                <SeparatorMenuItem mnemonicParsing="false" />
+                                <MenuItem fx:id="newAlertDialogCssMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog.css" />
+                                <MenuItem fx:id="newAlertDialogI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.alert.dialog.i18n" />
+                                <MenuItem fx:id="newBasicAppCssMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app.css" />
+                                <MenuItem fx:id="newBasicAppI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.basic.app.i18n" />
+                                <MenuItem fx:id="newComplexAppCssMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app.css" />
+                                <MenuItem fx:id="newComplexAppI18nMenuItem" mnemonicParsing="false" text="%menu.title.new.complex.app.i18n" />
+                            </items>
+                        </Menu>
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="openMenuItem" mnemonicParsing="false" text="%menu.title.open" />
+                        <Menu fx:id="openRecentMenu" mnemonicParsing="false" text="%menu.title.open.recent" >              
+                            <items>
+                                <MenuItem mnemonicParsing="false" text="Action 1" />
+                            </items>
+                        </Menu>
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="saveMenuItem" mnemonicParsing="false" text="%menu.title.save" />
+                        <MenuItem fx:id="saveAsMenuItem" mnemonicParsing="false" text="%menu.title.save.as" />
+                        <MenuItem fx:id="revertMenuItem" mnemonicParsing="false" text="%menu.title.revert" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="revealMenuItem" mnemonicParsing="false" text="Reveal (setup at runtime)" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="closeMenuItem" mnemonicParsing="false" text="%menu.title.close" />
+                        <SeparatorMenuItem fx:id="separatorAbovePreferencesMenuItem" mnemonicParsing="false" />
+                        <MenuItem fx:id="showPreferencesMenuItem" mnemonicParsing="false" text="%menu.title.preferences" />
+                        <MenuItem fx:id="exitMenuItem" mnemonicParsing="false" text="%menu.title.quit" />
+                    </items>
+                </Menu>
+                <Menu mnemonicParsing="false" text="%menu.title.edit">
+                    <items>
+                        <MenuItem fx:id="undoMenuItem" mnemonicParsing="false" text="%menu.title.undo" />
+                        <MenuItem fx:id="redoMenuItem" mnemonicParsing="false" text="%menu.title.redo" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="cutMenuItem" mnemonicParsing="false" text="%menu.title.cut" />
+                        <MenuItem fx:id="copyMenuItem" mnemonicParsing="false" text="%menu.title.copy" />
+                        <MenuItem fx:id="pasteMenuItem" mnemonicParsing="false" text="%menu.title.paste" />
+                        <MenuItem fx:id="pasteIntoMenuItem" mnemonicParsing="false" text="%menu.title.paste.into" />
+                        <MenuItem fx:id="duplicateMenuItem" mnemonicParsing="false" text="%menu.title.duplicate" />
+                        <MenuItem fx:id="deleteMenuItem" mnemonicParsing="false" text="%menu.title.delete" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="selectAllMenuItem" mnemonicParsing="false" text="%menu.title.select.all" />
+                        <MenuItem fx:id="selectNoneMenuItem" mnemonicParsing="false" text="%menu.title.select.none" />
+                        <MenuItem fx:id="selectParentMenuItem" mnemonicParsing="false" text="%menu.title.select.parent" />
+                        <MenuItem fx:id="selectNextMenuItem" mnemonicParsing="false" text="%menu.title.select.next" />
+                        <MenuItem fx:id="selectPreviousMenuItem" mnemonicParsing="false" text="%menu.title.select.previous" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="trimMenuItem" mnemonicParsing="false" text="%menu.title.trim" />
+                    </items>
+                </Menu>
+                <Menu mnemonicParsing="false" text="%menu.title.view">
+                    <items>
+                        <MenuItem fx:id="gotoContentMenuItem" mnemonicParsing="false" text="%menu.title.content" />
+                        <MenuItem fx:id="gotoPropertiesMenuItem" mnemonicParsing="false" text="%menu.title.properties" />
+                        <MenuItem fx:id="gotoLayoutMenuItem" mnemonicParsing="false" text="%menu.title.layout" />
+                        <MenuItem fx:id="gotoCodeMenuItem" mnemonicParsing="false" text="%menu.title.code" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="toggleLibraryPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.library.panel" />
+                        <MenuItem fx:id="toggleHierarchyPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.document.panel" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="toggleCSSPanelMenuItem" mnemonicParsing="false" text="%menu.title.show.bottom.panel" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="toggleLeftPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.left.panel" />
+                        <MenuItem fx:id="toggleRightPanelMenuItem" mnemonicParsing="false" text="%menu.title.hide.right.panel" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="toggleOutlinesMenuItem" mnemonicParsing="false" text="%menu.title.show.outlines" />
+                        <MenuItem fx:id="toggleSampleDataMenuItem" mnemonicParsing="false" text="%menu.title.show.sample.data" />
+                        <MenuItem fx:id="toggleAlignmentGuidesMenuItem" mnemonicParsing="false" text="%menu.title.disable.guides" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <Menu fx:id="zoomMenu" mnemonicParsing="false" text="%menu.title.zoom" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="showSampleControllerMenuItem" mnemonicParsing="false" text="%menu.title.show.sample.controller.skeleton" />
+                    </items>
+                </Menu>
+                <Menu fx:id="insertMenu" mnemonicParsing="false" text="%menu.title.insert" />
+                <Menu mnemonicParsing="false" text="%menu.title.modify">
+                    <items>
+                        <MenuItem fx:id="fitToParentMenuItem" mnemonicParsing="false" text="%menu.title.fit" />
+                        <MenuItem fx:id="useComputedSizesMenuItem" mnemonicParsing="false" text="%menu.title.use.computed.sizes" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <Menu mnemonicParsing="false" text="%menu.title.grid">
+                            <items>
+                                <MenuItem fx:id="selectNextRowMenuItem" mnemonicParsing="false" text="%menu.title.grid.select.next.row" />
+                                <MenuItem fx:id="selectNextColumnMenuItem" mnemonicParsing="false" text="%menu.title.grid.select.next.column" />
+                                <SeparatorMenuItem mnemonicParsing="false" />
+                                <MenuItem fx:id="moveRowAboveMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.row.above" />
+                                <MenuItem fx:id="moveRowBelowMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.row.below" />
+                                <MenuItem fx:id="moveColumnBeforeMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.column.before" />
+                                <MenuItem fx:id="moveColumnAfterMenuItem" mnemonicParsing="false" text="%menu.title.grid.move.column.after" />
+                                <SeparatorMenuItem mnemonicParsing="false" />
+                                <MenuItem fx:id="addRowAboveMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.row.above" />
+                                <MenuItem fx:id="addRowBelowMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.row.below" />
+                                <MenuItem fx:id="addColumnBeforeMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.column.before" />
+                                <MenuItem fx:id="addColumnAfterMenuItem" mnemonicParsing="false" text="%menu.title.grid.add.column.after" />
+                                <SeparatorMenuItem mnemonicParsing="false" />
+                                <MenuItem fx:id="increaseRowSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.increase.row.span" />
+                                <MenuItem fx:id="decreaseRowSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.decrease.row.span" />
+                                <MenuItem fx:id="increaseColumnSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.increase.column.span" />
+                                <MenuItem fx:id="decreaseColumnSpanMenuItem" mnemonicParsing="false" text="%menu.title.grid.decrease.column.span" />
+                            </items>
+                        </Menu>
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <Menu fx:id="addEffectMenu" mnemonicParsing="false" text="%menu.title.add.effect" />
+                        <Menu fx:id="addPopupControlMenu" mnemonicParsing="false" text="%menu.title.add.popup" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="editIncludedFileMenuItem" mnemonicParsing="false" text="%menu.title.edit.included.default" />
+                        <MenuItem fx:id="revealIncludedFileMenuItem" mnemonicParsing="false" text="%menu.title.reveal.included.default" />
+                    </items>
+                </Menu>
+                <Menu mnemonicParsing="false" text="%menu.title.arrange">
+                    <items>
+                        <MenuItem fx:id="bringToFrontMenuItem" mnemonicParsing="false" text="%menu.title.front" />
+                        <MenuItem fx:id="sendToBackMenuItem" mnemonicParsing="false" text="%menu.title.back" />
+                        <MenuItem fx:id="bringForwardMenuItem" mnemonicParsing="false" text="%menu.title.forward" />
+                        <MenuItem fx:id="sendBackwardMenuItem" mnemonicParsing="false" text="%menu.title.backward" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <Menu mnemonicParsing="false" text="%menu.title.wrap">
+                            <items>
+                                <MenuItem fx:id="wrapInAnchorPaneMenuItem" mnemonicParsing="false" text="AnchorPane" />
+                                <MenuItem fx:id="wrapInGridPaneMenuItem" mnemonicParsing="false" text="GridPane" />
+                                <MenuItem fx:id="wrapInHBoxMenuItem" mnemonicParsing="false" text="HBox" />
+                                <MenuItem fx:id="wrapInPaneMenuItem" mnemonicParsing="false" text="Pane" />
+                                <MenuItem fx:id="wrapInScrollPaneMenuItem" mnemonicParsing="false" text="ScrollPane" />
+                                <MenuItem fx:id="wrapInSplitPaneMenuItem" mnemonicParsing="false" text="SplitPane" />
+                                <MenuItem fx:id="wrapInStackPaneMenuItem" mnemonicParsing="false" text="StackPane" />
+                                <MenuItem fx:id="wrapInTabPaneMenuItem" mnemonicParsing="false" text="TabPane" />
+                                <MenuItem fx:id="wrapInTitledPaneMenuItem" mnemonicParsing="false" text="TitledPane" />
+                                <MenuItem fx:id="wrapInToolBarMenuItem" mnemonicParsing="false" text="ToolBar" />
+                                <MenuItem fx:id="wrapInVBoxMenuItem" mnemonicParsing="false" text="VBox" />
+                                <MenuItem fx:id="wrapInGroupMenuItem" mnemonicParsing="false" text="Group" />
+                            </items>
+                        </Menu>
+                        <MenuItem fx:id="unwrapMenuItem" mnemonicParsing="false" text="%menu.title.unwrap" />
+                    </items>
+                </Menu>
+                <Menu mnemonicParsing="false" text="%menu.title.preview">
+                    <items>
+                        <MenuItem fx:id="showPreviewMenuItem" mnemonicParsing="false" text="%menu.title.show.preview" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <MenuItem fx:id="chooseBackgroundColorMenuItem" mnemonicParsing="false" text="%menu.title.choose.background.color" />
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                        <Menu mnemonicParsing="false" text="%menu.title.theme">
+                            <items>
+                                <RadioMenuItem fx:id="modenaThemeMenuItem" mnemonicParsing="false" text="%menu.title.theme.modena" />
+                                <RadioMenuItem fx:id="caspianThemeMenuItem" mnemonicParsing="false" text="%menu.title.theme.caspian" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" />
+                            </items>
+                        </Menu>
+                        <Menu mnemonicParsing="false" text="%menu.title.scene.stylesheets">
+                            <items>
+                                <MenuItem fx:id="addSceneStyleSheetMenuItem" mnemonicParsing="false" text="%menu.title.add.stylesheet" />
+                                <Menu fx:id="removeSceneStyleSheetMenu" mnemonicParsing="false" text="%menu.title.remove.stylesheet">
+                                    <items>
+                                        <MenuItem disable="true" mnemonicParsing="false" text="%scenestylesheet.none" />
+                                    </items>
+                                </Menu>
+                                <Menu fx:id="openSceneStyleSheetMenu" mnemonicParsing="false" text="%menu.title.open.stylesheet">
+                                    <items>
+                                        <MenuItem disable="true" mnemonicParsing="false" text="%scenestylesheet.none" />
+                                    </items>
+                                </Menu>
+                            </items>
+                        </Menu>
+                        <Menu mnemonicParsing="false" text="%menu.title.internationalization">
+                            <items>
+                                <MenuItem fx:id="setResourceMenuItem" mnemonicParsing="false" text="%menu.title.set.resource" />
+                                <MenuItem fx:id="removeResourceMenuItem" mnemonicParsing="false" text="%menu.title.remove.resource" />
+                                <MenuItem fx:id="revealResourceMenuItem" mnemonicParsing="false" text="%menu.title.reveal.resource" />
+                            </items>
+                        </Menu>
+                    </items>
+                </Menu>
+                <Menu fx:id="windowMenu" mnemonicParsing="false" text="%menu.title.window">
+                    <items>
+                        <SeparatorMenuItem mnemonicParsing="false" />
+                    </items>
+                </Menu>
+                <Menu mnemonicParsing="false" text="%menu.title.help">
+                    <items>
+                        <MenuItem fx:id="helpMenuItem" mnemonicParsing="false" text="%menu.title.scene.builder.help" />
+                        <MenuItem fx:id="aboutMenuItem" mnemonicParsing="false" text="%menu.title.about" />
+                    </items>
+                </Menu>
+            </menus>
+        </MenuBar>
+    </children>
 </StackPane>
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBarController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/menubar/MenuBarController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -36,6 +36,8 @@
 import com.oracle.javafx.scenebuilder.app.SceneBuilderApp;
 import com.oracle.javafx.scenebuilder.app.SceneBuilderApp.ApplicationControlAction;
 import com.oracle.javafx.scenebuilder.app.i18n.I18N;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesController;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController.ControlAction;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController.EditAction;
@@ -68,6 +70,7 @@
 import javafx.scene.control.MenuBar;
 import javafx.scene.control.MenuItem;
 import javafx.scene.control.RadioMenuItem;
+import javafx.scene.control.SeparatorMenuItem;
 import javafx.scene.effect.Effect;
 import javafx.scene.input.KeyCharacterCombination;
 import javafx.scene.input.KeyCode;
@@ -76,7 +79,7 @@
 import javafx.scene.layout.StackPane;
 
 /**
- * 
+ *
  */
 public class MenuBarController {
 
@@ -84,125 +87,225 @@
     private final DocumentWindowController documentWindowController;
     // This member is null when this MenuBarController is used for
     // managing the menu bar passed to MenuBarSkin.setDefaultSystemMenu().
-    
-    @FXML private MenuBar menuBar;
-    @FXML private Menu insertMenu;
-    @FXML private Menu addEffectMenu;
-    @FXML private Menu fileMenu; // Useless as soon as Preferences menu item is implemented
-    @FXML private Menu windowMenu;
-    
+
+    @FXML
+    private MenuBar menuBar;
+    @FXML
+    private Menu insertMenu;
+    @FXML
+    private Menu addEffectMenu;
+    @FXML
+    private Menu fileMenu; // Useless as soon as Preferences menu item is implemented
+    @FXML
+    private Menu windowMenu;
+
     // File
-    @FXML private MenuItem newMenuItem;
-    @FXML private MenuItem newAlertDialogMenuItem;
-    @FXML private MenuItem newAlertDialogCssMenuItem;
-    @FXML private MenuItem newAlertDialogI18nMenuItem;
-    @FXML private MenuItem newBasicAppMenuItem;
-    @FXML private MenuItem newBasicAppCssMenuItem;
-    @FXML private MenuItem newBasicAppI18nMenuItem;
-    @FXML private MenuItem newComplexAppMenuItem;
-    @FXML private MenuItem newComplexAppCssMenuItem;
-    @FXML private MenuItem newComplexAppI18nMenuItem;
-    @FXML private MenuItem openMenuItem;
-    @FXML private MenuItem saveMenuItem;
-    @FXML private MenuItem saveAsMenuItem;
-    @FXML private MenuItem revertMenuItem;
-    @FXML private MenuItem closeMenuItem;
-    @FXML private MenuItem revealMenuItem;
-    @FXML private MenuItem showPreferencesMenuItem;
-    @FXML private MenuItem separatorAbovePreferencesMenuItem; // Useless as soon as Preferences menu item is implemented
-    @FXML private MenuItem exitMenuItem;
-    
+    @FXML
+    private MenuItem newMenuItem;
+    @FXML
+    private MenuItem newAlertDialogMenuItem;
+    @FXML
+    private MenuItem newAlertDialogCssMenuItem;
+    @FXML
+    private MenuItem newAlertDialogI18nMenuItem;
+    @FXML
+    private MenuItem newBasicAppMenuItem;
+    @FXML
+    private MenuItem newBasicAppCssMenuItem;
+    @FXML
+    private MenuItem newBasicAppI18nMenuItem;
+    @FXML
+    private MenuItem newComplexAppMenuItem;
+    @FXML
+    private MenuItem newComplexAppCssMenuItem;
+    @FXML
+    private MenuItem newComplexAppI18nMenuItem;
+    @FXML
+    private MenuItem openMenuItem;
+    @FXML
+    private Menu openRecentMenu;
+    @FXML
+    private MenuItem saveMenuItem;
+    @FXML
+    private MenuItem saveAsMenuItem;
+    @FXML
+    private MenuItem revertMenuItem;
+    @FXML
+    private MenuItem closeMenuItem;
+    @FXML
+    private MenuItem revealMenuItem;
+    @FXML
+    private MenuItem showPreferencesMenuItem;
+    @FXML
+    private MenuItem separatorAbovePreferencesMenuItem; // Useless as soon as Preferences menu item is implemented
+    @FXML
+    private MenuItem exitMenuItem;
+
     // Edit
-    @FXML private MenuItem undoMenuItem;
-    @FXML private MenuItem redoMenuItem;
-    @FXML private MenuItem copyMenuItem;
-    @FXML private MenuItem cutMenuItem;
-    @FXML private MenuItem pasteMenuItem;
-    @FXML private MenuItem pasteIntoMenuItem;
-    @FXML private MenuItem duplicateMenuItem;
-    @FXML private MenuItem deleteMenuItem;
-    @FXML private MenuItem selectAllMenuItem;
-    @FXML private MenuItem selectNoneMenuItem;
-    @FXML private MenuItem selectParentMenuItem;
-    @FXML private MenuItem selectNextMenuItem;
-    @FXML private MenuItem selectPreviousMenuItem;
-    @FXML private MenuItem trimMenuItem;
-    
+    @FXML
+    private MenuItem undoMenuItem;
+    @FXML
+    private MenuItem redoMenuItem;
+    @FXML
+    private MenuItem copyMenuItem;
+    @FXML
+    private MenuItem cutMenuItem;
+    @FXML
+    private MenuItem pasteMenuItem;
+    @FXML
+    private MenuItem pasteIntoMenuItem;
+    @FXML
+    private MenuItem duplicateMenuItem;
+    @FXML
+    private MenuItem deleteMenuItem;
+    @FXML
+    private MenuItem selectAllMenuItem;
+    @FXML
+    private MenuItem selectNoneMenuItem;
+    @FXML
+    private MenuItem selectParentMenuItem;
+    @FXML
+    private MenuItem selectNextMenuItem;
+    @FXML
+    private MenuItem selectPreviousMenuItem;
+    @FXML
+    private MenuItem trimMenuItem;
+
     // View
-    @FXML private MenuItem gotoContentMenuItem;
-    @FXML private MenuItem gotoPropertiesMenuItem;
-    @FXML private MenuItem gotoLayoutMenuItem;
-    @FXML private MenuItem gotoCodeMenuItem;
-    @FXML private MenuItem toggleLibraryPanelMenuItem;
-    @FXML private MenuItem toggleHierarchyPanelMenuItem;
-    @FXML private MenuItem toggleCSSPanelMenuItem;
-    @FXML private MenuItem toggleLeftPanelMenuItem;
-    @FXML private MenuItem toggleRightPanelMenuItem;
-    @FXML private MenuItem toggleOutlinesMenuItem;
-    @FXML private MenuItem toggleSampleDataMenuItem;
-    @FXML private MenuItem toggleAlignmentGuidesMenuItem;
-    @FXML private MenuItem showSampleControllerMenuItem;
-    @FXML private Menu zoomMenu;
-    
+    @FXML
+    private MenuItem gotoContentMenuItem;
+    @FXML
+    private MenuItem gotoPropertiesMenuItem;
+    @FXML
+    private MenuItem gotoLayoutMenuItem;
+    @FXML
+    private MenuItem gotoCodeMenuItem;
+    @FXML
+    private MenuItem toggleLibraryPanelMenuItem;
+    @FXML
+    private MenuItem toggleHierarchyPanelMenuItem;
+    @FXML
+    private MenuItem toggleCSSPanelMenuItem;
+    @FXML
+    private MenuItem toggleLeftPanelMenuItem;
+    @FXML
+    private MenuItem toggleRightPanelMenuItem;
+    @FXML
+    private MenuItem toggleOutlinesMenuItem;
+    @FXML
+    private MenuItem toggleSampleDataMenuItem;
+    @FXML
+    private MenuItem toggleAlignmentGuidesMenuItem;
+    @FXML
+    private MenuItem showSampleControllerMenuItem;
+    @FXML
+    private Menu zoomMenu;
+
     // Modify
-    @FXML private MenuItem fitToParentMenuItem;
-    @FXML private MenuItem useComputedSizesMenuItem;
-    @FXML private MenuItem selectNextRowMenuItem;
-    @FXML private MenuItem selectNextColumnMenuItem;
-    @FXML private MenuItem moveRowAboveMenuItem;
-    @FXML private MenuItem moveRowBelowMenuItem;
-    @FXML private MenuItem moveColumnBeforeMenuItem;
-    @FXML private MenuItem moveColumnAfterMenuItem;
-    @FXML private MenuItem addRowAboveMenuItem;
-    @FXML private MenuItem addRowBelowMenuItem;
-    @FXML private MenuItem addColumnBeforeMenuItem;
-    @FXML private MenuItem addColumnAfterMenuItem;
-    @FXML private MenuItem increaseRowSpanMenuItem;
-    @FXML private MenuItem decreaseRowSpanMenuItem;
-    @FXML private MenuItem increaseColumnSpanMenuItem;
-    @FXML private MenuItem decreaseColumnSpanMenuItem;
-    @FXML private MenuItem editIncludedFileMenuItem;
-    @FXML private MenuItem revealIncludedFileMenuItem;
-    
+    @FXML
+    private MenuItem fitToParentMenuItem;
+    @FXML
+    private MenuItem useComputedSizesMenuItem;
+    @FXML
+    private MenuItem selectNextRowMenuItem;
+    @FXML
+    private MenuItem selectNextColumnMenuItem;
+    @FXML
+    private MenuItem moveRowAboveMenuItem;
+    @FXML
+    private MenuItem moveRowBelowMenuItem;
+    @FXML
+    private MenuItem moveColumnBeforeMenuItem;
+    @FXML
+    private MenuItem moveColumnAfterMenuItem;
+    @FXML
+    private MenuItem addRowAboveMenuItem;
+    @FXML
+    private MenuItem addRowBelowMenuItem;
+    @FXML
+    private MenuItem addColumnBeforeMenuItem;
+    @FXML
+    private MenuItem addColumnAfterMenuItem;
+    @FXML
+    private MenuItem increaseRowSpanMenuItem;
+    @FXML
+    private MenuItem decreaseRowSpanMenuItem;
+    @FXML
+    private MenuItem increaseColumnSpanMenuItem;
+    @FXML
+    private MenuItem decreaseColumnSpanMenuItem;
+    @FXML
+    private MenuItem editIncludedFileMenuItem;
+    @FXML
+    private MenuItem revealIncludedFileMenuItem;
+
     // Arrange
-    @FXML private MenuItem bringToFrontMenuItem;
-    @FXML private MenuItem sendToBackMenuItem;
-    @FXML private MenuItem bringForwardMenuItem;
-    @FXML private MenuItem sendBackwardMenuItem;
-    @FXML private MenuItem wrapInAnchorPaneMenuItem;
-    @FXML private MenuItem wrapInGridPaneMenuItem;
-    @FXML private MenuItem wrapInHBoxMenuItem;
-    @FXML private MenuItem wrapInPaneMenuItem;
-    @FXML private MenuItem wrapInScrollPaneMenuItem;
-    @FXML private MenuItem wrapInSplitPaneMenuItem;
-    @FXML private MenuItem wrapInStackPaneMenuItem;
-    @FXML private MenuItem wrapInTabPaneMenuItem;
-    @FXML private MenuItem wrapInTitledPaneMenuItem;
-    @FXML private MenuItem wrapInToolBarMenuItem;
-    @FXML private MenuItem wrapInVBoxMenuItem;
-    @FXML private MenuItem wrapInGroupMenuItem;
-    @FXML private MenuItem unwrapMenuItem;
+    @FXML
+    private MenuItem bringToFrontMenuItem;
+    @FXML
+    private MenuItem sendToBackMenuItem;
+    @FXML
+    private MenuItem bringForwardMenuItem;
+    @FXML
+    private MenuItem sendBackwardMenuItem;
+    @FXML
+    private MenuItem wrapInAnchorPaneMenuItem;
+    @FXML
+    private MenuItem wrapInGridPaneMenuItem;
+    @FXML
+    private MenuItem wrapInHBoxMenuItem;
+    @FXML
+    private MenuItem wrapInPaneMenuItem;
+    @FXML
+    private MenuItem wrapInScrollPaneMenuItem;
+    @FXML
+    private MenuItem wrapInSplitPaneMenuItem;
+    @FXML
+    private MenuItem wrapInStackPaneMenuItem;
+    @FXML
+    private MenuItem wrapInTabPaneMenuItem;
+    @FXML
+    private MenuItem wrapInTitledPaneMenuItem;
+    @FXML
+    private MenuItem wrapInToolBarMenuItem;
+    @FXML
+    private MenuItem wrapInVBoxMenuItem;
+    @FXML
+    private MenuItem wrapInGroupMenuItem;
+    @FXML
+    private MenuItem unwrapMenuItem;
 
     // Preview
-    @FXML private MenuItem showPreviewMenuItem;
-    @FXML private MenuItem modenaThemeMenuItem;
-    @FXML private MenuItem caspianThemeMenuItem;
-    @FXML private MenuItem chooseBackgroundColorMenuItem;
-    @FXML private MenuItem addSceneStyleSheetMenuItem;
-    @FXML private Menu removeSceneStyleSheetMenu;
-    @FXML private Menu openSceneStyleSheetMenu;
-    @FXML private MenuItem setResourceMenuItem;
-    @FXML private MenuItem removeResourceMenuItem;
-    @FXML private MenuItem revealResourceMenuItem;
-            
-    
+    @FXML
+    private MenuItem showPreviewMenuItem;
+    @FXML
+    private MenuItem modenaThemeMenuItem;
+    @FXML
+    private MenuItem caspianThemeMenuItem;
+    @FXML
+    private MenuItem chooseBackgroundColorMenuItem;
+    @FXML
+    private MenuItem addSceneStyleSheetMenuItem;
+    @FXML
+    private Menu removeSceneStyleSheetMenu;
+    @FXML
+    private Menu openSceneStyleSheetMenu;
+    @FXML
+    private MenuItem setResourceMenuItem;
+    @FXML
+    private MenuItem removeResourceMenuItem;
+    @FXML
+    private MenuItem revealResourceMenuItem;
+
     // Window
-    
     // Help
-    @FXML private MenuItem helpMenuItem;
-    @FXML private MenuItem aboutMenuItem;
-    
+    @FXML
+    private MenuItem helpMenuItem;
+    @FXML
+    private MenuItem aboutMenuItem;
+
     private static final KeyCombination.Modifier modifier;
+
     static {
         if (EditorPlatform.IS_MAC) {
             modifier = KeyCombination.META_DOWN;
@@ -216,10 +319,9 @@
         this.documentWindowController = documentWindowController;
         debugMenuController = new DebugMenuController(documentWindowController);
     }
-    
-    
+
     public MenuBar getMenuBar() {
-        
+
         if (menuBar == null) {
             final URL fxmlURL = MenuBarController.class.getResource("MenuBar.fxml"); //NOI18N
             final FXMLLoader loader = new FXMLLoader();
@@ -236,10 +338,10 @@
                 throw new RuntimeException("Failed to load " + fxmlURL.getFile(), x); //NOI18N
             }
         }
-        
+
         return menuBar;
     }
-    
+
     public void setDebugMenuVisible(boolean visible) {
         if (isDebugMenuVisible() != visible) {
             if (visible) {
@@ -249,25 +351,23 @@
             }
         }
     }
-    
+
     public boolean isDebugMenuVisible() {
         return menuBar.getMenus().contains(debugMenuController.getMenu());
     }
-    
+
     /*
      * Private
      */
-    
-    
     private void controllerDidLoadFxml() {
-        
+
         assert menuBar != null;
         assert menuBar.getParent() instanceof StackPane;
         assert insertMenu != null;
         assert addEffectMenu != null;
         assert fileMenu != null;
         assert windowMenu != null;
-       
+
         assert newMenuItem != null;
         assert newAlertDialogMenuItem != null;
         assert newAlertDialogCssMenuItem != null;
@@ -279,6 +379,7 @@
         assert newComplexAppCssMenuItem != null;
         assert newComplexAppI18nMenuItem != null;
         assert openMenuItem != null;
+        assert openRecentMenu != null;
         assert saveMenuItem != null;
         assert saveAsMenuItem != null;
         assert revertMenuItem != null;
@@ -302,7 +403,7 @@
         assert selectNextMenuItem != null;
         assert selectPreviousMenuItem != null;
         assert trimMenuItem != null;
-    
+
         assert gotoContentMenuItem != null;
         assert gotoPropertiesMenuItem != null;
         assert gotoLayoutMenuItem != null;
@@ -318,7 +419,7 @@
         assert showSampleControllerMenuItem != null;
         assert zoomMenu != null;
         assert zoomMenu.getItems().isEmpty();
-    
+
         assert fitToParentMenuItem != null;
         assert useComputedSizesMenuItem != null;
         assert selectNextRowMenuItem != null;
@@ -366,7 +467,7 @@
         assert setResourceMenuItem != null;
         assert removeResourceMenuItem != null;
         assert revealResourceMenuItem != null;
-       
+
         assert helpMenuItem != null;
         assert aboutMenuItem != null;
 
@@ -375,10 +476,9 @@
          * in a StackPane. This stack pane is useless now.
          * So we unwrap the menu bar and make it the panel root.
          */
-        final StackPane rootStackPane = (StackPane)menuBar.getParent();
+        final StackPane rootStackPane = (StackPane) menuBar.getParent();
         rootStackPane.getChildren().remove(menuBar);
-        
-        
+
         /*
          * On Mac, move the menu bar on the desktop and remove the Quit item
          * from the File menu
@@ -387,7 +487,7 @@
             menuBar.setUseSystemMenuBar(true);
             exitMenuItem.getParentMenu().getItems().remove(exitMenuItem);
         }
-        
+
         /*
          * Setup title of the Reveal menu item according the underlying o/s.
          */
@@ -401,7 +501,7 @@
             revealMenuKey = "menu.title.reveal.linux";
         }
         revealMenuItem.setText(I18N.getString(revealMenuKey));
-        
+
         /*
          * File menu
          */
@@ -418,6 +518,12 @@
         newComplexAppI18nMenuItem.setUserData(new ApplicationControlActionController(ApplicationControlAction.NEW_COMPLEX_APPLICATION_I18N));
         openMenuItem.setUserData(new ApplicationControlActionController(ApplicationControlAction.OPEN_FILE));
         openMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.O, modifier));
+        openRecentMenu.setOnShowing(new EventHandler<Event>() {
+            @Override
+            public void handle(Event t) {
+                updateOpenRecentMenuItems();
+            }
+        });
         saveMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.SAVE_FILE));
         saveMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.S, modifier));
         saveAsMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.SAVE_AS_FILE));
@@ -464,7 +570,7 @@
         selectNextMenuItem.setUserData(new ControlActionController(ControlAction.SELECT_NEXT));
         selectPreviousMenuItem.setUserData(new ControlActionController(ControlAction.SELECT_PREVIOUS));
         trimMenuItem.setUserData(new EditActionController(EditAction.TRIM));
-        
+
         /*
          * View menu
          */
@@ -476,22 +582,22 @@
         gotoLayoutMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.DIGIT2, modifier));
         gotoCodeMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.GOTO_CODE));
         gotoCodeMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.DIGIT3, modifier));
-       
+
         toggleLibraryPanelMenuItem.setUserData(
-        new DocumentControlActionController(DocumentControlAction.TOGGLE_LIBRARY_PANEL) {
-            @Override
-            public String getTitle() {
-                final String titleKey;
-                if (documentWindowController == null) {
-                    titleKey = "menu.title.hide.library.panel";
-                } else if (documentWindowController.isLibraryPanelVisible()) {
-                    titleKey = "menu.title.hide.library.panel";
-                } else {
-                    titleKey = "menu.title.show.library.panel";
-                }
-                return I18N.getString(titleKey);
-            }
-        });
+                new DocumentControlActionController(DocumentControlAction.TOGGLE_LIBRARY_PANEL) {
+                    @Override
+                    public String getTitle() {
+                        final String titleKey;
+                        if (documentWindowController == null) {
+                            titleKey = "menu.title.hide.library.panel";
+                        } else if (documentWindowController.isLibraryPanelVisible()) {
+                            titleKey = "menu.title.hide.library.panel";
+                        } else {
+                            titleKey = "menu.title.show.library.panel";
+                        }
+                        return I18N.getString(titleKey);
+                    }
+                });
         toggleLibraryPanelMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.DIGIT4, modifier));
         toggleHierarchyPanelMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.TOGGLE_HIERARCHY_PANEL) {
             @Override
@@ -576,22 +682,21 @@
         });
 //        showSampleControllerMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.GOTO_CONTENT));
         updateZoomMenu();
-        
+
         /*
          * Insert menu
          */
         updateInsertMenu();
         if (documentWindowController != null) {
             this.documentWindowController.getEditorController().libraryProperty().addListener(
-                new ChangeListener<Library>() {
-                    @Override
-                    public void changed(ObservableValue<? extends Library> ov, Library t, Library t1) {
-                        updateInsertMenu();
-                    }
-                });
+                    new ChangeListener<Library>() {
+                        @Override
+                        public void changed(ObservableValue<? extends Library> ov, Library t, Library t1) {
+                            updateInsertMenu();
+                        }
+                    });
         }
-        
-       
+
         /*
          * Modify menu
          */
@@ -614,10 +719,10 @@
         increaseColumnSpanMenuItem.setUserData(new EditActionController(EditAction.INCREASE_COLUMN_SPAN));
         decreaseColumnSpanMenuItem.setUserData(new EditActionController(EditAction.DECREASE_COLUMN_SPAN));
         editIncludedFileMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.EDIT_INCLUDED_FILE));
-        
+
         // Add Effect submenu
         updateAddEffectMenu();
-        
+
         /*
          * Arrange menu
          */
@@ -661,15 +766,17 @@
         unwrapMenuItem.setUserData(new EditActionController(EditAction.UNWRAP));
         unwrapMenuItem.setAccelerator(
                 new KeyCodeCombination(KeyCode.U, modifier));
-        
+
         /*
          * Preview menu
          */
         showPreviewMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.SHOW_PREVIEW_WINDOW));
         showPreviewMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.P, modifier));
+        chooseBackgroundColorMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.CHOOSE_BACKGROUND_COLOR));
+        chooseBackgroundColorMenuItem.setDisable(true);
         caspianThemeMenuItem.setUserData(new SetThemeActionController(EditorPlatform.Theme.CASPIAN));
         modenaThemeMenuItem.setUserData(new SetThemeActionController(EditorPlatform.Theme.MODENA));
-        
+
         addSceneStyleSheetMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.ADD_SCENE_STYLE_SHEET));
         updateOpenAndRemoveSceneStyleSheetMenus();
         if (documentWindowController != null) {
@@ -685,7 +792,7 @@
                 }
             });
         }
-        
+
         setResourceMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.SET_RESOURCE));
         removeResourceMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.REMOVE_RESOURCE) {
             @Override
@@ -694,10 +801,10 @@
                         || documentWindowController.getEditorController().getResource() == null) {
                     return false;
                 }
-                
+
                 return true;
             }
-            
+
             @Override
             public String getTitle() {
                 String title = I18N.getString("menu.title.remove.resource");
@@ -706,7 +813,7 @@
                     title = I18N.getString("menu.title.remove.resource.with.file",
                             documentWindowController.getEditorController().getResource().getName());
                 }
-                
+
                 return title;
             }
         });
@@ -717,10 +824,10 @@
                         || documentWindowController.getEditorController().getResource() == null) {
                     return false;
                 }
-                
+
                 return true;
             }
-            
+
             @Override
             public String getTitle() {
                 String title = I18N.getString("menu.title.reveal.resource");
@@ -729,22 +836,21 @@
                     title = I18N.getString("menu.title.reveal.resource.with.file",
                             documentWindowController.getEditorController().getResource().getName());
                 }
-                
+
                 return title;
             }
         });
 
-        
         /*
          * Window menu : it is setup after the other menus
          */
-        
         /*
          * Help menu
          */
         aboutMenuItem.setUserData(new ApplicationControlActionController(ApplicationControlAction.ABOUT));
-        
-        
+        helpMenuItem.setUserData(new DocumentControlActionController(DocumentControlAction.HELP));
+        helpMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F1));
+
         /*
          * Put some generic handlers on each Menu and MenuItem.
          * For Window menu, they are overriden with specific handlers.
@@ -753,18 +859,11 @@
             setupMenuItemHandlers(m);
         }
         windowMenu.setOnMenuValidation(onWindowMenuValidationHandler);
-        
-        /*
-         * Until Preference menu is implemented, we remove it (see DTL-5854).
-         */
-        fileMenu.getItems().remove(separatorAbovePreferencesMenuItem);
-        fileMenu.getItems().remove(showPreferencesMenuItem);
     }
-    
+
     /*
      * Generic menu and item handlers
      */
-    
     private void setupMenuItemHandlers(MenuItem i) {
         if (i instanceof Menu) {
             final Menu m = (Menu) i;
@@ -776,23 +875,23 @@
             i.setOnAction(onActionEventHandler);
         }
     }
-    
-    private final EventHandler<Event> onMenuValidationEventHandler 
+
+    private final EventHandler<Event> onMenuValidationEventHandler
             = new EventHandler<Event>() {
                 @Override
                 public void handle(Event t) {
                     assert t.getSource() instanceof Menu;
-                    handleOnMenuValidation((Menu)t.getSource());
+                    handleOnMenuValidation((Menu) t.getSource());
                 }
             };
-    
+
     private void handleOnMenuValidation(Menu menu) {
         for (MenuItem i : menu.getItems()) {
             final boolean disable, selected;
             final String title;
             if (i.getUserData() instanceof MenuItemController) {
-                final MenuItemController c = (MenuItemController)i.getUserData();
-                disable = ! c.canPerform();
+                final MenuItemController c = (MenuItemController) i.getUserData();
+                disable = !c.canPerform();
                 title = c.getTitle();
                 selected = c.isSelected();
             } else {
@@ -811,43 +910,77 @@
                 i.setText(title);
             }
             if (i instanceof RadioMenuItem) {
-                final RadioMenuItem ri = (RadioMenuItem)i;
+                final RadioMenuItem ri = (RadioMenuItem) i;
                 ri.setSelected(selected);
             }
         }
     }
-    
-    private final EventHandler<ActionEvent> onActionEventHandler 
+
+    private final EventHandler<ActionEvent> onActionEventHandler
             = new EventHandler<ActionEvent>() {
                 @Override
                 public void handle(ActionEvent t) {
                     assert t.getSource() instanceof MenuItem;
-                    handleOnActionMenu((MenuItem)t.getSource());
+                    handleOnActionMenu((MenuItem) t.getSource());
                 }
             };
-    
+
     private void handleOnActionMenu(MenuItem i) {
         assert i.getUserData() instanceof MenuItemController;
-        final MenuItemController c = (MenuItemController)i.getUserData();
+        final MenuItemController c = (MenuItemController) i.getUserData();
         c.perform();
     }
-    
+
     /*
      * Private (zoom menu)
      */
-    
     private void updateZoomMenu() {
         final double[] scalingTable = {0.25, 0.50, 0.75, 1.00, 1.50, 2.0, 4.0};
-        
+
         for (int i = 0; i < scalingTable.length; i++) {
             final double scaling = scalingTable[i];
-            final String title = "%" + (int)(scaling * 100); //NOI18N
+            final String title = "%" + (int) (scaling * 100); //NOI18N
             final RadioMenuItem mi = new RadioMenuItem(title);
             mi.setUserData(new SetZoomActionController(scaling));
             zoomMenu.getItems().add(mi);
         }
     }
-    
+
+    private void updateOpenRecentMenuItems() {
+
+        final List<MenuItem> menuItems = new ArrayList<>();
+
+        final PreferencesController pc = PreferencesController.getSingleton();
+        final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+        final List<String> recentItems = recordGlobal.getRecentItems();
+
+        final MenuItem clearMenuItem = new MenuItem(I18N.getString("menu.title.open.recent.clear"));
+        clearMenuItem.setOnAction(new ClearOpenRecentHandler());
+
+        if (recentItems.isEmpty()) {
+            clearMenuItem.setDisable(true);
+            menuItems.add(clearMenuItem);
+        } else {
+            clearMenuItem.setDisable(false);
+            for (String recentItem : recentItems) {
+                final MenuItem mi = new MenuItem(recentItem);
+                mi.setOnAction(new EventHandler<ActionEvent>() {
+
+                    @Override
+                    public void handle(ActionEvent t) {
+                        final File file = new File(recentItem);
+                        SceneBuilderApp.getSingleton().performOpenRecent(documentWindowController, file);
+                    }
+                });
+                menuItems.add(mi);
+            }
+            menuItems.add(new SeparatorMenuItem());
+            menuItems.add(clearMenuItem);
+        }
+
+        openRecentMenu.getItems().setAll(menuItems);
+    }
+
     private void updateOpenAndRemoveSceneStyleSheetMenus() {
         assert removeSceneStyleSheetMenu != null;
 
@@ -857,7 +990,7 @@
             if (sceneStyleSheets != null) {
                 removeSceneStyleSheetMenu.getItems().clear();
                 openSceneStyleSheetMenu.getItems().clear();
-                
+
                 if (sceneStyleSheets.size() == 0) {
                     MenuItem mi = new MenuItem(I18N.getString("scenestylesheet.none"));
                     mi.setDisable(true);
@@ -878,23 +1011,22 @@
             }
         }
     }
-    
+
     /*
      * Private (insert menu)
      */
-    
     private void updateInsertMenu() {
         assert insertMenu != null;
-        
+
         insertMenu.getItems().clear();
-        
+
         if (documentWindowController == null) {
             insertMenu.getItems().add(new MenuItem(I18N.getString("menubar.no.lib.item")));
         } else {
             final EditorController editorController = documentWindowController.getEditorController();
             assert editorController.getLibrary() != null;
 
-            final Map<String, Set<LibraryItem>> sectionMap 
+            final Map<String, Set<LibraryItem>> sectionMap
                     = new TreeMap<>(new BuiltinSectionComparator());
             for (LibraryItem li : editorController.getLibrary().getItems()) {
                 Set<LibraryItem> sectionItems = sectionMap.get(li.getSection());
@@ -905,7 +1037,7 @@
                 sectionItems.add(li);
             }
 
-            for (Map.Entry<String,Set<LibraryItem>> e : sectionMap.entrySet()) {
+            for (Map.Entry<String, Set<LibraryItem>> e : sectionMap.entrySet()) {
                 final Menu sectionMenu = makeMenuForLibrarySection(e.getKey());
                 insertMenu.getItems().add(sectionMenu);
                 for (LibraryItem li : e.getValue()) {
@@ -914,7 +1046,7 @@
             }
         }
     }
-    
+
     private Menu makeMenuForLibrarySection(String section) {
         final Menu result = new Menu();
         result.setText(section);
@@ -926,10 +1058,10 @@
         });
         return result;
     }
-    
+
     private MenuItem makeMenuItemForLibraryItem(final LibraryItem li) {
         final MenuItem result = new MenuItem();
-        
+
         result.setText(li.getName());
         result.setUserData(li);
         result.setOnAction(new EventHandler<ActionEvent>() {
@@ -940,46 +1072,43 @@
         });
         return result;
     }
-    
-    
+
     private void updateInsertMenuState(Menu sectionMenu) {
         final EditorController editorController = documentWindowController.getEditorController();
         for (MenuItem menuItem : sectionMenu.getItems()) {
             assert menuItem.getUserData() instanceof LibraryItem;
             final LibraryItem li = (LibraryItem) menuItem.getUserData();
             final boolean enabled = editorController.canPerformInsert(li);
-            menuItem.setDisable(! enabled);
+            menuItem.setDisable(!enabled);
         }
     }
-    
+
     private void handleInsertMenuAction(LibraryItem li) {
         final EditorController editorController = documentWindowController.getEditorController();
         editorController.performInsert(li);
     }
-    
+
     /*
      * Private (Add Effect menu)
      */
-
     private void updateAddEffectMenu() {
         addEffectMenu.getItems().clear();
         for (Class<? extends Effect> c : EditorController.getEffectsSupportingAddition()) {
             addEffectMenu.getItems().add(makeMenuItemForEffect(c));
         }
     }
-    
+
     private MenuItem makeMenuItemForEffect(Class<? extends Effect> effectClass) {
         final Menu result = new Menu();
         result.setText(effectClass.getSimpleName());
         result.setUserData(new AddEffectActionController(effectClass));
         return result;
     }
-    
+
     /*
      * Private (window menu)
      */
-    
-    private final EventHandler<Event> onWindowMenuValidationHandler 
+    private final EventHandler<Event> onWindowMenuValidationHandler
             = new EventHandler<Event>() {
                 @Override
                 public void handle(Event t) {
@@ -987,10 +1116,10 @@
                     handleOnWindowMenuValidation();
                 }
             };
-    
+
     private void handleOnWindowMenuValidation() {
         windowMenu.getItems().clear();
-        
+
         final List<DocumentWindowController> documentWindowControllers
                 = SceneBuilderApp.getSingleton().getDocumentWindowControllers();
         if (documentWindowControllers.isEmpty()) {
@@ -1000,7 +1129,7 @@
             final List<DocumentWindowController> sortedControllers
                     = new ArrayList<>(documentWindowControllers);
             Collections.sort(sortedControllers, new DocumentWindowController.TitleComparator());
-            
+
             for (DocumentWindowController dwc : sortedControllers) {
                 windowMenu.getItems().add(makeWindowMenuItem(dwc));
             }
@@ -1019,38 +1148,42 @@
             result.setDisable(true);
             result.setSelected(false);
         }
-        
+
         return result;
     }
-    
+
     private static class WindowMenuEventHandler implements EventHandler<ActionEvent> {
-        
+
         private final DocumentWindowController dwc;
-        
+
         public WindowMenuEventHandler(DocumentWindowController dwc) {
             this.dwc = dwc;
         }
-        
+
         @Override
         public void handle(ActionEvent t) {
             dwc.getStage().toFront();
         }
     }
-    
-    
+
     /*
      * Private (MenuItemController)
      */
-    
     abstract class MenuItemController {
 
         public abstract boolean canPerform();
+
         public abstract void perform();
 
-        public String getTitle() { return null; }
-        public boolean isSelected() { return false; }
+        public String getTitle() {
+            return null;
+        }
+
+        public boolean isSelected() {
+            return false;
+        }
     }
-    
+
     class UndoActionController extends MenuItemController {
 
         @Override
@@ -1083,7 +1216,7 @@
     }
 
     class RedoActionController extends MenuItemController {
-        
+
         @Override
         public boolean canPerform() {
             boolean result;
@@ -1100,7 +1233,7 @@
             assert canPerform();
             documentWindowController.getEditorController().redo();
         }
-        
+
         @Override
         public String getTitle() {
             final StringBuilder result = new StringBuilder();
@@ -1114,9 +1247,9 @@
     }
 
     class EditActionController extends MenuItemController {
-        
+
         private final EditAction editAction;
-        
+
         public EditActionController(EditAction editAction) {
             this.editAction = editAction;
         }
@@ -1139,12 +1272,11 @@
         }
 
     }
-    
-    
+
     class ControlActionController extends MenuItemController {
-        
+
         private final ControlAction controlAction;
-        
+
         public ControlActionController(ControlAction controlAction) {
             this.controlAction = controlAction;
         }
@@ -1167,12 +1299,11 @@
         }
 
     }
-    
-    
+
     class DocumentControlActionController extends MenuItemController {
-        
+
         private final DocumentControlAction controlAction;
-        
+
         public DocumentControlActionController(DocumentControlAction controlAction) {
             this.controlAction = controlAction;
         }
@@ -1193,14 +1324,13 @@
             assert canPerform() : "controlAction=" + controlAction;
             documentWindowController.performControlAction(controlAction);
         }
-        
+
     }
-    
-    
+
     class ApplicationControlActionController extends MenuItemController {
-        
+
         private final ApplicationControlAction controlAction;
-        
+
         public ApplicationControlActionController(ApplicationControlAction controlAction) {
             this.controlAction = controlAction;
         }
@@ -1216,14 +1346,13 @@
             SceneBuilderApp.getSingleton().performControlAction(controlAction,
                     documentWindowController);
         }
-        
+
     }
-    
-    
+
     class AddEffectActionController extends MenuItemController {
-        
+
         private final Class<? extends Effect> effectClass;
-        
+
         public AddEffectActionController(Class<? extends Effect> effectClass) {
             this.effectClass = effectClass;
         }
@@ -1238,15 +1367,13 @@
         public void perform() {
             throw new UnsupportedOperationException("Not supported yet: effectClass=" + effectClass);  //NOI18N
         }
-        
-        
+
     }
-    
-    
+
     class SetZoomActionController extends MenuItemController {
-        
+
         private final double scaling;
-        
+
         public SetZoomActionController(double scaling) {
             this.scaling = scaling;
         }
@@ -1266,30 +1393,28 @@
                 contentPanelController.setScaling(scaling);
             }
         }
-        
+
         @Override
         public boolean isSelected() {
             boolean result;
-            
+
             if (documentWindowController == null) {
                 result = false;
             } else {
                 final double currentScaling
                         = documentWindowController.getContentPanelController().getScaling();
-                result = MathUtils.equals(currentScaling, scaling); 
+                result = MathUtils.equals(currentScaling, scaling);
             }
-            
+
             return result;
         }
-        
-        
+
     }
-    
-    
+
     class SetThemeActionController extends MenuItemController {
-        
+
         private final EditorPlatform.Theme theme;
-        
+
         public SetThemeActionController(EditorPlatform.Theme theme) {
             this.theme = theme;
         }
@@ -1304,11 +1429,11 @@
             assert documentWindowController != null;
             documentWindowController.getEditorController().setTheme(theme);
         }
-        
+
         @Override
         public boolean isSelected() {
             boolean result;
-            
+
             if (documentWindowController == null) {
                 result = false;
             } else {
@@ -1316,12 +1441,11 @@
                         = documentWindowController.getEditorController().getTheme();
                 result = currentTheme == theme;
             }
-            
+
             return result;
         }
     }
 
-    
     class RemoveSceneStyleSheetActionController extends MenuItemController {
 
         private final File styleSheet;
@@ -1347,7 +1471,6 @@
         }
     }
 
-    
     class OpenSceneStyleSheetActionController extends MenuItemController {
 
         private final File styleSheet;
@@ -1372,4 +1495,19 @@
             return styleSheet.getName();
         }
     }
+
+    /**
+     * *************************************************************************
+     * Static inner class
+     * *************************************************************************
+     */
+    private static class ClearOpenRecentHandler implements EventHandler<ActionEvent> {
+
+        @Override
+        public void handle(ActionEvent t) {
+            final PreferencesController pc = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal = pc.getRecordGlobal();
+            recordGlobal.clearRecentItems();
+        }
+    }
 }
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessageBarController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessageBarController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -31,6 +31,7 @@
  */
 package com.oracle.javafx.scenebuilder.app.message;
 
+import com.oracle.javafx.scenebuilder.app.i18n.I18N;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
 import com.oracle.javafx.scenebuilder.kit.editor.messagelog.MessageLogEntry;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.util.AbstractFxmlPanelController;
@@ -72,7 +73,7 @@
     private final ImageView alertImage;
 
     public MessageBarController(EditorController editorController) {
-        super(MessageBarController.class.getResource("MessageBar.fxml"), editorController); //NOI18N
+        super(MessageBarController.class.getResource("MessageBar.fxml"), I18N.getBundle(), editorController); //NOI18N
 
         // Initialize warning image
         final URL warningURL = MessageBarController.class.getResource("warning.png"); //NOI18N
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessagePanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/message/MessagePanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -80,7 +80,7 @@
     }
     
     public MessagePanelController(EditorController editorController) {
-        super(MessagePanelController.class.getResource("MessagePanel.fxml"), editorController); //NOI18N
+        super(MessagePanelController.class.getResource("MessagePanel.fxml"), I18N.getBundle(), editorController); //NOI18N
     }
     
     
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/Preferences.fxml	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/Preferences.fxml	Tue Dec 10 08:36:28 2013 +0100
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
   Copyright (c) 2012, 2013, Oracle and/or its affiliates.
   All rights reserved. Use is subject to license terms.
@@ -40,14 +41,14 @@
 <?import javafx.scene.paint.*?>
 <?scenebuilder-preview-i18n-resource ../i18n/SceneBuilderApp.properties?>
 
-<GridPane hgap="6.0" maxWidth="1.7976931348623157E308" vgap="10.0" xmlns:fx="http://javafx.com/fxml">
+<GridPane hgap="6.0" maxWidth="1.7976931348623157E308" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
   <children>
     <Label text="%prefs.doc.width" GridPane.columnIndex="0" GridPane.rowIndex="0" />
-    <TextField fx:id="documentWidth" onAction="#onWidthChange" prefWidth="200.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="0" />
+    <TextField fx:id="documentWidth" prefWidth="200.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="0" />
     <Label text="%prefs.doc.height" GridPane.columnIndex="0" GridPane.rowIndex="1" />
-    <TextField fx:id="documentHeight" onAction="#onHeightChange" prefWidth="200.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="1" />
+    <TextField fx:id="documentHeight" prefWidth="200.0" text="" GridPane.columnIndex="1" GridPane.rowIndex="1" />
     <Label text="%prefs.background" GridPane.columnIndex="0" GridPane.rowIndex="3" />
-    <ChoiceBox fx:id="backgroundStyleClass" GridPane.columnIndex="1" GridPane.rowIndex="3" />
+    <ChoiceBox fx:id="backgroundImage" GridPane.columnIndex="1" GridPane.rowIndex="3" />
     <Label text="%prefs.alignment.guides" GridPane.columnIndex="0" GridPane.rowIndex="4" />
     <VBox fx:id="alignmentGuides" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="4" />
     <Label text="%prefs.drop.ring" GridPane.columnIndex="0" GridPane.rowIndex="5" />
@@ -67,11 +68,24 @@
     <Separator prefWidth="-1.0" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2" />
     <Separator prefWidth="-1.0" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="6" />
     <Separator prefWidth="-1.0" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="9" />
+    <Label text="%prefs.recent.items" GridPane.columnIndex="0" GridPane.rowIndex="10" />
+    <ChoiceBox fx:id="recentItemsSize" GridPane.columnIndex="1" GridPane.rowIndex="10">
+      <items>
+        <FXCollections fx:factory="observableArrayList">
+          <String fx:value="Item 1" />
+          <String fx:value="Item 2" />
+          <String fx:value="Item 3" />
+        </FXCollections>
+      </items>
+    </ChoiceBox>
   </children>
   <columnConstraints>
     <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" />
     <ColumnConstraints halignment="LEFT" hgrow="ALWAYS" maxWidth="177.0" minWidth="-Infinity" prefWidth="-1.0" />
   </columnConstraints>
+  <padding>
+    <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
+  </padding>
   <rowConstraints>
     <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
     <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
@@ -83,6 +97,8 @@
     <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
     <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
     <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
+    <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
+    <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="-1.0" vgrow="NEVER" />
   </rowConstraints>
   <stylesheets>
     <URL value="@Preferences.css" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app.preferences;
+
+import java.util.prefs.Preferences;
+
+/**
+ * Defines preferences for Scene Builder. Theses preferences are common to all
+ * SB projects.
+ *
+ */
+public class PreferencesController {
+
+    // JAVA PREFERENCES KEYS DEFINITIONS
+    static final String SB_RELEASE_NODE = "SB_2.0"; //NOI18N
+
+    static final String DOCUMENT_HEIGHT = "DOCUMENT_HEIGHT"; //NOI18N
+    static final String DOCUMENT_WIDTH = "DOCUMENT_WIDTH"; //NOI18N
+
+    static final String BACKGROUND_IMAGE = "BACKGROUND_IMAGE"; //NOI18N
+    static final String ALIGNMENT_GUIDES_COLOR = "ALIGNMENT_GUIDES_COLOR"; //NOI18N
+    static final String PARENT_RING_COLOR = "PARENT_RING_COLOR"; //NOI18N
+
+    static final String HIERARCHY_DISPLAY_OPTION = "HIERARCHY_DISPLAY_OPTION"; //NOI18N
+    static final String CSS_ANALYZER_COLUMN_ORDER = "CSS_ANALYZER_COLUMN_ORDER"; //NOI18N
+
+    static final String RECENT_ITEMS = "RECENT_ITEMS"; //NOI18N
+    static final String RECENT_ITEMS_SIZE = "RECENT_ITEMS_SIZE"; //NOI18N
+
+    private static final PreferencesController singleton = new PreferencesController();
+
+    private final Preferences javaPreferences;
+    private final PreferencesRecordGlobal recordGlobal;
+
+    private PreferencesController() {
+        javaPreferences = Preferences.userNodeForPackage(
+                PreferencesController.class).node(SB_RELEASE_NODE);
+
+        // Preferences global to the SB application
+        recordGlobal = new PreferencesRecordGlobal(javaPreferences);
+    }
+
+    public static PreferencesController getSingleton() {
+        return singleton;
+    }
+
+    public PreferencesRecordGlobal getRecordGlobal() {
+        return recordGlobal;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesRecordDocument.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app.preferences;
+
+/**
+ *
+ */
+public class PreferencesRecordDocument {
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesRecordGlobal.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app.preferences;
+
+import com.oracle.javafx.scenebuilder.app.i18n.I18N;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.ALIGNMENT_GUIDES_COLOR;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.BACKGROUND_IMAGE;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.CSS_ANALYZER_COLUMN_ORDER;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.DOCUMENT_HEIGHT;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.DOCUMENT_WIDTH;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.HIERARCHY_DISPLAY_OPTION;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.PARENT_RING_COLOR;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.RECENT_ITEMS;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesController.RECENT_ITEMS_SIZE;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.hierarchy.AbstractHierarchyPanelController.DisplayOption;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.prefs.Preferences;
+import javafx.scene.paint.Color;
+
+/**
+ * Defines preferences global to the application.
+ */
+public class PreferencesRecordGlobal {
+
+    // Default values
+    private static final double DEFAULT_DOCUMENT_HEIGHT = 400;
+    private static final double DEFAULT_DOCUMENT_WIDTH = 600;
+
+    private static final BackgroundImage DEFAULT_BACKGROUND_IMAGE
+            = BackgroundImage.BACKGROUND_01;
+    private static final Color DEFAULT_ALIGNMENT_GUIDES_COLOR = Color.RED;
+    private static final Color DEFAULT_PARENT_RING_COLOR = Color.rgb(238, 168, 47);
+
+    private static final DisplayOption DEFAULT_HIERARCHY_DISPLAY_OPTION
+            = DisplayOption.INFO;
+    private static final CSSAnalyzerColumnsOrder DEFAULT_CSS_ANALYZER_COLUMN_ORDER
+            = CSSAnalyzerColumnsOrder.DEFAULTS_FIRST;
+
+    private static final int DEFAULT_RECENT_ITEMS_SIZE = 15;
+
+    // Global preferences
+    private double documentHeight = 0.0;
+    private double documentWidth = 0.0;
+    private BackgroundImage backgroundImage;
+    private Color alignmentGuidesColor;
+    private Color parentRingColor;
+    private DisplayOption hierarchyDisplayOption;
+    private CSSAnalyzerColumnsOrder cssAnalyzerColumnOrder;
+    private int recentItemsSize = 0;
+    private final List<String> recentItems = new ArrayList<>();
+
+    private final Preferences javaPreferences;
+
+    final static Integer[] recentItemsSizes = {5, 10, 15, 20};
+
+    public enum BackgroundImage {
+
+        BACKGROUND_01 {
+
+                    @Override
+                    public String toString() {
+                        return I18N.getString("prefs.background.value1");
+                    }
+                },
+        BACKGROUND_02 {
+
+                    @Override
+                    public String toString() {
+                        return I18N.getString("prefs.background.value2");
+                    }
+                },
+        BACKGROUND_03 {
+
+                    @Override
+                    public String toString() {
+                        return I18N.getString("prefs.background.value3");
+                    }
+                }
+    }
+
+    public enum CSSAnalyzerColumnsOrder {
+
+        DEFAULTS_FIRST {
+
+                    @Override
+                    public String toString() {
+                        return I18N.getString("prefs.cssanalyzer.columns.defaults.first");
+                    }
+                },
+        DEFAULTS_LAST {
+
+                    @Override
+                    public String toString() {
+                        return I18N.getString("prefs.cssanalyzer.columns.defaults.last");
+                    }
+                }
+    }
+
+    public PreferencesRecordGlobal(Preferences javaPreferences) {
+        this.javaPreferences = javaPreferences;
+    }
+
+    public double getDocumentHeight() {
+        return documentHeight;
+    }
+
+    public void setDocumentHeight(double value) {
+        documentHeight = value;
+    }
+
+    public double getDocumentWidth() {
+        return documentWidth;
+    }
+
+    public void setDocumentWidth(double value) {
+        documentWidth = value;
+    }
+
+    public BackgroundImage getBackgroundImage() {
+        return backgroundImage;
+    }
+
+    public void setBackgroundImage(BackgroundImage value) {
+        backgroundImage = value;
+    }
+
+    public Color getAlignmentGuidesColor() {
+        return alignmentGuidesColor;
+    }
+
+    public void setAlignmentGuidesColor(Color value) {
+        alignmentGuidesColor = value;
+    }
+
+    public Color getParentRingColor() {
+        return parentRingColor;
+    }
+
+    public void setParentRingColor(Color value) {
+        parentRingColor = value;
+    }
+
+    public DisplayOption getHierarchyDisplayOption() {
+        return hierarchyDisplayOption;
+    }
+
+    public void setHierarchyDisplayOption(DisplayOption value) {
+        hierarchyDisplayOption = value;
+    }
+
+    public CSSAnalyzerColumnsOrder getCSSAnalyzerColumnsOrder() {
+        return cssAnalyzerColumnOrder;
+    }
+
+    public void setCSSAnalyzerColumnsOrder(CSSAnalyzerColumnsOrder value) {
+        cssAnalyzerColumnOrder = value;
+    }
+
+    public int getRecentItemsSize() {
+        return recentItemsSize;
+    }
+
+    public void setRecentItemsSize(int value) {
+        recentItemsSize = value;
+        // Remove last items depending on the size
+        while (recentItems.size() > recentItemsSize) {
+            recentItems.remove(recentItems.size() - 1);
+        }
+    }
+
+    public List<String> getRecentItems() {
+        return recentItems;
+    }
+
+    public void addRecentItems(List<File> files) {
+        // Add the specified file to the recent items at first position
+        for (File file : files) {
+            final String path = file.getAbsolutePath();
+            if (recentItems.contains(path)) {
+                recentItems.remove(path);
+            }
+            recentItems.add(0, path);
+        }
+        // Remove last items depending on the size
+        while (recentItems.size() > recentItemsSize) {
+            recentItems.remove(recentItems.size() - 1);
+        }
+    }
+
+    public void clearRecentItems() {
+        recentItems.clear();
+    }
+
+    /**
+     * Read data from the java preferences DB and initialize properties.
+     */
+    public void readFromJavaPreferences() {
+
+        // Document size
+        final double height = javaPreferences.getDouble(DOCUMENT_HEIGHT,
+                DEFAULT_DOCUMENT_HEIGHT);
+        setDocumentHeight(height);
+        final double width = javaPreferences.getDouble(DOCUMENT_WIDTH,
+                DEFAULT_DOCUMENT_WIDTH);
+        setDocumentWidth(width);
+
+        // Background image
+        final String image = javaPreferences.get(BACKGROUND_IMAGE,
+                DEFAULT_BACKGROUND_IMAGE.name());
+        setBackgroundImage(BackgroundImage.valueOf(image));
+
+        // Alignment guides color
+        final String agColor = javaPreferences.get(ALIGNMENT_GUIDES_COLOR,
+                DEFAULT_ALIGNMENT_GUIDES_COLOR.toString());
+        setAlignmentGuidesColor(Color.valueOf(agColor));
+
+        // Parent ring color
+        final String prColor = javaPreferences.get(PARENT_RING_COLOR,
+                DEFAULT_PARENT_RING_COLOR.toString());
+        setParentRingColor(Color.valueOf(prColor));
+
+        // Hierarchy display option
+        final String displayOption = javaPreferences.get(HIERARCHY_DISPLAY_OPTION,
+                DEFAULT_HIERARCHY_DISPLAY_OPTION.name());
+        setHierarchyDisplayOption(DisplayOption.valueOf(displayOption));
+
+        // CSS analyzer column order
+        final String order = javaPreferences.get(CSS_ANALYZER_COLUMN_ORDER,
+                DEFAULT_CSS_ANALYZER_COLUMN_ORDER.name());
+        setCSSAnalyzerColumnsOrder(CSSAnalyzerColumnsOrder.valueOf(order));
+
+        // Recent items size
+        final int size = javaPreferences.getInt(
+                RECENT_ITEMS_SIZE, DEFAULT_RECENT_ITEMS_SIZE);
+        setRecentItemsSize(size);
+
+        // Recent items list
+        final String items = javaPreferences.get(RECENT_ITEMS, ""); //NOI18N
+        assert recentItems.isEmpty();
+        if (items.isEmpty() == false) {
+            final String[] itemsArray = items.split("\\" + File.pathSeparator); //NOI18N
+            assert itemsArray.length <= recentItemsSize;
+            recentItems.addAll(Arrays.asList(itemsArray));
+        }
+    }
+
+    /**
+     * Write the properties data to the java preferences DB.
+     */
+    public void writeToJavaPreferences() {
+
+        // Document size
+        javaPreferences.putDouble(DOCUMENT_HEIGHT, getDocumentHeight());
+        javaPreferences.putDouble(DOCUMENT_WIDTH, getDocumentWidth());
+
+        // Background image
+        javaPreferences.put(BACKGROUND_IMAGE, getBackgroundImage().name());
+
+        // Alignment guides color
+        javaPreferences.put(ALIGNMENT_GUIDES_COLOR, getAlignmentGuidesColor().toString());
+
+        // Parent ring color
+        javaPreferences.put(PARENT_RING_COLOR, getParentRingColor().toString());
+
+        // Hierarchy display option
+        javaPreferences.put(HIERARCHY_DISPLAY_OPTION, getHierarchyDisplayOption().name());
+
+        // CSS analyzer column order
+        javaPreferences.put(CSS_ANALYZER_COLUMN_ORDER, getCSSAnalyzerColumnsOrder().name());
+
+        // Recent items size
+        javaPreferences.putInt(RECENT_ITEMS_SIZE, getRecentItemsSize());
+
+        // Recent items list
+        final StringBuilder sb = new StringBuilder();
+        for (String recentItem : getRecentItems()) {
+            sb.append(recentItem);
+            sb.append(File.pathSeparator);
+        }
+        javaPreferences.put(RECENT_ITEMS, sb.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preferences/PreferencesWindowController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app.preferences;
+
+import com.oracle.javafx.scenebuilder.app.i18n.I18N;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal.BackgroundImage;
+import com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal.CSSAnalyzerColumnsOrder;
+import static com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal.recentItemsSizes;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.hierarchy.AbstractHierarchyPanelController.DisplayOption;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.util.AbstractFxmlWindowController;
+import java.util.Arrays;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.fxml.FXML;
+import javafx.scene.control.ChoiceBox;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.VBox;
+import javafx.stage.WindowEvent;
+
+/**
+ * Preferences window controller.
+ */
+public class PreferencesWindowController extends AbstractFxmlWindowController {
+
+    @FXML
+    private TextField documentHeight;
+    @FXML
+    private TextField documentWidth;
+    @FXML
+    private ChoiceBox<BackgroundImage> backgroundImage;
+    @FXML
+    private ChoiceBox<DisplayOption> hierarchyDisplayOption;
+    @FXML
+    private ChoiceBox<CSSAnalyzerColumnsOrder> cssAnalyzerColumnsOrder;
+    @FXML
+    private VBox alignmentGuides;
+    @FXML
+    private VBox dropTargetRing;
+    @FXML
+    private ChoiceBox<Integer> recentItemsSize;
+
+    public PreferencesWindowController() {
+        super(PreferencesWindowController.class.getResource("Preferences.fxml"), //NOI18N
+                I18N.getBundle());
+    }
+
+    /*
+     * AbstractModalDialog
+     */
+    @Override
+    protected void controllerDidLoadFxml() {
+        super.controllerDidLoadFxml();
+
+        final PreferencesController preferencesController
+                = PreferencesController.getSingleton();
+        final PreferencesRecordGlobal recordGlobal
+                = preferencesController.getRecordGlobal();
+
+        // Document size
+        documentHeight.setText(String.valueOf(recordGlobal.getDocumentHeight()));
+        documentHeight.setOnAction(new EventHandler<ActionEvent>() {
+
+            @Override
+            public void handle(ActionEvent t) {
+                final String value = documentHeight.getText();
+                recordGlobal.setDocumentHeight(Double.valueOf(value));
+                documentHeight.selectAll();
+            }
+        });
+        documentWidth.setText(String.valueOf(recordGlobal.getDocumentWidth()));
+        documentWidth.setOnAction(new EventHandler<ActionEvent>() {
+
+            @Override
+            public void handle(ActionEvent t) {
+                final String value = documentWidth.getText();
+                recordGlobal.setDocumentWidth(Double.valueOf(value));
+                documentWidth.selectAll();
+            }
+        });
+
+        // Background image
+        backgroundImage.getItems().setAll(Arrays.asList(BackgroundImage.class.getEnumConstants()));
+        backgroundImage.setValue(recordGlobal.getBackgroundImage());
+        backgroundImage.getSelectionModel().selectedItemProperty().addListener(new BackgroundImageListener());
+
+        // Hierarchy display option
+        hierarchyDisplayOption.getItems().setAll(Arrays.asList(DisplayOption.class.getEnumConstants()));
+        hierarchyDisplayOption.setValue(recordGlobal.getHierarchyDisplayOption());
+        hierarchyDisplayOption.getSelectionModel().selectedItemProperty().addListener(new DisplayOptionListener());
+
+        // CSS analyzer column order
+        cssAnalyzerColumnsOrder.getItems().setAll(Arrays.asList(CSSAnalyzerColumnsOrder.class.getEnumConstants()));
+        cssAnalyzerColumnsOrder.setValue(recordGlobal.getCSSAnalyzerColumnsOrder());
+        cssAnalyzerColumnsOrder.getSelectionModel().selectedItemProperty().addListener(new ColumnOrderListener());
+
+        // Number of open recent items
+        recentItemsSize.getItems().setAll(recentItemsSizes);
+        recentItemsSize.setValue(recordGlobal.getRecentItemsSize());
+        recentItemsSize.getSelectionModel().selectedItemProperty().addListener(new RecentItemsSizeListener());
+    }
+
+    /*
+     * AbstractWindowController
+     */
+    @Override
+    protected void controllerDidCreateStage() {
+        assert getRoot() != null;
+        assert getRoot().getScene() != null;
+        assert getRoot().getScene().getWindow() != null;
+
+        getStage().setTitle(I18N.getString("prefs.title"));
+        getStage().setResizable(false);
+    }
+
+    @Override
+    public void onCloseRequest(WindowEvent event) {
+        super.closeWindow();
+    }
+
+    /**
+     * *************************************************************************
+     * Static inner class
+     * *************************************************************************
+     */
+    private static class BackgroundImageListener implements ChangeListener<BackgroundImage> {
+
+        @Override
+        public void changed(ObservableValue<? extends BackgroundImage> observable,
+                BackgroundImage oldValue, BackgroundImage newValue) {
+            final PreferencesController preferencesController
+                    = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal
+                    = preferencesController.getRecordGlobal();
+            recordGlobal.setBackgroundImage(newValue);
+        }
+    }
+
+    private static class DisplayOptionListener implements ChangeListener<DisplayOption> {
+
+        @Override
+        public void changed(ObservableValue<? extends DisplayOption> observable,
+                DisplayOption oldValue, DisplayOption newValue) {
+            final PreferencesController preferencesController
+                    = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal
+                    = preferencesController.getRecordGlobal();
+            recordGlobal.setHierarchyDisplayOption(newValue);
+        }
+    }
+
+    private static class ColumnOrderListener implements ChangeListener<CSSAnalyzerColumnsOrder> {
+
+        @Override
+        public void changed(ObservableValue<? extends CSSAnalyzerColumnsOrder> observable,
+                CSSAnalyzerColumnsOrder oldValue, CSSAnalyzerColumnsOrder newValue) {
+            final PreferencesController preferencesController
+                    = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal
+                    = preferencesController.getRecordGlobal();
+            recordGlobal.setCSSAnalyzerColumnsOrder(newValue);
+        }
+    }
+
+    private static class RecentItemsSizeListener implements ChangeListener<Integer> {
+
+        @Override
+        public void changed(ObservableValue<? extends Integer> observable,
+                Integer oldValue, Integer newValue) {
+            final PreferencesController preferencesController
+                    = PreferencesController.getSingleton();
+            final PreferencesRecordGlobal recordGlobal
+                    = preferencesController.getRecordGlobal();
+            recordGlobal.setRecentItemsSize(newValue);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preview/BackgroundColor.fxml	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2012, 2013, 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.
+-->
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+
+<StackPane minHeight="-1.0" prefHeight="-1.0" prefWidth="-1.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/preview/BackgroundColorDialogController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.app.preview;
+
+import com.oracle.javafx.scenebuilder.app.i18n.I18N;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.util.dialog.AbstractModalDialog;
+import com.oracle.javafx.scenebuilder.kit.util.control.paintpicker.PaintPicker;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Paint;
+import javafx.stage.Window;
+
+/**
+ * Controller for the preview background color.
+ */
+public class BackgroundColorDialogController extends AbstractModalDialog {
+
+    private final PaintPicker paintPicker = new PaintPicker();
+
+    public BackgroundColorDialogController(Window owner) {
+        super(BackgroundColorDialogController.class.getResource("BackgroundColor.fxml"), //NOI18N
+                I18N.getBundle(), owner);
+    }
+
+    /*
+     * AbstractModalDialog
+     */
+    @Override
+    protected void controllerDidLoadFxml() {
+        super.controllerDidLoadFxml();
+        setActionButtonVisible(false);
+        setDefaultButtonID(AbstractModalDialog.ButtonID.OK);
+        setShowDefaultButton(true);
+        // Update title
+        final String title = I18N.getString("preview.background.color");
+        getStage().setTitle(title);
+    }
+
+    @Override
+    protected void controllerDidLoadContentFxml() {
+
+        assert getContentRoot() instanceof Pane;
+        final Pane contentRoot = (Pane) getContentRoot();
+        contentRoot.getChildren().add(paintPicker);
+
+        final ChangeListener<Number> sizeListener = new ChangeListener<Number>() {
+
+            @Override
+            public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
+                getStage().sizeToScene();
+            }
+        };
+
+        contentRoot.heightProperty().addListener(sizeListener);
+        contentRoot.widthProperty().addListener(sizeListener);
+
+        paintPicker.paintProperty().addListener(new PaintChangeListener<Paint>());
+    }
+
+    @Override
+    protected void okButtonPressed(ActionEvent e) {
+        closeWindow();
+    }
+
+    @Override
+    protected void cancelButtonPressed(ActionEvent e) {
+        closeWindow();
+    }
+
+    @Override
+    protected void actionButtonPressed(ActionEvent e) {
+        // Should not be called because button is hidden
+        throw new IllegalStateException();
+    }
+
+    private static class PaintChangeListener<Paint> implements ChangeListener<Paint> {
+
+        @Override
+        public void changed(ObservableValue<? extends Paint> ov, Paint oldValue, Paint newValue) {
+            // Missing update EditorController backgroundColor property
+            System.err.println("Update Preview background color with " + newValue); //NOI18N
+        }
+    }
+}
--- a/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/selectionbar/SelectionBarController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderApp/src/com/oracle/javafx/scenebuilder/app/selectionbar/SelectionBarController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -74,7 +74,7 @@
     private final Image warningBadgeImage;
 
     public SelectionBarController(EditorController editorController) {
-        super(SelectionBarController.class.getResource("SelectionBar.fxml"), editorController); //NOI18N
+        super(SelectionBarController.class.getResource("SelectionBar.fxml"), I18N.getBundle(), editorController); //NOI18N
 
         // Initialize selection chevron image
         final URL selectionChevronURL = SelectionBarController.class.getResource("selection-chevron.png"); //NOI18N
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.css	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.css	Tue Dec 10 08:36:28 2013 +0100
@@ -30,7 +30,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
 .drag-preview {
     -fx-text-fill: lightgray;
     -fx-text-alignment: center;
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -90,8 +90,10 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.ResourceBundle;
+import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.ListProperty;
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.SimpleListProperty;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ChangeListener;
@@ -208,6 +210,8 @@
             = new SimpleListProperty<>();
     private final ObjectProperty<File> resourceProperty
             = new SimpleObjectProperty<>(null);
+    private final BooleanProperty pickModeEnabledProperty
+            = new SimpleBooleanProperty(true);
     
     private Callback<Void, Boolean> requestTextEditingSessionEnd;
     
@@ -495,6 +499,32 @@
     }
     
     /**
+     * Returns true is 'pick mode' is enabled for this editor.
+     * @return true is 'pick mode' is enabled for this editor.
+     */
+    public boolean isPickModeEnabled() {
+        return pickModeEnabledProperty.getValue();
+    }
+    
+    /**
+     * Enables or disables 'pick mode' on this editor.
+     * 
+     * @param pickModeEnabled true if 'pick mode' should be enabled.
+     */
+    public void setPickModeEnabled(boolean pickModeEnabled) {
+        pickModeEnabledProperty.setValue(pickModeEnabled);
+    }
+    
+    /**
+     * The property indicating if 'pick mode' is enabled or not.
+     * 
+     * @return the property indicating if 'pick mode' is enabled or not.
+     */
+    public ObservableValue<Boolean> pickModeEnabledProperty() {
+        return pickModeEnabledProperty;
+    }
+    
+    /**
      * Returns null or the location of the fxml being edited.
      * 
      * @return null or the location of the fxml being edited.
@@ -1505,5 +1535,6 @@
     
     private void jobManagerRevisionDidChange() {
         errorReport.requestUpdate();
+//        setPickModeEnabled(false);
     }
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorPlatform.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/EditorPlatform.java	Tue Dec 10 08:36:28 2013 +0100
@@ -63,6 +63,11 @@
      * True if current platform is running Windows.
      */
     public static final boolean IS_WINDOWS = osName.contains("windows"); //NOI18N
+    
+    /**
+     * This URL is where you go when the user takes Scene Builder Help action (shortcut F1)
+     */
+    public static final String DOCUMENTATION_URL = "http://docs.oracle.com/javafx/index.html"; //NOI18N
 
     /**
      * Themes supported by Scene Builder Kit.
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/DragController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/DragController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -92,10 +92,12 @@
         if (committedDropTarget != null) {
             assert committedDropTarget.acceptDragSource(getDragSource());
             final Job dropJob = committedDropTarget.makeDropJob(getDragSource(), editorController);
+            editorController.getSelection().beginUpdate();
             editorController.getFxomDocument().beginUpdate(); // Required because dropJob may not do it
             editorController.getJobManager().push(dropJob);
             editorController.getFxomDocument().endUpdate();
             editorController.getSelection().select(getDragSource().getDraggedObjects());
+            editorController.getSelection().endUpdate();
         }
         
         /*
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/AbstractDragSource.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/AbstractDragSource.java	Tue Dec 10 08:36:28 2013 +0100
@@ -57,6 +57,9 @@
     }
     
     public abstract List<FXOMObject> getDraggedObjects();
+    public abstract FXOMObject getHitObject();
+    public abstract double getHitX();
+    public abstract double getHitY();
     public abstract ClipboardContent makeClipboardContent();
     public abstract Image makeDragView();
     public abstract Node makeShadow();
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/DocumentDragSource.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/DocumentDragSource.java	Tue Dec 10 08:36:28 2013 +0100
@@ -116,18 +116,6 @@
         return new Point2D(hitX,hitY);
     }
 
-    public FXOMObject getHitObject() {
-        return hitObject;
-    }
-
-    public double getHitX() {
-        return hitX;
-    }
-
-    public double getHitY() {
-        return hitY;
-    }
-
     /*
      * AbstractDragSource
      */
@@ -138,6 +126,21 @@
     }
 
     @Override
+    public FXOMObject getHitObject() {
+        return hitObject;
+    }
+
+    @Override
+    public double getHitX() {
+        return hitX;
+    }
+
+    @Override
+    public double getHitY() {
+        return hitY;
+    }
+
+    @Override
     public ClipboardContent makeClipboardContent() {
         
         // Encode the dragged objects in FXML
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/ExternalDragSource.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/ExternalDragSource.java	Tue Dec 10 08:36:28 2013 +0100
@@ -164,8 +164,57 @@
         
         return draggedObjects;
     }
+
+    @Override
+    public FXOMObject getHitObject() {
+        final FXOMObject result;
+        
+        if (getDraggedObjects().isEmpty()) {
+            result = null;
+        } else {
+            result = getDraggedObjects().get(0);
+        }
+        
+        return result;
+    }
     
     @Override
+    public double getHitX() {
+        final double result;
+        
+        final FXOMObject hitObject = getHitObject();
+        if (hitObject == null) {
+            result = Double.NaN;
+        } else if (hitObject.isNode()) {
+            final Node hitNode = (Node) hitObject.getSceneGraphObject();
+            final Bounds b = hitNode.getLayoutBounds();
+            result = (b.getMinX() + b.getMaxX()) / 2.0;
+        } else {
+            result = 0.0;
+        }
+        
+        return result;
+    }
+
+    @Override
+    public double getHitY() {
+        final double result;
+        
+        final FXOMObject hitObject = getHitObject();
+        if (hitObject == null) {
+            result = Double.NaN;
+        } else if (hitObject.isNode()) {
+            final Node hitNode = (Node) hitObject.getSceneGraphObject();
+            final Bounds b = hitNode.getLayoutBounds();
+            result = (b.getMinY() + b.getMaxY()) / 2.0;
+        } else {
+            result = 0.0;
+        }
+        
+        return result;
+    }
+
+    @Override
     public ClipboardContent makeClipboardContent() {
         throw new UnsupportedOperationException("should not be called"); //NOI18N
     }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/LibraryDragSource.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/source/LibraryDragSource.java	Tue Dec 10 08:36:28 2013 +0100
@@ -116,6 +116,47 @@
     }
     
     @Override
+    public FXOMObject getHitObject() {
+        return getDraggedObjects().get(0);
+    }
+    
+    @Override
+    public double getHitX() {
+        final double result;
+        
+        final FXOMObject hitObject = getHitObject();
+        if (hitObject == null) {
+            result = Double.NaN;
+        } else if (hitObject.isNode()) {
+            final Node hitNode = (Node) hitObject.getSceneGraphObject();
+            final Bounds b = hitNode.getLayoutBounds();
+            result = (b.getMinX() + b.getMaxX()) / 2.0;
+        } else {
+            result = 0.0;
+        }
+        
+        return result;
+    }
+
+    @Override
+    public double getHitY() {
+        final double result;
+        
+        final FXOMObject hitObject = getHitObject();
+        if (hitObject == null) {
+            result = Double.NaN;
+        } else if (hitObject.isNode()) {
+            final Node hitNode = (Node) hitObject.getSceneGraphObject();
+            final Bounds b = hitNode.getLayoutBounds();
+            result = (b.getMinY() + b.getMaxY()) / 2.0;
+        } else {
+            result = 0.0;
+        }
+        
+        return result;
+    }
+
+    @Override
     public ClipboardContent makeClipboardContent() {
         final ClipboardContent result = new ClipboardContent();
         
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/target/ContainerXYDropTarget.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/target/ContainerXYDropTarget.java	Tue Dec 10 08:36:28 2013 +0100
@@ -107,18 +107,9 @@
         
         
         final List<FXOMObject> draggedObjects = dragSource.getDraggedObjects();
-        final FXOMObject hitObject;
-        final double hitX, hitY;
-        if (dragSource instanceof DocumentDragSource) {
-            final DocumentDragSource dds = (DocumentDragSource)dragSource;
-            hitObject = dds.getHitObject();
-            hitX = dds.getHitX();
-            hitY = dds.getHitY();
-        } else {
-            hitObject = draggedObjects.get(0);
-            hitX = 0.0;
-            hitY = 0.0;
-        }
+        final FXOMObject hitObject = dragSource.getHitObject();
+        final double hitX = dragSource.getHitX();
+        final double hitY = dragSource.getHitY();
         final FXOMObject currentParent = hitObject.getParentObject();
         
         final BatchJob result;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/drag/target/GridPaneDropTarget.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.drag.target;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.source.AbstractDragSource;
+import com.oracle.javafx.scenebuilder.kit.editor.job.BatchJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.DeleteObjectJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.InsertAsSubComponentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2.GridSnapshot;
+import com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2.InsertColumnJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2.MoveCellContentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.v2.ClearSelectionJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.v2.UpdateSelectionJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignHierarchyMask;
+import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
+import com.oracle.javafx.scenebuilder.kit.util.GridBounds;
+import java.util.List;
+import javafx.scene.Node;
+import javafx.scene.layout.GridPane;
+
+/**
+ *
+ */
+public class GridPaneDropTarget extends AbstractDropTarget {
+    
+    public enum ColumnArea {
+        LEFT, CENTER, RIGHT
+    }
+    
+    public enum RowArea {
+        TOP, CENTER, BOTTOM
+    }
+
+    private final FXOMObject targetGridPane;
+    private final int targetColumnIndex;
+    private final int targetRowIndex;
+    private final ColumnArea targetColumnArea;
+    private final RowArea targetRowArea;
+
+    public GridPaneDropTarget(FXOMObject targetGridPane, 
+            int columnIndex, int rowIndex, 
+            ColumnArea targetColumnArea, RowArea targetRowArea) {
+        assert targetGridPane != null;
+        assert targetGridPane.getSceneGraphObject() instanceof GridPane;
+        assert columnIndex >= 0;
+        assert rowIndex >= 0;
+        
+        this.targetGridPane = targetGridPane;
+        this.targetColumnIndex = columnIndex;
+        this.targetRowIndex = rowIndex;
+        this.targetColumnArea = targetColumnArea;
+        this.targetRowArea = targetRowArea;
+    }
+
+    public int getTargetColumnIndex() {
+        return targetColumnIndex;
+    }
+
+    public int getTargetRowIndex() {
+        return targetRowIndex;
+    }
+
+    public ColumnArea getTargetColumnArea() {
+        return targetColumnArea;
+    }
+
+    public RowArea getTargetRowArea() {
+        return targetRowArea;
+    }
+    
+    /*
+     * AbstractDropTarget
+     */
+    @Override
+    public FXOMObject getTargetObject() {
+        return targetGridPane;
+    }
+
+    @Override
+    public boolean acceptDragSource(AbstractDragSource dragSource) {
+        assert dragSource != null;
+        
+        final boolean result;
+        if (dragSource.getDraggedObjects().isEmpty()) {
+            result = false;
+        } else {
+            final DesignHierarchyMask m = new DesignHierarchyMask(targetGridPane);
+            if (m.isAcceptingSubComponent(dragSource.getDraggedObjects())) {
+                final FXOMObject draggedObject0 = dragSource.getDraggedObjects().get(0);
+                assert draggedObject0.getSceneGraphObject() instanceof Node;
+                
+                final Node draggedNode0 = (Node) draggedObject0.getSceneGraphObject();
+                final Integer columIndexObj = GridPane.getColumnIndex(draggedNode0);
+                final Integer rowIndexObj = GridPane.getRowIndex(draggedNode0);
+                final int currentColumnIndex = (columIndexObj == null) ? 0 : columIndexObj;
+                final int currentRowIndex = (rowIndexObj == null) ? 0 : rowIndexObj;
+                
+                final boolean sameContainer 
+                        = targetGridPane == draggedObject0.getParentObject();
+                final boolean sameColumnIndex
+                        = targetColumnIndex == currentColumnIndex;
+                final boolean sameRowIndex
+                        = targetRowIndex == currentRowIndex;
+                        
+                result = (sameContainer == false) 
+                        || (sameColumnIndex == false)
+                        || (sameRowIndex == false);
+            } else {
+                result = false;
+            }
+        }
+        
+        return result;
+    }
+
+    @Override
+    public Job makeDropJob(AbstractDragSource dragSource, EditorController editorController) {
+        assert acceptDragSource(dragSource); // (1)
+        assert editorController != null;
+        
+        final boolean shouldRefreshSceneGraph = true;
+        final BatchJob result = new BatchJob(editorController,
+                shouldRefreshSceneGraph, dragSource.makeDropJobDescription());
+        
+        final List<FXOMObject> draggedObjects = dragSource.getDraggedObjects();
+        final FXOMObject hitObject = dragSource.getHitObject();
+        final FXOMObject currentParent = hitObject.getParentObject();
+        final boolean reparenting = (currentParent != targetGridPane);
+        final GridPane gridPane = (GridPane) targetGridPane.getSceneGraphObject();
+
+        //  Steps:
+        //
+        //  1) snapshot grid related properties of dragged objects
+        //      => this must be done here because they will be lost by #1
+        //  2) clear the selection
+        //  3) remove drag source objects from their current parent (if any)
+        //  4) add new columns/rows in target grip pane as needed
+        //  5) add drag source objects to this drop target
+        //  6) restore grid related properties
+        //  7) select the dragged objects
+        //
+        //  Note: if source and target parents are the same, skip #2,#3,#5 and #7
+                        
+        // Step #1
+        final GridSnapshot gridSnapshot;
+        if ((currentParent != null) 
+                && (currentParent.getSceneGraphObject() instanceof GridPane)) {
+            gridSnapshot = new GridSnapshot(draggedObjects);
+        } else {
+            gridSnapshot = new GridSnapshot(draggedObjects, 1);
+        }
+            
+        if (reparenting) {
+            
+            // Step #2
+            result.addSubJob(new ClearSelectionJob(editorController));
+            
+            // Step #3
+            if (currentParent != null) {
+                for (FXOMObject draggedObject : draggedObjects) {
+                    result.addSubJob(new DeleteObjectJob(draggedObject,
+                            editorController));
+                }
+            }
+        }
+        
+        // Step #4
+        final GridBounds snapshotBounds = gridSnapshot.getBounds();
+        final int hitColumnIndex = gridSnapshot.getColumnIndex(hitObject);
+        final int hitRowIndex = gridSnapshot.getRowIndex(hitObject);
+        final int destColumnIndex = (targetColumnArea == ColumnArea.RIGHT) ? targetColumnIndex+1 : targetColumnIndex;
+        final int destRowIndex = (targetRowArea == RowArea.BOTTOM) ? targetRowIndex+1 : targetRowIndex;
+        final int columnDelta = destColumnIndex - hitColumnIndex;
+        final int rowDelta = destRowIndex - hitRowIndex;
+        final GridBounds adjustedBounds = snapshotBounds.move(columnDelta, rowDelta);
+        
+        // Step #4.1 : columns
+        switch(targetColumnArea) {
+            case LEFT: 
+            case RIGHT: { // Insert columns at destColumnIndex
+                final int insertCount = snapshotBounds.getColumnSpan();
+                result.addSubJob(new InsertColumnJob(targetGridPane, 
+                        destColumnIndex, insertCount, editorController));
+                break;
+            }
+            case CENTER: {// Insert columns at right (first) and left ends if needed
+                final int targetColumnCount = Deprecation.getGridPaneColumnCount(gridPane);
+                if (adjustedBounds.getMaxColumnIndex() > targetColumnCount) {
+                    final int insertCount = adjustedBounds.getMaxColumnIndex() - targetColumnCount;
+                    result.addSubJob(new InsertColumnJob(targetGridPane, 
+                            targetColumnCount, insertCount, editorController));
+                }
+                if (adjustedBounds.getMinColumnIndex() < 0) {
+                    final int insertCount = -adjustedBounds.getMinColumnIndex();
+                    result.addSubJob(new InsertColumnJob(targetGridPane, 
+                            0, insertCount, editorController));
+                }
+                break;
+            }
+        }
+        
+        if (reparenting) {
+            
+            // Step #5
+            for (FXOMObject draggedObject : draggedObjects) {
+                final Job j = new InsertAsSubComponentJob(draggedObject, 
+                        targetGridPane, -1, editorController);
+                result.addSubJob(j);
+            }
+        }
+        
+        // Step #6
+        for (FXOMObject draggedObject : draggedObjects) {
+            assert draggedObject instanceof FXOMInstance; // Because (1)
+            result.addSubJob(new MoveCellContentJob((FXOMInstance) draggedObject,
+                    columnDelta, rowDelta, editorController));
+        }
+        
+        if (reparenting) {
+            // Step #7
+            result.addSubJob(new UpdateSelectionJob(draggedObjects, editorController));
+        }
+        
+        assert result.isExecutable();
+        
+        return result;
+    }
+    
+    
+}
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/i18n/SceneBuilderKit.properties	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/i18n/SceneBuilderKit.properties	Tue Dec 10 08:36:28 2013 +0100
@@ -168,8 +168,8 @@
 csspanel = CSS Analyzer
 csspanel.api.defaults.navigation = API (built-in)
 csspanel.api.origin = Node
-csspanel.caspian.defaults.navigation = FX Theme
-csspanel.caspian.origin = FX caspian stylesheet
+csspanel.fxtheme.defaults.navigation = FX Theme
+csspanel.fxtheme.origin = FX theme stylesheet
 csspanel.copy = Copy
 csspanel.inherited = inherited
 csspanel.no.matching.rule = No Matching Rule
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DeleteObjectSelectionJob.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DeleteObjectSelectionJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -38,6 +38,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -48,12 +49,21 @@
     public DeleteObjectSelectionJob(EditorController editorController) {
         super(editorController);
         
+    }
+
+    /*
+     * CompositeJob
+     */
+
+    @Override
+    protected List<Job> makeSubJobs() {
         final Selection selection = getEditorController().getSelection();
         assert selection.getGroup() instanceof ObjectSelectionGroup;
         final ObjectSelectionGroup osg = (ObjectSelectionGroup) selection.getGroup();
+        final List<Job> result = new ArrayList<>();
         
         // First we clear the selection
-        addSubJob(new ClearSelectionJob(getEditorController()));
+        result.add(new ClearSelectionJob(getEditorController()));
         
         // Next we make one DeleteObjectJob for each selected objects
         int cannotDeleteCount = 0;
@@ -61,7 +71,7 @@
             final DeleteObjectJob subJob
                     = new DeleteObjectJob(candidate, getEditorController());
             if (subJob.isExecutable()) {
-                addSubJob(subJob);
+                result.add(subJob);
             } else {
                 cannotDeleteCount++;
             }
@@ -70,14 +80,12 @@
         // If some objects cannot be deleted, then we clear all to
         // make this job not executable.
         if (cannotDeleteCount >= 1) {
-            clearSubJobs();
+            result.clear();
         }
+        
+        return result;
     }
 
-    /*
-     * CompositeJob
-     */
-
     @Override
     protected String makeDescription() {
         final String result;
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DuplicateSelectionJob.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/DuplicateSelectionJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -33,6 +33,8 @@
 
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
 import com.oracle.javafx.scenebuilder.kit.editor.job.v2.CompositeJob;
+import java.util.Collections;
+import java.util.List;
 
 /**
  *
@@ -41,16 +43,20 @@
 
     public DuplicateSelectionJob(EditorController editorController) {
         super(editorController);
-        
-        // TODO fix DTL-5649 : SB Kit: Menu commands
-        System.out.println("== DuplicateSelectionJob : "
-                + "build new FXOM Objects from selection ");
     }
 
     /*
      * CompositeJob
      */
     @Override
+    protected List<Job> makeSubJobs() {
+        // TODO fix DTL-5649 : SB Kit: Menu commands
+        System.out.println("== DuplicateSelectionJob : "
+                + "build new FXOM Objects from selection ");
+        return Collections.emptyList();
+    }
+
+    @Override
     protected String makeDescription() {
         return getClass().getSimpleName();
     }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/PasteJob.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/PasteJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -42,6 +42,7 @@
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
 import com.oracle.javafx.scenebuilder.kit.metadata.util.ClipboardDecoder;
 import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignHierarchyMask;
+import java.util.ArrayList;
 import java.util.List;
 import javafx.scene.input.Clipboard;
 
@@ -52,9 +53,17 @@
 
     public PasteJob(EditorController editorController) {
         super(editorController);
+    }
+
+    /*
+     * CompositeJob
+     */
+    
+    @Override
+    protected List<Job> makeSubJobs() {
+        final List<Job> result = new ArrayList<>();
         
-        
-        final FXOMDocument fxomDocument = editorController.getFxomDocument();
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
         if (fxomDocument != null) {
 
             // Retrieve the FXOMObjects from the clipboard
@@ -91,8 +100,8 @@
                     final SetDocumentRootJob subJob = new SetDocumentRootJob(
                             newObject0,
                             getEditorController());
-                    addSubJob(subJob);
-                    addSubJob(new UpdateSelectionJob(newObject0, editorController));
+                    result.add(subJob);
+                    result.add(new UpdateSelectionJob(newObject0, getEditorController()));
                 }
             } else {
                 // Build InsertAsSubComponent jobs
@@ -104,17 +113,16 @@
                                 targetObject,
                                 targetMask.getSubComponentCount(),
                                 getEditorController());
-                        addSubJob(subJob);
+                        result.add(subJob);
                     }
-                    addSubJob(new UpdateSelectionJob(newObjects, editorController));
+                    result.add(new UpdateSelectionJob(newObjects, getEditorController()));
                 }
             }
         }
+        
+        return result;
     }
 
-    /*
-     * CompositeJob
-     */
     
     @Override
     protected String makeDescription() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/GridSnapshot.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.util.GridBounds;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+public class GridSnapshot {
+    
+    private final Map<FXOMObject, GridSnapshotItem> items = new HashMap<>();
+    
+    public GridSnapshot(Collection<FXOMObject> fxomObjects) {
+        assert fxomObjects != null;
+        assert fxomObjects.isEmpty() == false; // (1)
+        
+        for (FXOMObject fxomObject : fxomObjects) {
+            assert items.containsKey(fxomObject) == false;
+            items.put(fxomObject, new GridSnapshotItem(fxomObject));
+        }
+    }
+    
+    public GridSnapshot(Collection<FXOMObject> fxomObjects, int columnCount) {
+        assert fxomObjects != null;
+        assert fxomObjects.isEmpty() == false;
+        assert columnCount >= 1;
+        
+        int columnIndex = 0;
+        int rowIndex = 0;
+        for (FXOMObject fxomObject : fxomObjects) {
+            items.put(fxomObject, new GridSnapshotItem(fxomObject, columnIndex, rowIndex));
+            columnIndex++;
+            if (columnIndex >= columnCount) {
+                columnIndex = 0;
+                rowIndex++;
+            }
+        }
+    }
+    
+    public int getColumnIndex(FXOMObject fxomObject) {
+        assert fxomObject != null;
+        assert items.containsKey(fxomObject);
+        return items.get(fxomObject).getColumnIndex();
+    }
+    
+    public int getRowIndex(FXOMObject fxomObject) {
+        assert fxomObject != null;
+        assert items.containsKey(fxomObject);
+        return items.get(fxomObject).getRowIndex();
+    }
+    
+    public GridBounds getBounds() {
+        GridBounds result = null;
+        
+        for (Map.Entry<FXOMObject, GridSnapshotItem> e : items.entrySet()) {
+            if (result == null) {
+                result = e.getValue().getBounds();
+            } else {
+                result = result.union(e.getValue().getBounds());
+            }
+        }
+        
+        assert result != null; // Because (1)
+        
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/GridSnapshotItem.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.util.GridBounds;
+import javafx.geometry.HPos;
+import javafx.geometry.VPos;
+import javafx.scene.Node;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+
+/**
+ *
+ */
+public class GridSnapshotItem {
+        
+        private final Integer columnIndex;
+        private final Integer rowIndex;
+        private final Integer columnSpan;
+        private final Integer rowSpan;
+        private final Priority vgrow;
+        private final Priority hgrow;
+        private final VPos valignment;
+        private final HPos halignment;
+        
+        public GridSnapshotItem(FXOMObject fxomObject) {
+            assert fxomObject != null;
+            assert fxomObject.getSceneGraphObject() instanceof Node;
+            
+            final Node node = (Node) fxomObject.getSceneGraphObject();
+            this.columnIndex = GridPane.getColumnIndex(node);
+            this.rowIndex = GridPane.getRowIndex(node);
+            this.columnSpan = GridPane.getColumnSpan(node);
+            this.rowSpan = GridPane.getRowSpan(node);
+            this.vgrow = GridPane.getVgrow(node);
+            this.hgrow = GridPane.getHgrow(node);
+            this.valignment = GridPane.getValignment(node);
+            this.halignment = GridPane.getHalignment(node);
+        }
+
+        public GridSnapshotItem(FXOMObject fxomObject, int columnIndex, int rowIndex) {
+            assert fxomObject != null;
+            assert fxomObject.getSceneGraphObject() instanceof Node;
+            assert columnIndex >= 0;
+            assert rowIndex >= 0;
+            
+            this.columnIndex = columnIndex;
+            this.rowIndex = rowIndex;
+            this.columnSpan = null;
+            this.rowSpan = null;
+            this.vgrow = null;
+            this.hgrow = null;
+            this.valignment = null;
+            this.halignment = null;
+        }
+
+        public int getColumnIndex() {
+            return (columnIndex == null) ? 0 : columnIndex;
+        }
+
+        public int getRowIndex() {
+            return (rowIndex == null) ? 0 : rowIndex;
+        }
+
+        public int getColumnSpan() {
+            return (columnSpan == null) ? 1 : columnSpan;
+        }
+
+        public int getRowSpan() {
+            return (rowSpan == null) ? 1 : rowSpan;
+        }
+
+        public Priority getVgrow() {
+            return vgrow;
+        }
+
+        public Priority getHgrow() {
+            return hgrow;
+        }
+
+        public VPos getValignment() {
+            return valignment;
+        }
+
+        public HPos getHalignment() {
+            return halignment;
+        }
+        
+        public GridBounds getBounds() {
+            final int actualColumnIndex = (columnIndex == null) ? 0 : columnIndex;
+            final int actualRowIndex = (rowIndex == null) ? 0 : rowIndex;
+            
+            final int actualColumnSpan;
+            if ((columnSpan == null) || (columnSpan == GridPane.REMAINING)) {
+                actualColumnSpan = 1;
+            } else {
+                actualColumnSpan = columnSpan;
+            }
+            final int actualRowSpan;
+            if ((rowSpan == null) || (rowSpan == GridPane.REMAINING)) {
+                actualRowSpan = 1;
+            } else {
+                actualRowSpan = rowSpan;
+            }
+            
+            return new GridBounds(actualColumnIndex, actualRowIndex, actualColumnSpan, actualRowSpan);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/InsertColumnConstraintsJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.value.list.ColumnConstraintsListPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import java.util.Collections;
+import java.util.List;
+import javafx.scene.layout.ColumnConstraints;
+import javafx.scene.layout.GridPane;
+
+/**
+ *
+ */
+public class InsertColumnConstraintsJob extends Job {
+
+    private static final ColumnConstraintsListPropertyMetadata columnContraintsMeta =
+            new ColumnConstraintsListPropertyMetadata(
+                new PropertyName("columnConstraints"), //NOI18N
+                true, /* readWrite */
+                Collections.emptyList(), /* defaultValue */
+                InspectorPath.UNUSED);
+
+    private final FXOMInstance gridPaneObject;
+    private final int columnIndex;
+    private final int insertCount;
+
+    public InsertColumnConstraintsJob(FXOMObject gridPaneObject, 
+            int columnIndex, int insertCount, EditorController editorController) {
+        super(editorController);
+        
+        assert gridPaneObject instanceof FXOMInstance;
+        assert gridPaneObject.getSceneGraphObject() instanceof GridPane;
+        assert columnIndex >= 0;
+        assert columnIndex < columnContraintsMeta.getValue((FXOMInstance)gridPaneObject).size();
+        assert insertCount >= 1;
+        
+        this.gridPaneObject = (FXOMInstance)gridPaneObject;
+        this.columnIndex = columnIndex;
+        this.insertCount = insertCount;
+    }
+
+    /*
+     * Job
+     */
+    @Override
+    public boolean isExecutable() {
+        return true;
+    }
+
+    @Override
+    public void execute() {
+        // Same as redo()
+        redo();
+    }
+
+    @Override
+    public void undo() {
+        final List<ColumnConstraints> constraintsList = columnContraintsMeta.getValue(gridPaneObject);
+        assert columnIndex < constraintsList.size();
+        for (int i = 0; i < insertCount; i++) {
+            constraintsList.remove(columnIndex);
+        }
+        columnContraintsMeta.setValue(gridPaneObject, constraintsList);
+    }
+
+    @Override
+    public void redo() {
+        final List<ColumnConstraints> constraintsList = columnContraintsMeta.getValue(gridPaneObject);
+        final ColumnConstraints template;
+        if (columnIndex >= 1) {
+            template = constraintsList.get(columnIndex-1);
+        } else {
+            template = null;
+        }
+        for (int i = 0; i < insertCount; i++) {
+            constraintsList.add(columnIndex, makeColumnConstraints(template));
+        }
+        columnContraintsMeta.setValue(gridPaneObject, constraintsList);
+    }
+
+    @Override
+    public String getDescription() {
+        return getClass().getSimpleName();
+    }
+    
+    
+    /*
+     * Private
+     */
+    
+    private ColumnConstraints makeColumnConstraints(ColumnConstraints template) {
+        final ColumnConstraints result = new ColumnConstraints();
+        if (columnIndex >= 1) {
+            result.setFillWidth(template.isFillWidth());
+            result.setHalignment(template.getHalignment());
+            result.setHgrow(template.getHgrow());
+            result.setMaxWidth(template.getMaxWidth());
+            result.setMinWidth(template.getMinWidth());
+            result.setPercentWidth(template.getPercentWidth());
+            result.setPrefWidth(template.getPrefWidth());
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/InsertColumnJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.v2.CompositeJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.value.list.ColumnConstraintsListPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javafx.scene.layout.GridPane;
+
+/**
+ *
+ */
+public class InsertColumnJob extends CompositeJob {
+
+    private static final ColumnConstraintsListPropertyMetadata columnContraintsMeta =
+            new ColumnConstraintsListPropertyMetadata(
+                new PropertyName("columnConstraints"), //NOI18N
+                true, /* readWrite */
+                Collections.emptyList(), /* defaultValue */
+                InspectorPath.UNUSED);
+
+    private final FXOMInstance gridPaneObject;
+    private final int columnIndex;
+    private final int insertCount;
+
+    public InsertColumnJob(FXOMObject gridPaneObject, 
+            int columnIndex, int insertCount, EditorController editorController) {
+        super(editorController);
+        
+        assert gridPaneObject instanceof FXOMInstance;
+        assert gridPaneObject.getSceneGraphObject() instanceof GridPane;
+        assert columnIndex >= 0;
+        assert columnIndex < columnContraintsMeta.getValue((FXOMInstance)gridPaneObject).size();
+        assert insertCount >= 1;
+        
+        this.gridPaneObject = (FXOMInstance)gridPaneObject;
+        this.columnIndex = columnIndex;
+        this.insertCount = insertCount;
+    }
+
+    /*
+     * CompositeJob
+     */
+    
+    @Override
+    protected List<Job> makeSubJobs() {
+        final List<Job> result = new ArrayList<>();
+        
+        final Job insertJob 
+                = new InsertColumnConstraintsJob(gridPaneObject, columnIndex, insertCount, getEditorController());
+        result.add(insertJob);
+        
+        final Job moveJob
+                = new MoveColumnContentJob(gridPaneObject, columnIndex, +insertCount, getEditorController());
+        if (moveJob.isExecutable()) {
+            result.add(moveJob);
+        } // else column is empty : no children to move
+        
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName();
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/MoveCellContentJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.value.IntegerPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import javafx.scene.Node;
+import javafx.scene.layout.GridPane;
+
+/**
+ *
+ */
+public class MoveCellContentJob extends Job {
+    
+    private static final IntegerPropertyMetadata columnIndexMeta =
+            new IntegerPropertyMetadata(
+                new PropertyName("columnIndex", GridPane.class), //NOI18N
+                true, /* readWrite */
+                0, /* defaultValue */
+                InspectorPath.UNUSED);
+    private static final IntegerPropertyMetadata rowIndexMeta =
+            new IntegerPropertyMetadata(
+                new PropertyName("rowIndex", GridPane.class), //NOI18N
+                true, /* readWrite */
+                0, /* defaultValue */
+                InspectorPath.UNUSED);
+    
+    private final FXOMInstance fxomObject;
+    private final int columnIndexDelta;
+    private final int rowIndexDelta;
+    private int oldColumnIndex = -1;
+    private int oldRowIndex = -1;
+
+    public MoveCellContentJob(FXOMInstance fxomObject, 
+            int columnIndexDelta, int rowIndexDelta, 
+            EditorController editorController) {
+        super(editorController);
+        assert fxomObject != null;
+        assert fxomObject.getSceneGraphObject() instanceof Node;
+        
+        this.fxomObject = fxomObject;
+        this.columnIndexDelta = columnIndexDelta;
+        this.rowIndexDelta = rowIndexDelta;
+    }
+
+    /*
+     * Job
+     */
+    
+    @Override
+    public boolean isExecutable() {
+        return true;
+    }
+
+    @Override
+    public void execute() {
+        oldColumnIndex = columnIndexMeta.getValue(fxomObject);
+        oldRowIndex = rowIndexMeta.getValue(fxomObject);
+        
+        assert oldColumnIndex + columnIndexDelta >= 0;
+        assert oldRowIndex + rowIndexDelta >= 0;
+        
+        // Now same as redo()
+        redo();
+    }
+
+    @Override
+    public void undo() {
+        assert isExecutable();
+
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        fxomDocument.beginUpdate();
+        columnIndexMeta.setValue(fxomObject, oldColumnIndex);
+        rowIndexMeta.setValue(fxomObject, oldRowIndex);
+        fxomDocument.endUpdate();
+    }
+
+    @Override
+    public void redo() {
+        assert isExecutable();
+
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        fxomDocument.beginUpdate();
+        columnIndexMeta.setValue(fxomObject, oldColumnIndex + columnIndexDelta);
+        rowIndexMeta.setValue(fxomObject, oldRowIndex + rowIndexDelta);
+        fxomDocument.endUpdate();
+    }
+
+    @Override
+    public String getDescription() {
+        return getClass().getSimpleName();
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/gridpane/v2/MoveColumnContentJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.job.gridpane.v2;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.v2.CompositeJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.value.IntegerPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignHierarchyMask;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import java.util.ArrayList;
+import java.util.List;
+import javafx.scene.layout.GridPane;
+
+/**
+ *
+ */
+public class MoveColumnContentJob extends CompositeJob {
+    
+    private final IntegerPropertyMetadata columnIndexMeta =
+            new IntegerPropertyMetadata(
+                new PropertyName("columnIndex", GridPane.class), //NOI18N
+                true, /* readWrite */
+                0, /* defaultValue */
+                InspectorPath.UNUSED);
+
+    private final FXOMInstance gridPaneObject;
+    private final int movingColumnIndex;
+    private final int columnIndexDelta;
+
+    public MoveColumnContentJob(FXOMObject gridPaneObject, int movingColumnIndex, int columnIndexDelta, EditorController editorController) {
+        super(editorController);
+        assert gridPaneObject instanceof FXOMInstance;
+        assert gridPaneObject.getSceneGraphObject() instanceof GridPane;
+        assert movingColumnIndex >= 0;
+        
+        this.gridPaneObject = (FXOMInstance)gridPaneObject;
+        this.movingColumnIndex = movingColumnIndex;
+        this.columnIndexDelta = columnIndexDelta;
+    }
+
+
+    
+    
+    /*
+     * CompositeJob
+     */
+    
+    @Override
+    protected List<Job> makeSubJobs() {
+        final List<Job> result = new ArrayList<>();
+        
+        final DesignHierarchyMask m = new DesignHierarchyMask(gridPaneObject);
+        assert m.isAcceptingSubComponent();
+        
+        for (int i = 0, count = m.getSubComponentCount(); i <  count; i++) {
+            assert m.getSubComponentAtIndex(i) instanceof FXOMInstance; // Because children of GridPane are nodes
+            final FXOMInstance child = (FXOMInstance) m.getSubComponentAtIndex(i);
+            if (columnIndexMeta.getValue(child) == movingColumnIndex) {
+                // child belongs to column at movingColumnIndex
+                final MoveCellContentJob subJob 
+                        = new MoveCellContentJob(child, columnIndexDelta, 0, getEditorController());
+                result.add(subJob);
+            }
+        }
+        
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName();
+    }
+    
+}
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/v2/CompositeJob.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/v2/CompositeJob.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,7 +35,6 @@
 import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -44,47 +43,36 @@
  */
 public abstract class CompositeJob extends Job {
 
-    private final List<Job> subJobs = new ArrayList<>();
-    private boolean shouldRefreshSceneGraph;
-    private boolean shouldUpdateSelection;
+    private final boolean shouldRefreshSceneGraph;
+    private final boolean shouldUpdateSelection;
+    private List<Job> subJobs;
     private String description;
 
     public CompositeJob(EditorController editorController) {
+        this(editorController, true ,true);
+    }
+    
+    public CompositeJob(EditorController editorController, 
+            boolean shouldRefreshSceneGraph, boolean shouldUpdateSelection) {
         super(editorController);
-        this.shouldRefreshSceneGraph = true;
-        this.shouldUpdateSelection = true;
+        this.shouldRefreshSceneGraph = shouldRefreshSceneGraph;
+        this.shouldUpdateSelection = shouldUpdateSelection;
     }
     
     public List<Job> getSubJobs() {
-        return Collections.unmodifiableList(subJobs);
+        if (subJobs == null) {
+            subJobs = makeSubJobs();
+            assert subJobs != null;
+            subJobs = Collections.unmodifiableList(subJobs);
+        }
+        return subJobs;
     }
     
     /*
-     * For subclasses
+     * To be implemented by subclasses
      */
     
-    protected void addSubJob(Job subJob) {
-        assert subJob != null;
-        this.subJobs.add(subJob);
-    }
-
-    protected void addSubJobs(List<Job> subJobs) {
-        assert subJobs != null;
-        this.subJobs.addAll(subJobs);
-    }
-    
-    protected void clearSubJobs() {
-        this.subJobs.clear();
-    }
-    
-    protected void setShouldRefreshSceneGraph(boolean shouldRefreshSceneGraph) {
-        this.shouldRefreshSceneGraph = shouldRefreshSceneGraph;
-    }
-    
-    protected void setShouldUpdateSelection(boolean shouldUpdateSelection) {
-        this.shouldUpdateSelection = shouldUpdateSelection;
-    }
-    
+    protected abstract List<Job> makeSubJobs();
     protected abstract String makeDescription();
     
     /*
@@ -93,7 +81,7 @@
     
     @Override
     public boolean isExecutable() {
-        return subJobs.isEmpty() == false;
+        return getSubJobs().isEmpty() == false;
     }
 
     @Override
@@ -106,7 +94,7 @@
         if (shouldRefreshSceneGraph) {
             fxomDocument.beginUpdate();
         }
-        for (Job subJob : subJobs) {
+        for (Job subJob : getSubJobs()) {
             subJob.execute();
         }
         if (shouldRefreshSceneGraph) {
@@ -127,8 +115,8 @@
         if (shouldRefreshSceneGraph) {
             fxomDocument.beginUpdate();
         }
-        for (int i = subJobs.size()-1; i >= 0; i--) {
-            subJobs.get(i).undo();
+        for (int i = getSubJobs().size()-1; i >= 0; i--) {
+            getSubJobs().get(i).undo();
         }
         if (shouldRefreshSceneGraph) {
             fxomDocument.endUpdate();
@@ -149,7 +137,7 @@
         if (shouldRefreshSceneGraph) {
             fxomDocument.beginUpdate();
         }
-        for (Job subJob : subJobs) {
+        for (Job subJob : getSubJobs()) {
             subJob.redo();
         }
         if (shouldRefreshSceneGraph) {
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/AbstractDecoration.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/AbstractDecoration.java	Tue Dec 10 08:36:28 2013 +0100
@@ -158,7 +158,8 @@
     
     public abstract Bounds getSceneGraphObjectBounds();
     public abstract Transform getSceneGraphToSceneTransform();
-    public abstract Point2D sceneGraphObjectToDecoration(double x, double y);
+    public abstract Point2D sceneGraphObjectToScene(double x, double y);
+    public abstract Point2D sceneToSceneGraphObject(double x, double y);
     protected abstract void startListeningToSceneGraphObject();
     protected abstract void stopListeningToSceneGraphObject();
     protected abstract void layoutDecoration();
@@ -168,6 +169,10 @@
      * Utilities for subclasses
      */
     
+    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+        return getRootNode().sceneToLocal(sceneGraphObjectToScene(x, y));
+    }
+            
     protected void startListeningToLayoutBounds(Node node) {
         assert node != null;
         node.layoutBoundsProperty().addListener(layoutBoundsListener);
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanel.css	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanel.css	Tue Dec 10 08:36:28 2013 +0100
@@ -165,6 +165,18 @@
     -fx-fill: rgba(0,0,0,0.4);
 }
 
+.gap.hilit {
+    -fx-stroke: rgba(0,0,0,0.4);
+    -fx-stroke-line-cap: butt;
+//  -fx-stroke-width is setup programmatically
+}
+
+.gap.empty {
+    -fx-stroke: rgba(0,0,0,0.4);
+    -fx-stroke-line-cap: butt;
+    -fx-stroke-dash-array: 3 3;
+}
+
 .tray.selected {
     -fx-border-color: rgba(255, 255, 255, 0.4), rgba(0, 0, 0, 1), rgba(255, 255, 255, 0.5);
     -fx-background-color: yellow;
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/ContentPanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,6 +35,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform;
 import com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform.Theme;
 import com.oracle.javafx.scenebuilder.kit.editor.drag.target.AbstractDropTarget;
+import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.mode.AbstractModeController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.mode.EditModeController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.mode.PickModeController;
@@ -140,7 +141,6 @@
     private boolean tracingEvents; // For debugging purpose
     
     private final Picker picker = new Picker();
-    private Node lastHitNode; // Updated by pick()
     
     /*
      * Public
@@ -152,7 +152,7 @@
      * @param editorController the editor controller (never null).
      */
     public ContentPanelController(EditorController editorController) {
-        super(ContentPanelController.class.getResource("ContentPanel.fxml"), editorController);
+        super(ContentPanelController.class.getResource("ContentPanel.fxml"), I18N.getBundle(), editorController);
         this.editModeController = new EditModeController(this);
         this.pickModeController = new PickModeController(this);
         
@@ -432,13 +432,10 @@
             final Node startNode = (Node) startObject.getSceneGraphObject();
             final List<Node> hitNodes = picker.pick(startNode, sceneX, sceneY);
             if (hitNodes == null) {
-                lastHitNode = null;
                 result = null;
             } else {
                 assert hitNodes.isEmpty() == false;
                 
-                lastHitNode = hitNodes.get(0);
-
                 FXOMObject hitObject = null;
                 Node hitNode = null;
                 final Iterator<Node> it = hitNodes.iterator();
@@ -454,7 +451,6 @@
             }
             
         } else {
-            lastHitNode = null;
             result = null;
         }
         
@@ -462,15 +458,6 @@
     }
     
     /**
-     * Returns null or the last node picked by pick() method.
-     * 
-     * @return  null or the last node picked by pick() method.
-     */
-    public Node getLastHitNode() {
-        return lastHitNode;
-    }
-    
-    /**
      * Returns the FXOMObject which matches (sceneGraphNode, sceneX, sceneY).
      * 
      * @param sceneGraphNode scene graph node
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/HudWindow.css	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/HudWindow.css	Tue Dec 10 08:36:28 2013 +0100
@@ -29,6 +29,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 .hud-background {
     -fx-background-color: rgb(0,0,0,0.7);
     -fx-background-radius: 6;
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/GridPaneDriver.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/GridPaneDriver.java	Tue Dec 10 08:36:28 2013 +0100
@@ -31,13 +31,23 @@
  */
 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver;
 
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.AbstractDropTarget;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget.ColumnArea;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget.RowArea;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.handles.AbstractHandles;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane.GridPaneHandles;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane.GridPaneTring;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.resizer.AbstractResizer;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.resizer.RegionResizer;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.tring.AbstractTring;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.util.BoundsUtils;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.Region;
 
@@ -46,6 +56,8 @@
  */
 public class GridPaneDriver extends AbstractNodeDriver {
 
+    private static final double MATCH_DIST = 4;
+
     public GridPaneDriver(ContentPanelController contentPanelController) {
         super(contentPanelController);
     }
@@ -61,6 +73,14 @@
         return new GridPaneHandles(contentPanelController, (FXOMInstance)fxomObject);
     }
 
+    @Override
+    public AbstractTring<?> makeTring(AbstractDropTarget dropTarget) {
+        assert dropTarget != null;
+        assert dropTarget.getTargetObject() instanceof FXOMInstance;
+        assert dropTarget.getTargetObject().getSceneGraphObject() instanceof GridPane;
+        return new GridPaneTring(contentPanelController, (FXOMInstance) dropTarget.getTargetObject());
+    }
+
     
     @Override
     public AbstractResizer<?> makeResizer(FXOMObject fxomObject) {
@@ -68,4 +88,206 @@
         return new RegionResizer((Region) fxomObject.getSceneGraphObject());
     }
     
+    
+    @Override
+    public AbstractDropTarget makeDropTarget(FXOMObject fxomObject, double sceneX, double sceneY) {
+        assert fxomObject.getSceneGraphObject() instanceof GridPane;
+        assert fxomObject instanceof FXOMInstance;
+        
+        final AbstractDropTarget result;
+        
+        final FXOMInstance fxomInstance = (FXOMInstance) fxomObject;
+        final GridPane gridPane = (GridPane) fxomInstance.getSceneGraphObject();
+        final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
+        final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
+        
+        
+        /*
+         *
+         *               
+         *     |--------|-------------|-----------|-----------------------|--|
+         *         0           1            2                 3            4
+         *     +-------------------------------------------------------------+ -
+         *     |                                                             | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | |
+         *     |  |     |   |         |   |       |   |                   |  | | 0
+         *     |  | 0,0 |   |   1,0   |   |  2,0  |   |        3,0        |  | |
+         *     |  |     |   |         |   |       |   |                   |  | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | -
+         *     |                                                             | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | |
+         *     |  |     |   |         |   |       |   |                   |  | | 1
+         *     |  | 0,1 |   |   1,1   |   |  2,1  |   |        3,1        |  | |
+         *     |  |     |   |         |   |       |   |                   |  | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | -
+         *     |         (A)                                                 | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | |
+         *     |  |     |   |         |   |       |   |                   |  | | 2
+         *     |  | 0,2 |   |   1,2   |   |  2,2  |   |        3,2        |  | |
+         *     |  |     |   |   (B)   |   |       |   |                   |  | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | -
+         *     |                                                             | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | |
+         *     |  |     |   |         |   |       |   |                   |  | | 3
+         *     |  | 0,3 |   |   1,3   |   |  2,3  |   |        3,3        |  | |
+         *     |  |     |   |         |   |       |   |                   |  | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | -
+         *     |                                                             | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | |
+         *     |  |     |   |         |   |       |   |                   |  | | 4
+         *     |  | 0,4 |   |   1,4   |   |  2,4  |   |        3,4        |  | |
+         *     |  |     |   |         |   |       |   |                   |  | |
+         *     |  +-----+   +---------+   +-------+   +-------------------+  | -
+         *     |                                                             | | 5
+         *     +-------------------------------------------------------------+ -
+         */
+        
+        if ((rowCount == 0) || (columnCount == 0)) {
+            result = new GridPaneDropTarget(fxomInstance, 0, 0, ColumnArea.CENTER, RowArea.CENTER);
+        } else {
+        
+            final Point2D hitPoint = gridPane.sceneToLocal(sceneX, sceneY);
+            final double hitX = hitPoint.getX();
+            final double hitY = hitPoint.getY();
+            final int targetColumnIndex, targetRowIndex;
+            final double targetCellX, targetCellY;
+            
+            // Searches the column where hitX resides
+            int c = 0;
+            Bounds cellBounds = Deprecation.getGridPaneCellBounds(gridPane, c++, 0);
+            double columnMaxX = cellBounds.getMaxX();
+            while ((columnMaxX < hitX) && (c < columnCount)) {
+                cellBounds = Deprecation.getGridPaneCellBounds(gridPane, c++, 0);                
+                columnMaxX = cellBounds.getMaxX();
+            }
+            if (hitX <= columnMaxX) { // hitX is in column 'c-1'
+                assert hitX <= columnMaxX;
+                targetColumnIndex = c-1;
+                targetCellX = hitX;
+            } else { // hitX is past the last column
+                targetColumnIndex = columnCount;
+                targetCellX = 0.0;
+            }
+            
+            // Searches the row where hitY resides
+            int r = 0;
+            cellBounds = Deprecation.getGridPaneCellBounds(gridPane, 0, r++);
+            double rowMaxY = cellBounds.getMaxY();
+            while ((rowMaxY < hitY) && (r < rowCount)) {
+                cellBounds = Deprecation.getGridPaneCellBounds(gridPane, 0, r++);
+                rowMaxY = cellBounds.getMaxY();
+            }
+            if (hitY <= rowMaxY) { // hitY is in row 'r-1'
+                assert hitY <= rowMaxY;
+                targetRowIndex = r-1;
+                targetCellY = hitY;
+            } else {
+                targetRowIndex = rowCount;
+                targetCellY = 0.0;
+            }
+            
+            final Bounds targetCellBounds 
+                    = Deprecation.getGridPaneCellBounds(gridPane, targetColumnIndex, targetRowIndex);
+            final BoundsUtils.EdgeInfo edgeInfo
+                    = BoundsUtils.distanceToEdges(targetCellBounds, targetCellX, targetCellY, gridPane);
+            
+            /*
+             *            hgap          targetCellBounds.width
+             *        +----------+----------------------------------+
+             *        |                                             |
+             *        |                                             |
+             *        +          +----------------------------------+
+             *        |          |                                  |
+             *        |          |    +........................+    |
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |    (A)   |(B) .           (C)          . (D)|
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |          |    +........................+    |
+             *        |          |                                  |
+             *        +----------+----------------------------------+
+             * 
+             *        (A) ColumnArea.LEFT
+             *        (B) ColumnArea.LEFT
+             *        (C) ColumnArea.CENTER
+             *        (D) ColumnArea.RIGHT
+             */
+            
+            final ColumnArea targetColumnArea;
+            if (targetColumnIndex < columnCount) {
+                if (targetCellX < targetCellBounds.getMinX()) {
+                    targetColumnArea= ColumnArea.LEFT; // (A)
+                } else if (edgeInfo == null) {
+                    targetColumnArea= ColumnArea.CENTER; // cell bounds are empty
+                } else {
+                    final boolean eastMatch = edgeInfo.getEastDistance() < MATCH_DIST;
+                    final boolean westMatch = edgeInfo.getWestDistance() < MATCH_DIST;
+                    if (westMatch) {
+                        targetColumnArea= ColumnArea.LEFT; // (B)
+                    } else if (eastMatch) {
+                        targetColumnArea= ColumnArea.RIGHT; // (D)
+                    } else {
+                        targetColumnArea= ColumnArea.CENTER; // (C)
+                    }
+                }
+            } else {
+                targetColumnArea = ColumnArea.CENTER;
+            }
+            
+            /*
+             *        +----------+----------------------------------+
+             *        |                                             |
+             * vgap   |                           (A)               |
+             *        |                                             |
+             *        +          +----------------------------------+
+             *        |          |                (B)               |
+             *        |          |    +........................+    |
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |          |    .           (C)          .    |
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |          |    .                        .    |
+             *        |          |    +........................+    |
+             *        |          |                (D)               |
+             *        +----------+----------------------------------+
+             * 
+             *        (A) RowArea.TOP
+             *        (B) RowArea.TOP
+             *        (C) RowArea.CENTER
+             *        (D) RowArea.BOTTOM
+             */
+            
+            final RowArea targetRowArea;
+            if (targetRowIndex < rowCount) {
+                if (targetCellY < targetCellBounds.getMinY()) {
+                    targetRowArea = RowArea.TOP; // (A)
+                } else if (edgeInfo == null) {
+                    targetRowArea = RowArea.CENTER; // cell bounds are empty
+                } else {
+                    final boolean northMatch = edgeInfo.getNorthDistance() < MATCH_DIST;
+                    final boolean southMatch = edgeInfo.getSouthDistance() < MATCH_DIST;
+                    if (northMatch) {
+                        targetRowArea= RowArea.TOP; // (B)
+                    } else if (southMatch) {
+                        targetRowArea= RowArea.BOTTOM; // (D)
+                    } else {
+                        targetRowArea= RowArea.CENTER; // (C)
+                    }
+                }
+            } else {
+                targetRowArea = RowArea.CENTER;
+            }
+            
+            result = new GridPaneDropTarget(fxomInstance, 
+                    targetColumnIndex, targetRowIndex, 
+                    targetColumnArea, targetRowArea);
+        }
+        
+        
+        return result;
+    }
+    
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -47,7 +47,8 @@
  */
 public class GridPaneHandles extends AbstractNodeHandles<GridPane> {
     
-    private final GridPaneMosaic mosaic = new GridPaneMosaic();
+    private final GridPaneMosaic mosaic 
+            = new GridPaneMosaic("handles", true /* shouldShowTray */); //NOI18N
     
     public GridPaneHandles(ContentPanelController contentPanelController,
             FXOMInstance fxomInstance) {
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneMosaic.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneMosaic.java	Tue Dec 10 08:36:28 2013 +0100
@@ -45,7 +45,9 @@
 import javafx.scene.control.Label;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.Region;
+import javafx.scene.shape.Line;
 import javafx.scene.shape.Path;
+import javafx.scene.shape.Rectangle;
 
 /**
  *
@@ -59,29 +61,70 @@
     
     private final Group topGroup = new Group();
     private final Path gridPath = new Path();
+    private final Group hgapLinesGroup = new Group();
+    private final Group vgapLinesGroup = new Group();
     private final Group northTrayGroup = new Group();
     private final Group southTrayGroup = new Group();
     private final Group westTrayGroup = new Group();
     private final Group eastTrayGroup = new Group();
+    private final Rectangle targetCellShadow = new Rectangle();
+    private final Line targetGapShadowV = new Line();
+    private final Line targetGapShadowH= new Line();
     
     private final Quad gridAreaQuad = new Quad();
     private final List<Quad> gridHoleQuads = new ArrayList<>();
 
+    private final String baseStyleClass;
+    private final boolean shouldShowTrays;
+    
     private GridPane gridPane;
+    private int columnCount;
+    private int rowCount;
+    private List<Bounds> cellBounds = new ArrayList<>();
     private final Set<Integer> selectedColumnIndexes = new HashSet<>();
     private final Set<Integer> selectedRowIndexes = new HashSet<>();
+    private int targetColumnIndex = -1;
+    private int targetRowIndex = -1;
+    private int targetGapColumnIndex = -1;
+    private int targetGapRowIndex = -1;
     
-    public GridPaneMosaic() {
+    public GridPaneMosaic(String baseStyleClass, boolean shouldShowTrays) {
+        assert baseStyleClass != null;
+        
+        this.baseStyleClass = baseStyleClass;
+        this.shouldShowTrays = shouldShowTrays;
+        
         final List<Node> topChildren = topGroup.getChildren();
         topChildren.add(gridPath);
+        topChildren.add(hgapLinesGroup);
+        topChildren.add(vgapLinesGroup);
         topChildren.add(northTrayGroup);
         topChildren.add(southTrayGroup);
         topChildren.add(westTrayGroup);
         topChildren.add(eastTrayGroup);
+        topChildren.add(targetCellShadow);
+        topChildren.add(targetGapShadowV);
+        topChildren.add(targetGapShadowH);
         gridAreaQuad.addToPath(gridPath);
         
         gridPath.setMouseTransparent(true);
         gridPath.getStyleClass().add("gap");
+        gridPath.getStyleClass().add(baseStyleClass);
+        
+        targetCellShadow.setMouseTransparent(true);
+        targetCellShadow.getStyleClass().add("gap");
+        targetCellShadow.getStyleClass().add("selected");
+        targetCellShadow.getStyleClass().add(baseStyleClass);
+        
+        targetGapShadowV.setMouseTransparent(true);
+        targetGapShadowV.getStyleClass().add("gap");
+        targetGapShadowV.getStyleClass().add("hilit");
+        targetGapShadowV.getStyleClass().add(baseStyleClass);
+        
+        targetGapShadowH.setMouseTransparent(true);
+        targetGapShadowH.getStyleClass().add("gap");
+        targetGapShadowH.getStyleClass().add("hilit");
+        targetGapShadowH.getStyleClass().add(baseStyleClass);
     }
 
     public Group getTopGroup() {
@@ -108,40 +151,73 @@
         selectedRowIndexes.addAll(indexes);
         update();
     }
+
+    public void setTargetCell(int targetColumnIndex, int targetRowIndex) {
+        assert (targetColumnIndex == -1) == (targetRowIndex == -1);
+        this.targetColumnIndex = targetColumnIndex;
+        this.targetRowIndex = targetRowIndex;
+        this.targetGapColumnIndex = -1;
+        this.targetGapRowIndex = -1;
+        update();
+    }
+    
+    public void setTargetGap(int targetGapColumnIndex, int targetGapRowIndex) {
+        assert (-1 <= targetGapColumnIndex) && (targetGapColumnIndex <= columnCount);
+        assert (-1 <= targetGapRowIndex) && (targetGapRowIndex <= rowCount);
+        
+        this.targetGapColumnIndex = targetGapColumnIndex;
+        this.targetGapRowIndex = targetGapRowIndex;
+        this.targetColumnIndex = -1;
+        this.targetRowIndex = -1;
+        update();
+    }
     
     public void update() {
-        final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
-        final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
-
-        final int actualColumnCount, actualRowCount;
+        
+        columnCount = Deprecation.getGridPaneColumnCount(gridPane);
+        rowCount = Deprecation.getGridPaneRowCount(gridPane);
         if ((columnCount == 0) || (rowCount == 0)) {
-            actualColumnCount = 0;
-            actualRowCount = 0;
-        } else {
-            actualColumnCount = columnCount;
-            actualRowCount = rowCount;
+            columnCount = rowCount = 0;
+        }
+        this.cellBounds.clear();
+        for (int c = 0; c < columnCount; c++) {
+            for (int r = 0; r < rowCount; r++) {
+                this.cellBounds.add(Deprecation.getGridPaneCellBounds(gridPane, c, r));
+            }
         }
         
         gridAreaQuad.setBounds(gridPane.getLayoutBounds());
-        adjustHoleItems(actualColumnCount, actualRowCount);
-        adjustTrayItems(northTrayGroup.getChildren(), "north", actualColumnCount);
-        adjustTrayItems(southTrayGroup.getChildren(), "south", actualColumnCount);
-        adjustTrayItems(westTrayGroup.getChildren(), "west", actualRowCount);
-        adjustTrayItems(eastTrayGroup.getChildren(), "east", actualRowCount);
+        adjustHoleItems();
+        adjustHGapLines();
+        adjustVGapLines();
+        if (shouldShowTrays) {
+            adjustTrayItems(northTrayGroup.getChildren(), "north", columnCount);
+            adjustTrayItems(southTrayGroup.getChildren(), "south", columnCount);
+            adjustTrayItems(westTrayGroup.getChildren(), "west", rowCount);
+            adjustTrayItems(eastTrayGroup.getChildren(), "east", rowCount);
+        }
         
-        if (actualColumnCount >= 1) {
-            assert actualRowCount >= 1;
+        if (columnCount >= 1) {
+            assert rowCount >= 1;
             
             updateHoleBounds();
-            updateNorthTrayBounds();
-            updateSouthTrayBounds();
-            updateWestTrayBounds();
-            updateEastTrayBounds();
+            updateHGapLines();
+            updateVGapLines();
+            
+            if (shouldShowTrays) {
+                updateNorthTrayBounds();
+                updateSouthTrayBounds();
+                updateWestTrayBounds();
+                updateEastTrayBounds();
 
-            updateSelection(northTrayGroup.getChildren(), selectedColumnIndexes);
-            updateSelection(southTrayGroup.getChildren(), selectedColumnIndexes);
-            updateSelection(westTrayGroup.getChildren(), selectedRowIndexes);
-            updateSelection(eastTrayGroup.getChildren(), selectedRowIndexes);
+                updateSelection(northTrayGroup.getChildren(), selectedColumnIndexes);
+                updateSelection(southTrayGroup.getChildren(), selectedColumnIndexes);
+                updateSelection(westTrayGroup.getChildren(), selectedRowIndexes);
+                updateSelection(eastTrayGroup.getChildren(), selectedRowIndexes);
+            }
+            
+            updateTargetCell();
+            updateTargetGap();
         }
     }
     
@@ -168,8 +244,8 @@
      */
     
     
-    private void adjustHoleItems(int actualColumnCount, int actualRowCount) {
-        final int holeCount = actualColumnCount * actualRowCount;
+    private void adjustHoleItems() {
+        final int holeCount = columnCount * rowCount;
         
         while (gridHoleQuads.size() < holeCount) {
             final Quad holeQuad = new Quad(false /* clockwise */); // Counterclockwise !!
@@ -183,6 +259,48 @@
         }
     }
     
+    
+    private void adjustHGapLines() {
+        final int hgapLineCount;
+        if (gridPane.getHgap() == 0) {
+            hgapLineCount = columnCount-1;
+        } else {
+            hgapLineCount = 0;
+        }
+        final List<Node> children = hgapLinesGroup.getChildren();
+        while (children.size() < hgapLineCount) {
+            children.add(makeGapLine());
+        }
+        while (children.size() > hgapLineCount) {
+            children.remove(0);
+        }
+    }
+    
+    private void adjustVGapLines() {
+        final int vgapLineCount;
+        if (gridPane.getVgap() == 0) {
+            vgapLineCount = rowCount-1;
+        } else {
+            vgapLineCount = 0;
+        }
+        final List<Node> children = vgapLinesGroup.getChildren();
+        while (children.size() < vgapLineCount) {
+            children.add(makeGapLine());
+        }
+        while (children.size() > vgapLineCount) {
+            children.remove(0);
+        }
+    }
+    
+    private Line makeGapLine() {
+        final Line result = new Line();
+        result.getStyleClass().add("gap");
+        result.getStyleClass().add("empty");
+        result.getStyleClass().add(baseStyleClass);
+        return result;
+    }
+    
+    
     private void adjustTrayItems(List<Node> trayChildren, String direction, int targetCount) {
         
         while (trayChildren.size() < targetCount) {
@@ -199,6 +317,7 @@
         final Label result = new Label();
         result.getStyleClass().add("tray");
         result.getStyleClass().add(direction);
+        result.getStyleClass().add(baseStyleClass);
         result.setText(String.valueOf(num));
         result.setMinWidth(Region.USE_PREF_SIZE);
         result.setMaxWidth(Region.USE_PREF_SIZE);
@@ -210,22 +329,57 @@
     
     
     private void updateHoleBounds() {
-        final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
-        final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
-        
         for (int c = 0; c < columnCount; c++) {
             for (int r = 0; r < rowCount; r++) {
-                final int holeIndex = c * rowCount + r;
-                final Bounds cb = Deprecation.getGridPaneCellBounds(gridPane, c, r);
-                gridHoleQuads.get(holeIndex).setBounds(cb);
+                final Bounds cb = getCellBounds(c, r);
+                gridHoleQuads.get(getCellIndex(c, r)).setBounds(cb);
             }
         }
     }
     
+    private void updateHGapLines() {
+        final List<Node> children = hgapLinesGroup.getChildren();
+        final int lineCount = children.size();
+        assert (lineCount == 0) || (lineCount == columnCount-1);
+        for (int i = 0; i < lineCount; i++) {
+            final Bounds topLeftCellBounds = getCellBounds(i, 0);
+            final Bounds topRightCellBounds = getCellBounds(i+1, 0);
+            final Bounds bottomLeftCellBounds = getCellBounds(i, rowCount-1);
+            final double startX = (topLeftCellBounds.getMaxX() + topRightCellBounds.getMinX()) / 2.0;
+            final double startY = topLeftCellBounds.getMinY();
+            final double endY = bottomLeftCellBounds.getMaxY();
+            final double snappedX = Math.round(startX) + 0.5;
+            final Line line = (Line) children.get(i);
+            line.setStartX(snappedX);
+            line.setStartY(startY);
+            line.setEndX(snappedX);
+            line.setEndY(endY);
+        }
+    }
+    
+    private void updateVGapLines() {
+        final List<Node> children = vgapLinesGroup.getChildren();
+        final int lineCount = children.size();
+        assert (lineCount == 0) || (lineCount == rowCount-1);
+        for (int i = 0; i < lineCount; i++) {
+            final Bounds topLeftCellBounds = getCellBounds(0, i);
+            final Bounds bottomLeftCellBounds = getCellBounds(0, i+1);
+            final Bounds topRightCellBounds = getCellBounds(columnCount-1, i);
+            final double startX = topLeftCellBounds.getMinX();
+            final double startY = (topLeftCellBounds.getMaxY() + bottomLeftCellBounds.getMinY()) / 2.0;
+            final double endX = topRightCellBounds.getMaxX();
+            final double snappedY = Math.round(startY) + 0.5;
+            final Line line = (Line) children.get(i);
+            line.setStartX(startX);
+            line.setStartY(snappedY);
+            line.setEndX(endX);
+            line.setEndY(snappedY);
+        }
+    }
+    
     
     private void updateNorthTrayBounds() {
         final List<Node> northTrayChildren = northTrayGroup.getChildren();
-        final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
         assert northTrayChildren.size() == columnCount;
         
         for (int c = 0; c < columnCount; c++) {
@@ -236,7 +390,7 @@
     
     private void updateNorthTrayBounds(int column, Label label) {
         final Bounds gb = gridPane.getLayoutBounds();
-        final Bounds cb = Deprecation.getGridPaneCellBounds(gridPane, column, 0);
+        final Bounds cb = getCellBounds(column, 0);
 
 
         /*
@@ -269,7 +423,6 @@
     
     private void updateSouthTrayBounds() {
         final List<Node> trayChildren = southTrayGroup.getChildren();
-        final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
         assert trayChildren.size() == columnCount;
         
         for (int c = 0; c < columnCount; c++) {
@@ -280,7 +433,7 @@
     
     private void updateSouthTrayBounds(int column, Label label) {
         final Bounds gb = gridPane.getLayoutBounds();
-        final Bounds cb = Deprecation.getGridPaneCellBounds(gridPane, column, 0);
+        final Bounds cb = getCellBounds(column, 0);
 
 
         /*
@@ -313,7 +466,6 @@
     
     private void updateWestTrayBounds() {
         final List<Node> trayChildren = westTrayGroup.getChildren();
-        final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
         assert trayChildren.size() == rowCount;
         
         for (int r = 0; r < rowCount; r++) {
@@ -324,7 +476,7 @@
     
     private void updateWestTrayBounds(int row, Label label) {
         final Bounds gb = gridPane.getLayoutBounds();
-        final Bounds cb = Deprecation.getGridPaneCellBounds(gridPane, 0,row);
+        final Bounds cb = getCellBounds(0,row);
 
 
         /*
@@ -372,7 +524,6 @@
     
     private void updateEastTrayBounds() {
         final List<Node> trayChildren = eastTrayGroup.getChildren();
-        final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
         assert trayChildren.size() == rowCount;
         
         for (int r = 0; r < rowCount; r++) {
@@ -383,7 +534,7 @@
     
     private void updateEastTrayBounds(int row, Label label) {
         final Bounds gb = gridPane.getLayoutBounds();
-        final Bounds cb = Deprecation.getGridPaneCellBounds(gridPane, 0,row);
+        final Bounds cb = getCellBounds(0,row);
 
 
         /*
@@ -556,4 +707,112 @@
         }
     }
     
+    
+    private void updateTargetCell() {
+        if (targetColumnIndex == -1) {
+            assert targetRowIndex == -1;
+            targetCellShadow.setVisible(false);
+        } else {
+            targetCellShadow.setVisible(true);
+            final Bounds tb = getCellBounds(targetColumnIndex, targetRowIndex);
+            targetCellShadow.setX(tb.getMinX());
+            targetCellShadow.setY(tb.getMinY());
+            targetCellShadow.setWidth(tb.getWidth());
+            targetCellShadow.setHeight(tb.getHeight());
+        }
+    }
+    
+    
+    private Bounds getCellBounds(int c, int r) {
+        final int cellIndex = getCellIndex(c, r);
+        assert cellIndex < cellBounds.size();
+        return cellBounds.get(cellIndex);
+    }
+    
+    private int getCellIndex(int c, int r) {
+        return c * rowCount + r;
+    }
+    
+    
+    private static final double MIN_STROKE_WIDTH = 8;
+    
+    private void updateTargetGap() {
+        
+        /*
+         * targetGapShadowV
+         */
+        if (targetGapColumnIndex == -1) {
+            targetGapShadowV.setVisible(false);
+        } else {
+            targetGapShadowV.setVisible(true);
+            
+            final double startX, startY, endY, strokeWidth;
+            if (targetGapColumnIndex < columnCount) {
+                final Bounds topCellBounds = getCellBounds(targetGapColumnIndex, 0);
+                final Bounds bottomCellBounds = getCellBounds(targetGapColumnIndex, rowCount-1);
+                startY = topCellBounds.getMinY();
+                endY = bottomCellBounds.getMaxY();
+                if (targetGapColumnIndex == 0) {
+                    startX = topCellBounds.getMinX();
+                    strokeWidth = MIN_STROKE_WIDTH;
+                } else {
+                    assert targetGapColumnIndex >= 1;
+                    final Bounds leftTopCellBounds = getCellBounds(targetGapColumnIndex-1, 0);
+                    startX = (leftTopCellBounds.getMaxX() + topCellBounds.getMinX()) / 2.0;
+                    strokeWidth = Math.abs(leftTopCellBounds.getMaxX() - topCellBounds.getMinX());
+                }
+            } else {
+                final Bounds topCellBounds = getCellBounds(columnCount-1, 0);
+                final Bounds bottomCellBounds = getCellBounds(columnCount-1, rowCount-1);
+                startX = topCellBounds.getMaxX();
+                startY = topCellBounds.getMinY();
+                endY = bottomCellBounds.getMaxY();
+                strokeWidth = MIN_STROKE_WIDTH;
+            }
+            targetGapShadowV.setStartX(startX);
+            targetGapShadowV.setStartY(startY);
+            targetGapShadowV.setEndX(startX);
+            targetGapShadowV.setEndY(endY);
+            targetGapShadowV.setStrokeWidth(Math.max(strokeWidth, MIN_STROKE_WIDTH));
+        }
+        
+        /*
+         * targetGapShadowH
+         */
+        if (targetGapRowIndex == -1) {
+            targetGapShadowH.setVisible(false);
+        } else {
+            targetGapShadowH.setVisible(true);
+            
+            final double startX, endX, startY, strokeWidth;
+            if (targetGapRowIndex < rowCount) {
+                final Bounds leftCellBounds = getCellBounds(0, targetGapRowIndex);
+                final Bounds rightCellBounds = getCellBounds(columnCount-1, targetGapRowIndex);
+                startX = leftCellBounds.getMinX();
+                endX = rightCellBounds.getMaxX();
+                if (targetGapRowIndex == 0) {
+                    startY = leftCellBounds.getMinY();
+                    strokeWidth = MIN_STROKE_WIDTH;
+                } else {
+                    assert targetGapRowIndex >= 1;
+                    final Bounds aboveLeftCellBounds = getCellBounds(0, targetGapRowIndex-1);
+                    startY = (aboveLeftCellBounds.getMaxY() + leftCellBounds.getMinY()) / 2.0;
+                    strokeWidth = Math.abs(aboveLeftCellBounds.getMaxY() - leftCellBounds.getMinY());
+                }
+            } else {
+                final Bounds leftCellBounds = getCellBounds(0, rowCount-1);
+                final Bounds rightCellBounds = getCellBounds(columnCount-1, rowCount-1);
+                startX = leftCellBounds.getMinX();
+                endX = rightCellBounds.getMaxX();
+                startY = leftCellBounds.getMaxY();
+                strokeWidth = MIN_STROKE_WIDTH;
+            }
+            targetGapShadowH.setStartX(startX);
+            targetGapShadowH.setStartY(startY);
+            targetGapShadowH.setEndX(endX);
+            targetGapShadowH.setEndY(startY);
+            targetGapShadowH.setStrokeWidth(Math.max(strokeWidth, MIN_STROKE_WIDTH));
+        }
+        
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/gridpane/GridPaneTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane;
+
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget.ColumnArea;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget.RowArea;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.tring.AbstractGenericTring;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+import javafx.scene.layout.GridPane;
+import javafx.scene.transform.Transform;
+
+/**
+ *
+ */
+public class GridPaneTring extends AbstractGenericTring<GridPane> {
+
+    private final GridPaneMosaic mosaic 
+            = new GridPaneMosaic("tring", false /* shouldShowTray */); //NOI18N
+    
+    public GridPaneTring(ContentPanelController contentPanelController, 
+            FXOMObject fxomObject) {
+        super(contentPanelController, fxomObject, GridPane.class);
+        getRootNode().getChildren().add(0, mosaic.getTopGroup()); // Below handles
+    }
+
+    public void setupWithDropTarget(GridPaneDropTarget dropTarget) {
+        assert dropTarget != null;
+        
+        final int targetColumnIndex
+                = dropTarget.getTargetColumnIndex();
+        final int targetRowIndex
+                = dropTarget.getTargetRowIndex();
+        final ColumnArea targetColumnArea
+                = dropTarget.getTargetColumnArea();
+        final RowArea targetRowArea
+                = dropTarget.getTargetRowArea();
+
+        if ((targetColumnArea == ColumnArea.CENTER) && (targetRowArea == RowArea.CENTER)) {
+            mosaic.setTargetCell(targetColumnIndex, targetRowIndex);
+        } else {
+            final int targetGapColumnIndex;
+            switch(targetColumnArea) {
+                case LEFT:
+                    targetGapColumnIndex = targetColumnIndex;
+                    break;
+                default:
+                case CENTER:
+                    targetGapColumnIndex = -1;
+                    break;
+                case RIGHT:
+                    targetGapColumnIndex = targetColumnIndex+1;
+                    break;
+            }
+            final int targetGapRowIndex;
+            switch(targetRowArea) {
+                case TOP:
+                    targetGapRowIndex = targetRowIndex;
+                    break;
+                default:
+                case CENTER:
+                    targetGapRowIndex = -1;
+                    break;
+                case BOTTOM:
+                    targetGapRowIndex = targetRowIndex+1;
+                    break;
+            }
+            mosaic.setTargetGap(targetGapColumnIndex, targetGapRowIndex);
+        }
+    }
+    
+    /*
+     * AbstractGenericPring
+     */
+    
+    @Override
+    public Bounds getSceneGraphObjectBounds() {
+        return getSceneGraphObject().getLayoutBounds();
+    }
+
+    @Override
+    public Transform getSceneGraphToSceneTransform() {
+        return getSceneGraphObject().getLocalToSceneTransform();
+    }
+
+    @Override
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x, y);
+    }
+
+    @Override
+    protected void startListeningToSceneGraphObject() {
+        startListeningToLayoutBounds(getSceneGraphObject());
+        startListeningToLocalToSceneTransform(getSceneGraphObject());
+    }
+
+    @Override
+    protected void stopListeningToSceneGraphObject() {
+        stopListeningToLayoutBounds(getSceneGraphObject());
+        stopListeningToLocalToSceneTransform(getSceneGraphObject());
+    }
+    
+    @Override
+    protected void layoutDecoration() {
+        
+        super.layoutDecoration();
+        
+        if (mosaic.getGridPane() != getSceneGraphObject()) {
+            mosaic.setGridPane(getSceneGraphObject());
+        } else {
+            mosaic.update();
+        }
+        
+        // Update mosaic transform
+        mosaic.getTopGroup().getTransforms().clear();
+        mosaic.getTopGroup().getTransforms().add(getSceneGraphObjectToDecorationTransform());
+    }
+}
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractCurveHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractCurveHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -75,8 +75,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x,y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x,y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x,y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractNodeHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/AbstractNodeHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -87,8 +87,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x,y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x,y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x,y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TabHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TabHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,8 +35,8 @@
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.TabPaneDesignInfoX;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.AbstractGesture;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse.DebugMouseGesture;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.util.BoundsUtils;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
-import javafx.geometry.BoundingBox;
 import javafx.geometry.Bounds;
 import javafx.geometry.Point2D;
 import javafx.scene.Node;
@@ -74,7 +74,7 @@
         final TabPane tabPane = getSceneGraphObject().getTabPane();
         final Point2D min = tabPane.sceneToLocal(tabNode.localToScene(b.getMinX(), b.getMinY()));
         final Point2D max = tabPane.sceneToLocal(tabNode.localToScene(b.getMaxX(), b.getMaxY()));
-        return makeBoundingBox(min, max);
+        return BoundsUtils.makeBounds(min, max);
     }
 
     @Override
@@ -83,11 +83,16 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TabPane tabPane = getSceneGraphObject().getTabPane();
-        return getRootNode().sceneToLocal(tabPane.localToScene(x, y));
+        return tabPane.localToScene(x, y);
     }
 
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TabPane tabPane = getSceneGraphObject().getTabPane();
+        return tabPane.sceneToLocal(x, y);
+    }
 
     @Override
     protected void startListeningToSceneGraphObject() {
@@ -118,17 +123,4 @@
     public AbstractGesture findGesture(Node node) {
         return new DebugMouseGesture(getContentPanelController(), "Resize gesture for Tab");
     }
-    
-    
-    /*
-     * Private
-     */
-    
-    private static BoundingBox makeBoundingBox(Point2D p1, Point2D p2) {
-        return new BoundingBox(
-                Math.min(p1.getX(), p2.getX()),
-                Math.min(p1.getY(), p2.getY()),
-                Math.abs(p2.getX() - p1.getX()),
-                Math.abs(p2.getY() - p1.getY()));
-    }
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TableColumnHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TableColumnHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -77,11 +77,16 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TableView<?> tv = getTableColumn().getTableView();
-        return getRootNode().sceneToLocal(tv.localToScene(x, y));
+        return tv.localToScene(x, y);
     }
 
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TableView<?> tv = getTableColumn().getTableView();
+        return tv.sceneToLocal(x, y);
+    }
 
     @Override
     protected void startListeningToSceneGraphObject() {
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TreeTableColumnHandles.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/handles/TreeTableColumnHandles.java	Tue Dec 10 08:36:28 2013 +0100
@@ -77,11 +77,16 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TreeTableView<?> tv = getTreeTableColumn().getTreeTableView();
-        return getRootNode().sceneToLocal(tv.localToScene(x, y));
+        return tv.localToScene(x, y);
     }
 
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TreeTableView<?> tv = getTreeTableColumn().getTreeTableView();
+        return tv.sceneToLocal(x, y);
+    }
 
     @Override
     protected void startListeningToSceneGraphObject() {
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/NodePring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/NodePring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -70,8 +70,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x, y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TabPring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TabPring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -114,9 +114,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TabPane tabPane = getSceneGraphObject().getTabPane();
-        return getRootNode().sceneToLocal(tabPane.localToScene(x, y));
+        return tabPane.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TabPane tabPane = getSceneGraphObject().getTabPane();
+        return tabPane.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TableColumnPring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TableColumnPring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -77,9 +77,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TableView<?> tv = getTableColumn().getTableView();
-        return getRootNode().sceneToLocal(tv.localToScene(x, y));
+        return tv.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TableView<?> tv = getTableColumn().getTableView();
+        return tv.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TreeTableColumnPring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/pring/TreeTableColumnPring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -77,9 +77,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TreeTableView<?> ttv = getTreeTableColumn().getTreeTableView();
-        return getRootNode().sceneToLocal(ttv.localToScene(x, y));
+        return ttv.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TreeTableView<?> ttv = getTreeTableColumn().getTreeTableView();
+        return ttv.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/resizer/ImageViewResizer.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/resizer/ImageViewResizer.java	Tue Dec 10 08:36:28 2013 +0100
@@ -31,6 +31,7 @@
  */
 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.resizer;
 
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.util.BoundsUtils;
 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
 import com.oracle.javafx.scenebuilder.kit.util.MathUtils;
 import java.util.ArrayList;
@@ -59,8 +60,8 @@
         originalFitHeight  = sceneGraphObject.getFitHeight();
         propertyNames.add(fitWidthName);
         propertyNames.add(fitHeightName);
-        assert sceneGraphObject.getLayoutBounds().equals(
-                computeBounds(originalFitWidth, originalFitHeight));
+//        assert BoundsUtils.equals(sceneGraphObject.getLayoutBounds(), 
+//                computeBounds(originalFitWidth, originalFitHeight));
     }
 
     /*
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/rudder/ResizeRudder.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/rudder/ResizeRudder.java	Tue Dec 10 08:36:28 2013 +0100
@@ -74,8 +74,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x,y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x,y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x,y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/HBoxTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/HBoxTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -81,8 +81,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x, y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/NodeTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/NodeTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -68,8 +68,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x, y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TabTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TabTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -93,9 +93,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TabPane tabPane = getSceneGraphObject().getTabPane();
-        return getRootNode().sceneToLocal(tabPane.localToScene(x, y));
+        return tabPane.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TabPane tabPane = getSceneGraphObject().getTabPane();
+        return tabPane.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TableColumnTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TableColumnTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -74,9 +74,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TableView<?> tv = getTableColumn().getTableView();
-        return getRootNode().sceneToLocal(tv.localToScene(x, y));
+        return tv.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TableView<?> tv = getTableColumn().getTableView();
+        return tv.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TreeTableColumnTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/TreeTableColumnTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -74,9 +74,15 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
+    public Point2D sceneGraphObjectToScene(double x, double y) {
         final TreeTableView<?> tv = getTreeTableColumn().getTreeTableView();
-        return getRootNode().sceneToLocal(tv.localToScene(x, y));
+        return tv.localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        final TreeTableView<?> tv = getTreeTableColumn().getTreeTableView();
+        return tv.sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/VBoxTring.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/driver/tring/VBoxTring.java	Tue Dec 10 08:36:28 2013 +0100
@@ -81,8 +81,13 @@
     }
 
     @Override
-    public Point2D sceneGraphObjectToDecoration(double x, double y) {
-        return getRootNode().sceneToLocal(getSceneGraphObject().localToScene(x, y));
+    public Point2D sceneGraphObjectToScene(double x, double y) {
+        return getSceneGraphObject().localToScene(x, y);
+    }
+
+    @Override
+    public Point2D sceneToSceneGraphObject(double x, double y) {
+        return getSceneGraphObject().sceneToLocal(x, y);
     }
 
     @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/ResizeGesture.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/ResizeGesture.java	Tue Dec 10 08:36:28 2013 +0100
@@ -43,6 +43,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.rudder.ResizeRudder;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.guides.ResizingGuideController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.util.CardinalPoint;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.util.RegionRectangle;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
 import com.oracle.javafx.scenebuilder.kit.metadata.Metadata;
@@ -77,7 +78,7 @@
     private AbstractResizer<?> resizer;
     private AbstractRelocater<?> relocater;
     private ResizingGuideController resizingGuideController;
-    private ResizeShadow shadow;
+    private RegionRectangle shadow;
     private boolean snapEnabled;
     private boolean guidesDisabled;
 
@@ -411,7 +412,8 @@
     private void showShadow() {
         assert shadow == null;
         
-        shadow = new ResizeShadow();
+        shadow = new RegionRectangle();
+        shadow.getRegion().getStyleClass().add("resize-shadow");
         shadow.setMouseTransparent(true);
         contentPanelController.getRudderLayer().getChildren().add(shadow);
         
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/SelectAndMoveGesture.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/gesture/mouse/SelectAndMoveGesture.java	Tue Dec 10 08:36:28 2013 +0100
@@ -38,6 +38,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import java.util.Objects;
 import javafx.geometry.Point2D;
 import javafx.scene.Node;
 import javafx.scene.input.Dragboard;
@@ -58,7 +59,6 @@
     private FXOMObject hitObject;
     private double hitSceneX;
     private double hitSceneY;
-    private Node hitNode;
 
     public FXOMObject getHitObject() {
         return hitObject;
@@ -76,10 +76,6 @@
         this.hitSceneY = hitSceneY;
     }
     
-    public void setHitNode(Node hitNode) {
-        this.hitNode = hitNode;
-    }
-    
     /*
      * AbstractMouseDragGesture
      */
@@ -113,22 +109,28 @@
         final boolean extendKeyDown
                 = EditorPlatform.isContinuousSelectKeyDown(e) 
                 || EditorPlatform.isNonContinousSelectKeyDown(e);
+        final Point2D hitPoint
+                = computeHitPoint(hitObject);
         
         if (selection.isSelected(hitObject)) {
             if (extendKeyDown) { // Case C
-                selection.toggleSelection(hitObject);
-            } // else Case A
+                selection.toggleSelection(hitObject, hitPoint);
+            } else { // else Case A
+                if (Objects.equals(hitPoint, selection.getHitPoint()) == false) {
+                    selection.select(hitObject, hitPoint);
+                }
+            }
         } else {
             final FXOMObject ancestor = selection.lookupSelectedAncestor(hitObject);
             if (ancestor == null) {
                 if (extendKeyDown) { // Case D.1
-                    selection.toggleSelection(hitObject);
+                    selection.toggleSelection(hitObject, hitPoint);
                 } else { // Case B.1
-                    selection.select(hitObject);
+                    selection.select(hitObject, hitPoint);
                 }
             } else {
                 if (extendKeyDown) { // Case D.2
-                    selection.toggleSelection(ancestor);
+                    selection.toggleSelection(ancestor, hitPoint);
                 } // else Case B.2
             }
         }
@@ -197,16 +199,12 @@
     }
     
     private Point2D computeHitPoint(FXOMObject fxomObject) {
-        final Point2D result;
         
-        if (fxomObject.getSceneGraphObject() instanceof Node) {
-            final Node sceneGraphNode = (Node) fxomObject.getSceneGraphObject();
-            result = sceneGraphNode.sceneToLocal(hitSceneX, hitSceneY);
-        } else {
-            result = Point2D.ZERO;
-        }
-        
-        return result;
+        final FXOMObject nodeObject = fxomObject.getClosestNode();
+        assert nodeObject != null; // At least the root is a Node
+        assert nodeObject.getSceneGraphObject() instanceof Node;
+        final Node sceneGraphNode = (Node) nodeObject.getSceneGraphObject();
+        return sceneGraphNode.sceneToLocal(hitSceneX, hitSceneY);
     }
 
     @Override
@@ -221,7 +219,7 @@
                 = EditorPlatform.isContinuousSelectKeyDown(e) 
                 || EditorPlatform.isNonContinousSelectKeyDown(e);
         if (extendKeyDown == false) {
-            selection.select(hitObject);
+            selection.select(hitObject, computeHitPoint(hitObject));
         }
         
         /*
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/MovingGuideRenderer.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/MovingGuideRenderer.java	Tue Dec 10 08:36:28 2013 +0100
@@ -123,14 +123,14 @@
             chromeMap.put(s, chrome);
         }
         
-        assert chromeMap.keySet().size() == lines1.size() + lines2.size()
-                : "chromeMap.keySet().size()=" + chromeMap.keySet().size()
-                + ", lines1.size()=" + lines1.size()
-                + ", lines2.size()=" + lines2.size()
-                + ", currentLines.size()=" + currentLines.size()
-                + ", newLines.size()=" + newLines.size()
-                + ", obsoleteLines.size()=" + obsoleteLines.size();
-        assert chromeMap.size() + reusableChromes.size() == guideGroup.getChildren().size();
+//        assert chromeMap.keySet().size() == lines1.size() + lines2.size()
+//                : "chromeMap.keySet().size()=" + chromeMap.keySet().size()
+//                + ", lines1.size()=" + lines1.size()
+//                + ", lines2.size()=" + lines2.size()
+//                + ", currentLines.size()=" + currentLines.size()
+//                + ", newLines.size()=" + newLines.size()
+//                + ", obsoleteLines.size()=" + obsoleteLines.size();
+//        assert chromeMap.size() + reusableChromes.size() == guideGroup.getChildren().size();
     }
     
     
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/ResizingGuideRenderer.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/guides/ResizingGuideRenderer.java	Tue Dec 10 08:36:28 2013 +0100
@@ -97,10 +97,10 @@
             chromeMap.put(s, chrome);
         }
         
-        assert chromeMap.keySet().size() == segments.size()
-                : "chromeMap.keySet().size()=" + chromeMap.keySet().size()
-                + ", segments.size()=" + segments.size();
-        assert chromeMap.size() + reusableChromes.size() == guideGroup.getChildren().size();
+//        assert chromeMap.keySet().size() == segments.size()
+//                : "chromeMap.keySet().size()=" + chromeMap.keySet().size()
+//                + ", segments.size()=" + segments.size();
+//        assert chromeMap.size() + reusableChromes.size() == guideGroup.getChildren().size();
     }
     
     
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/mode/EditModeController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/mode/EditModeController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,12 +35,14 @@
 import com.oracle.javafx.scenebuilder.kit.editor.EditorController.EditAction;
 import com.oracle.javafx.scenebuilder.kit.editor.drag.DragController;
 import com.oracle.javafx.scenebuilder.kit.editor.drag.target.AbstractDropTarget;
+import com.oracle.javafx.scenebuilder.kit.editor.drag.target.GridPaneDropTarget;
 import com.oracle.javafx.scenebuilder.kit.editor.drag.target.RootDropTarget;
 import com.oracle.javafx.scenebuilder.kit.editor.job.ModifyObjectJob;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.AbstractDecoration;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.AbstractDriver;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane.GridPaneHandles;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane.GridPaneTring;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.handles.AbstractHandles;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.pring.AbstractPring;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.tring.AbstractTring;
@@ -205,6 +207,9 @@
         }
     }
     
+    /*
+     * Private (pring)
+     */
     private void updateParentRing() {
         final Selection selection = contentPanelController.getEditorController().getSelection();
         final AbstractPring<?> newPring;
@@ -245,13 +250,40 @@
         }
     }
     
+    private AbstractPring<?> makePring(FXOMObject fxomObject) {
+        final AbstractDriver driver = contentPanelController.lookupDriver(fxomObject);
+        final AbstractPring<?> result;
+        
+        if (driver != null) {
+            result = driver.makePring(fxomObject);
+            if (result != null) {
+                result.changeStroke(contentPanelController.getPringColor());
+            }
+        } else {
+            result = null;
+        }
+        
+        return result;
+    }
+    
+
+    /*
+     * Private (tring)
+     */
     private void updateTring() {
         final DragController dragController
                 = contentPanelController.getEditorController().getDragController();
         final AbstractTring<?> newTring;
         
         if (dragController.isDropAccepted()) {
-            newTring = makeTring(dragController.getDropTarget());
+            final AbstractDropTarget dropTarget = dragController.getDropTarget();
+            if ((tring instanceof GridPaneTring) && (dropTarget instanceof GridPaneDropTarget)) {
+                // Let's reuse the GridPaneTring (because it's costly)
+                newTring = tring;
+                updateTring((GridPaneTring) tring, (GridPaneDropTarget) dropTarget);
+            } else {
+                newTring = makeTring(dragController.getDropTarget());
+            }
         } else {
             newTring = null;
         }
@@ -270,20 +302,11 @@
         }
     }
     
-    private AbstractPring<?> makePring(FXOMObject fxomObject) {
-        final AbstractDriver driver = contentPanelController.lookupDriver(fxomObject);
-        final AbstractPring<?> result;
+    private void updateTring(GridPaneTring tring, GridPaneDropTarget dropTarget) {
+        assert tring != null;
+        assert dropTarget != null;
         
-        if (driver != null) {
-            result = driver.makePring(fxomObject);
-            if (result != null) {
-                result.changeStroke(contentPanelController.getPringColor());
-            }
-        } else {
-            result = null;
-        }
-        
-        return result;
+        tring.setupWithDropTarget(dropTarget);
     }
     
     private AbstractTring<?> makeTring(AbstractDropTarget dropTarget) {
@@ -628,7 +651,6 @@
             selectAndMoveGesture.setHitObject(hitObject);
             selectAndMoveGesture.setHitSceneX(e.getSceneX());
             selectAndMoveGesture.setHitSceneY(e.getSceneY());
-            selectAndMoveGesture.setHitNode(contentPanelController.getLastHitNode());
             glassGesture = selectAndMoveGesture;
         }
     }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/BoundsUtils.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/BoundsUtils.java	Tue Dec 10 08:36:28 2013 +0100
@@ -32,14 +32,34 @@
 
 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.util;
 
+import com.oracle.javafx.scenebuilder.kit.util.MathUtils;
 import javafx.geometry.BoundingBox;
 import javafx.geometry.Bounds;
+import javafx.geometry.Point2D;
+import javafx.scene.Node;
 
 /**
  *
  */
 public class BoundsUtils {
     
+    public static Bounds makeBounds(Point2D p1, Point2D p2) {
+        return new BoundingBox(
+                Math.min(p1.getX(), p2.getX()),
+                Math.min(p1.getY(), p2.getY()),
+                Math.abs(p2.getX() - p1.getX()),
+                Math.abs(p2.getY() - p1.getY()));
+    }
+    
+    
+    public static boolean equals(Bounds b1, Bounds b2) {
+        return MathUtils.equals(b1.getMinX(), b2.getMinX()) &&
+                MathUtils.equals(b1.getMinY(), b2.getMinY()) &&
+                MathUtils.equals(b1.getMaxX(), b2.getMaxX()) &&
+                MathUtils.equals(b1.getMaxY(), b2.getMaxY());
+                
+    }
+    
     public static Bounds inset(Bounds bounds, double dx, double dy) {
         final double minX = bounds.getMinX() + dx;
         final double minY = bounds.getMinY() + dy;
@@ -47,4 +67,97 @@
         final double maxY = bounds.getMaxY() - dy;
         return new BoundingBox(minX, minY, maxX - minX, maxY - minY);
     }
+    
+    
+    public static EdgeInfo distanceToEdges(Bounds b, double x, double y, Node node) {
+        assert b != null;
+        assert node != null;
+        assert node.getScene() != null;
+
+        final EdgeInfo result;
+        if (b.isEmpty()) {
+            result = null;
+        } else {
+            final double minX = b.getMinX();
+            final double minY = b.getMinY();
+            final double maxX = b.getMaxX();
+            final double maxY = b.getMaxY();
+            
+            final Point2D p1 = node.localToScene(minX, minY);
+            final Point2D p2 = node.localToScene(maxX, minY);
+            final Point2D p3 = node.localToScene(maxX, maxY);
+            final Point2D p4 = node.localToScene(minX, maxY);
+
+            final LineEquation nl = new LineEquation(p1, p2);
+            final LineEquation el = new LineEquation(p2, p3);
+            final LineEquation sl = new LineEquation(p3, p4);
+            final LineEquation wl = new LineEquation(p4, p1);
+
+            final Point2D p = node.localToScene(x, y);
+            final double sceneX = p.getX();
+            final double sceneY = p.getY();
+            final Point2D nh = nl.pointAtOffset(nl.offsetAtPoint(sceneX, sceneY));
+            final Point2D eh = el.pointAtOffset(el.offsetAtPoint(sceneX, sceneY));
+            final Point2D sh = sl.pointAtOffset(sl.offsetAtPoint(sceneX, sceneY));
+            final Point2D wh = wl.pointAtOffset(wl.offsetAtPoint(sceneX, sceneY));
+
+            final double nd = distance(nh, p);
+            final double ed = distance(eh, p);
+            final double sd = distance(sh, p);
+            final double wd = distance(wh, p);
+
+            return new EdgeInfo(nd, ed, sd, wd);
+        }
+        
+        return result;
+    }
+    
+    public static class EdgeInfo {
+        private final double northDistance;
+        private final double eastDistance;
+        private final double southDistance;
+        private final double westDistance;
+
+        public EdgeInfo(double northDistance, double eastDistance,
+                double southDistance, double westDistance) {
+            this.northDistance = northDistance;
+            this.eastDistance = eastDistance;
+            this.southDistance = southDistance;
+            this.westDistance = westDistance;
+        }
+
+        public double getNorthDistance() {
+            return northDistance;
+        }
+
+        public double getEastDistance() {
+            return eastDistance;
+        }
+
+        public double getSouthDistance() {
+            return southDistance;
+        }
+
+        public double getWestDistance() {
+            return westDistance;
+        }
+
+        @Override
+        public String toString() {
+            return "EdgeInfo{" //NOI18N
+                    + "northDistance=" + northDistance  //NOI18N
+                    + ", eastDistance=" + eastDistance  //NOI18N
+                    + ", southDistance=" + southDistance  //NOI18N
+                    + ", westDistance=" + westDistance  //NOI18N
+                    + '}'; //NOI18N
+        }
+
+    }
+    
+    
+    private static double distance(Point2D p1, Point2D p2) {
+        final double dx = p2.getX() - p1.getX();
+        final double dy = p2.getY() - p1.getY();
+        return Math.sqrt(dx * dx + dy * dy);
+    }
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/LineEquation.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/LineEquation.java	Tue Dec 10 08:36:28 2013 +0100
@@ -97,13 +97,15 @@
     public double offsetAtPoint(double x, double y) {
         /*
          * offset is the dot product of:
-         *      - v1 : vector ((0, 0), (x, y))
+         *      - v1 : vector ((x0, y0), (x, y))
          *      - v2 : normalized vector ((x0, y0), (x1, y1))
          */
         
-        final double x01 = (x1 - x0) / distance;
-        final double y01 = (y1 - y0) / distance;
-        final double result = x * x01 + y * y01;
+        final double dx1 = x - x0;
+        final double dy1 = y - y0;
+        final double dx2 = (x1 - x0) / distance;
+        final double dy2 = (y1 - y0) / distance;
+        final double result = dx1 * dx2 + dy1 * dy2;
         
         return result;
     }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/Picker.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/Picker.java	Tue Dec 10 08:36:28 2013 +0100
@@ -55,6 +55,11 @@
      * Returns the list of nodes below (sceneX, sceneY).
      * Topmost node is at index 0.
      * Search starts from startNode.
+     * 
+     * @param startNode
+     * @param sceneX
+     * @param sceneY
+     * @return the list of nodes below (sceneX, sceneY).
      */
     public List<Node> pick(Node startNode, double sceneX, double sceneY) {
         assert startNode != null;
@@ -62,11 +67,18 @@
         assert Double.isNaN(sceneX) == false;
         assert Double.isNaN(sceneY) == false;
         
+        final Point2D localXY = startNode.sceneToLocal(sceneX, sceneY);
+        return pickInLocal(startNode, localXY.getX(), localXY.getY());
+    }
+    
+    public List<Node> pickInLocal(Node startNode, double localX, double localY) {
+        assert startNode != null;
+        assert startNode.getScene() != null;
+        assert Double.isNaN(localX) == false;
+        assert Double.isNaN(localY) == false;
+        
         this.matches.clear();
-        final Point2D localXY = startNode.sceneToLocal(sceneX, sceneY);
-        
-        pickInLocal(startNode, localXY.getX(), localXY.getY());
-        
+        performPick(startNode, localX, localY);
         return matches.isEmpty() ? null : Collections.unmodifiableList(matches);
     }
 
@@ -75,7 +87,7 @@
     }
     
 
-    private void pickInLocal(Node startNode, double localX, double localY) {
+    private void performPick(Node startNode, double localX, double localY) {
 
         if (excludes.contains(startNode) == false) {
             if (startNode.getLayoutBounds().contains(localX, localY)) {
@@ -89,7 +101,7 @@
                     // Note : childLocalXY may be null.
                     // For example, child is a Button with scaleX == 0.
                     if (childLocalXY != null) {
-                        pickInLocal(child, childLocalXY.getX(), childLocalXY.getY());
+                        performPick(child, childLocalXY.getX(), childLocalXY.getY());
                     }
                 }
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/content/util/RegionRectangle.java	Tue Dec 10 08:36:28 2013 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, 2013, 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 com.oracle.javafx.scenebuilder.kit.editor.panel.content.util;
+
+import javafx.geometry.Bounds;
+import javafx.scene.Group;
+import javafx.scene.layout.Region;
+
+/**
+ * A RegionRectangle behaves like a Rectangle but enables all the
+ * CSS Styling available on a Region.
+ * 
+ * It is the following construct:
+ *
+ *    Group
+ *         Region
+ *
+ * Layout bounds of the group must be equal to layout bounds
+ * of the scene graph node. We ensure this by setting layoutX/Y
+ * on the region (1).
+ */
+public class RegionRectangle extends Group {
+    
+    private final Region region = new Region();
+    
+    
+    public RegionRectangle() {
+        this.getChildren().add(region);
+    }
+    
+    public Region getRegion() {
+        return region;
+    }
+    
+    public void setLayoutBounds(Bounds layoutBounds) {
+        
+        // Setup layoutX/layoutY on the image view and the region (1)
+        region.setLayoutX(layoutBounds.getMinX());
+        region.setLayoutY(layoutBounds.getMinY());
+        region.setPrefWidth(layoutBounds.getWidth());
+        region.setPrefHeight(layoutBounds.getHeight());
+    }
+}
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssContentMaker.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssContentMaker.java	Tue Dec 10 08:36:28 2013 +0100
@@ -68,7 +68,7 @@
     private static final List<StyleOrigin> ORDERED_ORIGIN = new ArrayList<>();
 
     static {
-        ORDERED_ORIGIN.add(StyleOrigin.USER_AGENT);// modena / caspian
+        ORDERED_ORIGIN.add(StyleOrigin.USER_AGENT);// fxTheme : modena/caspian
         ORDERED_ORIGIN.add(StyleOrigin.USER);//Bean API Call
 
         ORDERED_ORIGIN.add(StyleOrigin.AUTHOR);//CSS files
@@ -233,24 +233,6 @@
      * Private methods
      *
      */
-    private static void clearStyledSubProperty(InitialPropertyState prop, Collection<CssPropertyState> styled) {
-        Iterator<CssPropertyState> it = styled.iterator();
-        while (it.hasNext()) {
-            CssPropertyState styledProp = it.next();
-            if (styledProp.getCssProperty().equals(prop.getCssProperty())) {
-                // If the styled property contains the initial sub property, remove it from the initial sub Properties
-                for (PropertyState sub : styledProp.getSubProperties()) {
-                    for (PropertyState initialSub : prop.getSubProperties()) {
-                        if (initialSub.getCssProperty().equals(sub.getCssProperty())) {
-                            prop.getSubProperties().remove(initialSub);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     private static boolean containsInStyle(CssPropertyState prop, String style) {
         return style.contains(prop.getCssProperty());
     }
@@ -282,19 +264,6 @@
         }
     }
 
-    // XXX jfdenise, to remove, used for alternate view of Initial values.
-    private static <N extends Node> PropertyState computeCurrentValue(
-            N n, CssMetaData<N, ?> cssMeta, FXOMObject fxomObject) {
-        PropertyState val = modelValue(n, cssMeta, fxomObject);
-        if (val == null) {
-            val = initialValue(n, cssMeta);
-        }
-        assert val != null;
-        val.getNotAppliedStyles().addAll(
-                getNotAppliedStyles(Collections.<Style>emptyList(), n, cssMeta));
-        return val;
-    }
-
     private static FXOMObject getFXOMObject(Object selectedObject) {
         if (selectedObject instanceof FXOMObject) {
             return (FXOMObject) selectedObject;
@@ -378,14 +347,14 @@
         List<CssStyle> ret = new ArrayList<>();
 
         List<Style> allStyles = Deprecation.getMatchingStyles(cssMeta, node);
+//        System.out.println("===========================");
+//        System.out.println("getNotAppliedStyles() called!");
+//        System.out.println("===========================");
 //        System.out.println("\n\n");
 //        printStyles(allStyles);
         List<Style> notApplied = new ArrayList<>();
         for (Object obj : allStyles) {
             Style style = (Style) obj;
-            if (CssInternal.isThemeStyle(style)) {
-                continue;
-            }
             if (!appliedStyles.contains(style)) {
                 notApplied.add(style);
             }
@@ -406,7 +375,7 @@
 //        }
 //
 //    }
-//
+
 //    private static void printStyle(Style style) {
 //        System.out.println(style.getDeclaration().getRule().getOrigin() + " ==> STYLE " + style.getDeclaration());
 //        System.out.println("--> css url = " + style.getDeclaration().getRule().getStylesheet().getUrl());
@@ -546,6 +515,10 @@
                 return used;
             }
 
+            public Style getStyle() {
+                return style;
+            }
+
             public String getCssProperty() {
                 return style.getDeclaration().getProperty();
             }
@@ -556,11 +529,7 @@
             }
 
             public StyleOrigin getOrigin() {
-                Rule rule = style.getDeclaration().getRule();
-                if (rule == null) {
-                    return null;
-                }
-                return rule.getOrigin();
+                return CssInternal.getOrigin(style);
             }
 
             public String getSelector() {
@@ -665,7 +634,6 @@
         private Collection<CssPropertyState> author;
         private Collection<CssPropertyState> inline;
         private Collection<CssPropertyState> userAgent;
-        private Collection<PropertyState> initial;
         private Map<MatchingRule, List<MatchingDeclaration>> matchingRules;
         private List<MatchingRule> sortedMatchingRules = new ArrayList<>();
         private Collection<CssProperty> props;
@@ -678,7 +646,6 @@
             getAuthorStyles();
             getInlineStyles();
             getUserAgentStyles();
-            getInitialStyles();
             getMatchingRules();
             getAllStyleables();
         }
@@ -692,12 +659,12 @@
             private final List<CssProperty> sub = new ArrayList<>();
             private final ObjectProperty<String> name = new SimpleObjectProperty<>();
             private final ObjectProperty<PropertyState> builtin = new SimpleObjectProperty<>();
-            private final ObjectProperty<CssPropertyState> caspian = new SimpleObjectProperty<>();
+            private final ObjectProperty<CssPropertyState> fxTheme = new SimpleObjectProperty<>();
             private final ObjectProperty<CssPropertyState> authorCss = new SimpleObjectProperty<>();
             private final ObjectProperty<CssPropertyState> inlineCss = new SimpleObjectProperty<>();
             private final ObjectProperty<PropertyState> fxmlModel = new SimpleObjectProperty<>();
             private PropertyState currentState;
-            
+
             @SuppressWarnings("rawtypes")
             CssProperty(NodeCssState nodeCssState, CssMetaData cssMeta, Node target, FXOMObject fxomObject) {
                 this(nodeCssState, null, cssMeta, target, fxomObject);
@@ -717,9 +684,9 @@
                 if (authorState != null) {
                     authorCss.setValue(authorState);
                 }
-                CssPropertyState caspianState = nodeCssState.retrieveCssStyle(cssMeta, nodeCssState.getUserAgentStyles());
-                if (caspianState != null) {
-                    caspian.setValue(caspianState);
+                CssPropertyState fxThemeState = nodeCssState.retrieveCssStyle(cssMeta, nodeCssState.getUserAgentStyles());
+                if (fxThemeState != null) {
+                    fxTheme.setValue(fxThemeState);
                 }
                 @SuppressWarnings("unchecked")
                 PropertyState builtinState = CssContentMaker.initialValue(target, mainProperty == null ? this : mainProperty, cssMeta);
@@ -740,8 +707,8 @@
                 return fxmlModel;
             }
 
-            public ObjectProperty<CssPropertyState> caspianState() {
-                return caspian;
+            public ObjectProperty<CssPropertyState> fxThemeState() {
+                return fxTheme;
             }
 
             public ObjectProperty<CssPropertyState> authorState() {
@@ -803,11 +770,11 @@
                 return inlineState().get() == null
                         && authorState().get() == null
                         && modelState().get() == null
-                        && caspianState().get() == null;
+                        && fxThemeState().get() == null;
             }
 
-            public boolean isCaspianSource() {
-                return caspianState().get() != null
+            public boolean isFxThemeSource() {
+                return fxThemeState().get() != null
                         && inlineState().get() == null
                         && authorState().get() == null
                         && modelState().get() == null;
@@ -836,7 +803,7 @@
                 if (authorState().get() != null) {
                     return authorState().get();
                 }
-                return caspianState().get();
+                return fxThemeState().get();
             }
 
             public PropertyState getCurrentStyle() {
@@ -892,7 +859,7 @@
                 return ret;
             }
 
-            public List<CssStyle> getCaspianHiddenByModel() {
+            public List<CssStyle> getFxThemeHiddenByModel() {
                 List<CssStyle> ret = new ArrayList<>();
                 CssPropertyState ps = getWinner();
                 List<CssStyle> notAppliedStyles = ps == null ? Collections.<CssStyle>emptyList() : ps.getNotAppliedStyles();
@@ -1000,27 +967,12 @@
             return userAgent;
         }
 
-        public final Collection<PropertyState> getInitialStyles() {
-            if (initial == null) {
-                SortedSet<PropertyState> sorted = new TreeSet<>();
-                sorted.addAll(getAppliedIStyles(node));
-
-                // Not needed now that the skin.getNode() returns the control itself
-//                if (node instanceof Skinnable) {
-//                    Skin<?> skin = ((Skinnable) node).getSkin();
-//                    Node skinNode = skin.getNode();
-//                    sorted.addAll(getAppliedIStyles(skinNode));
-//                }
-                initial = sorted;
-            }
-            return initial;
-        }
-
         public static class RuleComparator implements Comparator<MatchingRule> {
 
-        @Override
+            @Override
             public int compare(MatchingRule t, MatchingRule t1) {
-                int originComparaison = compareOrigin(t.getRule().getOrigin(), t1.rule.getOrigin());
+                int originComparaison = compareOrigin(
+                        CssInternal.getOrigin(t.getRule()), CssInternal.getOrigin(t1.rule));
                 int tnotApplied = countNotApplied(t.declarations);
                 int t1notApplied = countNotApplied(t1.declarations);
                 int notAppliedComparaisons = tnotApplied - t1notApplied;
@@ -1177,7 +1129,7 @@
                 for (Entry<MatchingRule, List<MatchingDeclaration>> entry : matchingRules.entrySet()) {
                     MatchingRule rule = entry.getKey();
                     // Filterout the Inline
-                    if (rule.getRule().getOrigin() != StyleOrigin.INLINE) {
+                    if (CssInternal.getOrigin(rule.getRule()) != StyleOrigin.INLINE) {
                         rule.addDeclarations(entry.getValue());
                         sortedMatchingRules.add(rule);
                     }
@@ -1240,21 +1192,8 @@
 //                System.out.println("\nStyleable property: " + value);
                 assert entry.getValue() != null;
                 assert !entry.getValue().isEmpty();
-
-                Style st = null;
-                // Find the first style which is not a theme style.
-                for (Style style : entry.getValue()) {
-                    if (!CssInternal.isThemeStyle(style)) {
-                        st = style;
-                        break;
-                    }
-                }
-                if (st == null) {
-                    // No "real" style found for this property: continue with next property
-                    continue;
-                }
-
-                StyleOrigin o = st.getDeclaration().getRule().getOrigin();// Winning Style.
+                Style st = entry.getValue().get(0);
+                StyleOrigin o = CssInternal.getOrigin(st);
 //                printStyle(st);
                 /* If this origin is equals to the passed one, this is the nominal case.
                  * If this property contains sub properties (eg:background-fills), then we need to check
@@ -1264,7 +1203,6 @@
                 if (o == origin || cssMetaList.getSubProperties() != null) {
                     // Need the first style to compute the value
                     // We have at least a style. The first one is the winner.
-
                     String cssValue = CssValueConverter.toCssString(cssMetaList.getProperty(),
                             st.getDeclaration().getRule(), value.getValue());
 
@@ -1273,16 +1211,16 @@
                     /* 
                      * Each sub property can be ruled by a specific Origin, 
                      * we need to check if the sub property is in a rule of the passed origin.
-                     * For example, we can have background-radius set by caspian 
+                     * For example, we can have background-radius set by fxTheme 
                      * and background-color set by inline or author.
                      */
                     if (cssMetaList.getSubProperties() != null) {
                         for (CssMetaData sub : cssMetaList.getSubProperties()) {
                             List<CssStyle> notApplied = getNotAppliedStyles(entry.getValue(), node, sub);
                             for (Style style : entry.getValue()) {
+                                StyleOrigin styleOrigin = CssInternal.getOrigin(style);
                                 if (style.getDeclaration().getProperty().equals(sub.getProperty())
-                                        && (style.getDeclaration().getRule().getStylesheet().getOrigin() == origin)
-                                        && !CssInternal.isThemeStyle(style)) {
+                                        && (styleOrigin == origin)) {
                                     CssStyle cssStyle = retrieveStyle(entry.getValue(), style);
                                     String subCssValue = CssValueConverter.toCssString(sub.getProperty(), style.getDeclaration().getRule(), value.getValue());
                                     CssSubPropertyState subCss = new CssSubPropertyState(value, sub, subCssValue);
@@ -1318,51 +1256,5 @@
             }
             return propertyStates;
         }
-
-        private Collection<PropertyState> getAppliedIStyles(Node node) {
-            SortedSet<PropertyState> sorted = new TreeSet<>();
-            List<CssMetaData<? extends Styleable, ?>> cssMetaList = node.getCssMetaData();
-            for (CssMetaData<?, ?> cssMeta : cssMetaList) {
-                @SuppressWarnings("unchecked")
-                final CssMetaData<Node, ?> s = (CssMetaData<Node, ?>) cssMeta;
-                StyleableProperty<?> val = s.getStyleableProperty(node);
-                List<Style> styles = map.get(val);
-                if (styles != null) {
-                    StyleOrigin o = val.getStyleOrigin();
-                    /*
-                     * If the origin is not null and the property has sub properties, 
-                     * it doesn't mean that the property is to be ignored.
-                     * Some sub properties can be un-styled. This was one of the root cause of
-                     * DTL-5064
-                     */
-                    if (o != null && cssMeta.getSubProperties() == null) {
-                        continue;
-                    }
-                }
-                PropertyState ps = computeCurrentValue(node, s, fxomObject);
-                if (ps instanceof InitialPropertyState) {
-                    /*
-                     * XXX jfdenise, this check could be done before computing the value.
-                     * In some cases, some sub properties are styled by INLINE/USER/AUTHOR
-                     * In such a case, the sub properties must be removed from the initial sub properties.
-                     */
-                    if (!ps.getSubProperties().isEmpty()) {
-                        clearStyledSubProperty(((InitialPropertyState) ps), getAuthorStyles());
-                        clearStyledSubProperty(((InitialPropertyState) ps), getInlineStyles());
-                        clearStyledSubProperty(((InitialPropertyState) ps), getUserAgentStyles());
-                        // If no more sub properties, then forget about this property.
-                        if (!ps.getSubProperties().isEmpty()) {
-                            sorted.add(ps);
-                        }
-                    } else {
-                        sorted.add(ps);
-                    }
-                }
-
-            }
-            return sorted;
-        }
-
     }
-
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanel.fxml	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanel.fxml	Tue Dec 10 08:36:28 2013 +0100
@@ -65,7 +65,7 @@
                 <ToggleGroup fx:id="modes" />
               </toggleGroup>
             </ToggleButton>
-            <ToggleButton fx:id="picking" contentDisplay="GRAPHIC_ONLY" graphicTextGap="2.0" mnemonicParsing="false" onAction="#onSelectionModeSwitchAction" styleClass="toggle-button-right" toggleGroup="$modes">
+            <ToggleButton fx:id="pick" contentDisplay="GRAPHIC_ONLY" graphicTextGap="2.0" mnemonicParsing="false" onAction="#onSelectionModeSwitchAction" styleClass="toggle-button-right" toggleGroup="$modes">
               <tooltip>
                 <Tooltip text="%csspanel.picking.tooltip" />
               </tooltip>
@@ -89,7 +89,7 @@
         <TableColumn fx:id="propertiesColumn" editable="false" minWidth="150.0" prefWidth="200.0" resizable="false" sortable="false" text="%csspanel.col.properties" />
         <TableColumn fx:id="defaultColumn" editable="false" minWidth="100.0" prefWidth="100.0" sortable="false" text="%csspanel.col.defaults" visible="true" />
         <TableColumn fx:id="builtinColumn" editable="false" minWidth="100.0" prefWidth="100.0" sortable="false" text="%csspanel.col.api.defaults" visible="false" />
-        <TableColumn fx:id="caspianColumn" editable="false" minWidth="120.0" prefWidth="120.0" sortable="false" text="%csspanel.col.theme.defaults" visible="false" />
+        <TableColumn fx:id="fxThemeColumn" editable="false" minWidth="120.0" prefWidth="120.0" sortable="false" text="%csspanel.col.theme.defaults" visible="false" />
         <TableColumn fx:id="beanApiColumn" editable="false" minWidth="100.0" prefWidth="100.0" sortable="false" text="%csspanel.col.inspector" visible="true" />
         <TableColumn fx:id="stylesheetsColumn" editable="false" minWidth="100.0" prefWidth="100.0" sortable="false" text="%csspanel.col.stylesheets" />
         <TableColumn fx:id="inlineColumn" editable="false" minWidth="100.0" prefWidth="100.0" sortable="false" text="%csspanel.col.inline" />
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/CssPanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -50,7 +50,10 @@
 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup;
 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection;
 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
-import com.oracle.javafx.scenebuilder.kit.metadata.property.PropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.Metadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import com.oracle.javafx.scenebuilder.kit.util.CssInternal;
 import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
 import com.sun.javafx.css.ParsedValueImpl;
 import com.sun.javafx.css.Rule;
@@ -77,6 +80,7 @@
 import javafx.event.EventHandler;
 import javafx.fxml.FXML;
 import javafx.geometry.Orientation;
+import javafx.geometry.Point2D;
 import javafx.geometry.Pos;
 import javafx.geometry.VPos;
 import javafx.scene.Node;
@@ -115,7 +119,7 @@
     @FXML
     private TableColumn<CssProperty, CssProperty> builtinColumn;
     @FXML
-    private TableColumn<CssProperty, CssProperty> caspianColumn;
+    private TableColumn<CssProperty, CssProperty> fxThemeColumn;
     @FXML
     private TableColumn<CssProperty, CssProperty> inlineColumn;
     @FXML
@@ -123,7 +127,7 @@
     @FXML
     private TableColumn<CssProperty, CssProperty> defaultColumn;
     @FXML
-    private ToggleButton picking;
+    private ToggleButton pick;
     @FXML
     private ToggleButton edit;
     @FXML
@@ -161,7 +165,7 @@
             InspectorPanelController.class.getResource("images/cog.png").toExternalForm()); //NOI18N
     private static final Image lookups = new Image(
             CssPanelController.class.getResource("images/css-lookup-icon.png").toExternalForm()); //NOI18N
-    private static final Image pickingImg = new Image(
+    private static final Image pickImg = new Image(
             CssPanelController.class.getResource("images/css-cursor.png").toExternalForm()); //NOI18N
     private static final Image editImg = new Image(
             CssPanelController.class.getResource("images/css-button-arrow.png").toExternalForm()); //NOI18N
@@ -173,15 +177,23 @@
         TABLE, RULES, TEXT;
     }
 
-    private PropertyNavigator navigator = new PropertyNavigator();
-    private Object selectedObject; // Can be either an FXOMObject (selection mode), or a Node (picking mode)
+    private Object selectedObject; // Can be either an FXOMObject (selection mode), or a Node (pick mode)
     private Selection selection;
     @SuppressWarnings("rawtypes")
     private Callable onSelectionModeSwitch;
     private final EditorController editorController;
+    private final Delegate applicationDelegate;
     private final ObjectProperty<NodeCssState> cssStateProperty = new SimpleObjectProperty<>();
 
     /*
+     * Should be implemented by the application
+     */
+    public static abstract class Delegate {
+
+        public abstract void revealInspectorEditor(ValuePropertyMetadata propMeta);
+    }
+
+    /*
      * AbstractPanelController
      */
     @Override
@@ -212,7 +224,11 @@
         if (isCssPanelLoaded() && hasFxomDocument()) {
             selection = editorController.getSelection();
             if (!isMultipleSelection()) {
-                selectedObject = getFXOMInstance(selection);
+                if (isPickMode()) {
+                    selectedObject = selection.findHitNode();
+                } else {
+                    selectedObject = getFXOMInstance(selection);
+                }
             }
             refresh();
         }
@@ -227,13 +243,25 @@
         root.getChildren().remove(rulesPane);
         root.getChildren().remove(textPane);
         root.getChildren().remove(table);
-//        initializeMenu();
 
-        picking.setGraphic(new ImageView(pickingImg));
-        // TODO : implement picking. In the meantime, disable the menu buttons.
-        picking.setDisable(true);
+        pick.setGraphic(new ImageView(pickImg));
+        pick.setOnAction(new EventHandler<ActionEvent>() {
+
+            @Override
+            public void handle(ActionEvent t) {
+                editorController.setPickModeEnabled(true);
+            }
+        });
         edit.setGraphic(new ImageView(editImg));
-        edit.setDisable(true);
+        edit.setSelected(true);
+        editorController.pickModeEnabledProperty().addListener(new ChangeListener<Boolean>() {
+
+            @Override
+            public void changed(ObservableValue<? extends Boolean> ov, Boolean oldVal, Boolean newVal) {
+                setPickMode(newVal);
+            }
+        });
+        
         table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
         initialOrder = FXCollections.observableArrayList(table.getColumns());
         reversedOrder = FXCollections.observableArrayList(table.getColumns());
@@ -249,8 +277,8 @@
         builtinColumn.setCellValueFactory(valueFactory);
         builtinColumn.setCellFactory(new BuiltinCellFactory());
 
-        caspianColumn.setCellValueFactory(valueFactory);
-        caspianColumn.setCellFactory(new CaspianCellFactory());
+        fxThemeColumn.setCellValueFactory(valueFactory);
+        fxThemeColumn.setCellFactory(new FxThemeCellFactory());
 
         beanApiColumn.setCellValueFactory(valueFactory);
         beanApiColumn.setCellFactory(new ModelCellFactory());
@@ -278,7 +306,10 @@
                     Node selectedSubNode = CssUtils.getNode(newValue.getItem());
                     selectedObject = selectedSubNode;
                     refresh();
-                    // TODO: update the (SB) selection
+                    // TODO: use the hit point method from Eric
+                    selection.select(getFXOMInstance(selection), Point2D.ZERO);
+                    // Switch to pick mode
+                    setPickMode(true);
                 }
             }
         };
@@ -317,11 +348,11 @@
         }
     }
 
-    private class CaspianCellFactory implements Callback<TableColumn<CssProperty, CssProperty>, TableCell<CssProperty, CssProperty>> {
+    private class FxThemeCellFactory implements Callback<TableColumn<CssProperty, CssProperty>, TableCell<CssProperty, CssProperty>> {
 
         @Override
         public TableCell<CssProperty, CssProperty> call(TableColumn<CssProperty, CssProperty> param) {
-            return new CaspianValueTableCell();
+            return new FxThemeValueTableCell();
         }
     }
 
@@ -362,9 +393,10 @@
      * Public
      *
      */
-    public CssPanelController(EditorController c) {
-        super(CssPanelController.class.getResource("CssPanel.fxml"), c);
+    public CssPanelController(EditorController c, Delegate delegate) {
+        super(CssPanelController.class.getResource("CssPanel.fxml"), I18N.getBundle(), c);
         this.editorController = c;
+        this.applicationDelegate = delegate;
     }
 
     public String getSearchPattern() {
@@ -393,14 +425,6 @@
         root.getChildren().add(message);
     }
 
-    public void stageViewModeDidChange() {
-        /// TODO : check with Eric
-
-//        final boolean pickingEnabled = frame.getStageView().getMode() == StageView.Mode.CSS_PICK;
-//        edit.setSelected(!pickingEnabled);
-//        picking.setSelected(pickingEnabled);
-    }
-
     public final Node getRulesPane() {
         return rulesPane;
     }
@@ -446,18 +470,6 @@
         }
     }
 
-    public static class PropertyNavigator {
-
-        public void navigate(Object component, PropertyMetadata propertyMeta) {
-            // TODO
-
-//            AreaPanel ap = frame.getRight();
-//            InspectorPanel ip = ap.getInspectorPanel();
-//            ip.setFocusToProp(prop);
-            throw new UnsupportedOperationException("Navigation to inspector property is not yet supported!");
-        }
-    }
-
     @SuppressWarnings("rawtypes")
     public void setOnSelectionModeSwitch(Callable callable) {
         onSelectionModeSwitch = callable;
@@ -592,6 +604,14 @@
         assert selObject instanceof Node;
         return (Node) selObject;
     }
+    
+    private boolean isPickMode() {
+        return pick.isSelected();
+    }
+
+    private void setPickMode(boolean pickMode) {
+        pick.setSelected(pickMode);
+    }
 
     private void fillSelectionContent() {
         assert selectedObject != null;
@@ -787,13 +807,9 @@
         selectionPath.selected().removeListener(selectionListener);
     }
 
-    void setPropertyNavigator(PropertyNavigator navigator) {
-        this.navigator = navigator;
-    }
-
     private void unmerge() {
         defaultColumn.setVisible(!advanced);
-        caspianColumn.setVisible(advanced);
+        fxThemeColumn.setVisible(advanced);
         builtinColumn.setVisible(advanced);
     }
 
@@ -1036,9 +1052,9 @@
                     }
                 }
             }
-            // Case where an API call has been made, not applied caspian (if any) are hidden
+            // Case where an API call has been made, not applied fxTheme (if any) are hidden
             if (getOrigin(item) == StyleOrigin.USER_AGENT) {
-                List<CssPropertyState.CssStyle> styles = item.getCaspianHiddenByModel();
+                List<CssPropertyState.CssStyle> styles = item.getFxThemeHiddenByModel();
                 for (CssPropertyState.CssStyle style : styles) {
                     Node n = createValueUI(item, style);
                     if (n == null) {
@@ -1068,7 +1084,7 @@
             if (nav != null) {
                 Label navigationLabel = new Label(nav);
                 navigationLabel.getStyleClass().add("note-label");//NOI18N
-                if (origin != null && origin != StyleOrigin.USER_AGENT) {// No arrow for builtin and caspian
+                if (origin != null && origin != StyleOrigin.USER_AGENT) {// No arrow for builtin and fxTheme
                     createNavigationMenuButton();
                     openStylesheetMenuItem
                             = new MenuItem(MessageFormat.format(I18N.getString("csspanel.open.stylesheet"), nav));
@@ -1081,7 +1097,10 @@
                                 navigate(item, getPropertyState(item), style, origin);
                             }
                         });
-                        revealInInspectorMenuItem.setDisable(true); // Until this is supported
+                        if (CssPanelController.this.applicationDelegate == null) {
+                            // disable the menu item in this case
+                            revealInInspectorMenuItem.setDisable(true);
+                        }
                     } else if (origin == StyleOrigin.AUTHOR) {
                         // Stylesheets column
                         navigationMenuButton.getItems().add(openStylesheetMenuItem);
@@ -1144,16 +1163,16 @@
     }
 
     // "FX Theme defaults" column
-    private class CaspianValueTableCell extends CssValueTableCell {
+    private class FxThemeValueTableCell extends CssValueTableCell {
 
         @Override
         protected PropertyState getPropertyState(CssProperty item) {
-            return item.caspianState().get();
+            return item.fxThemeState().get();
         }
 
         @Override
         protected boolean isWinner(CssProperty item) {
-            return item.isCaspianSource();
+            return item.isFxThemeSource();
         }
 
         @Override
@@ -1163,7 +1182,7 @@
 
         @Override
         protected CssStyle getStyle(CssProperty item) {
-            CssPropertyState ps = item.caspianState().get();
+            CssPropertyState ps = item.fxThemeState().get();
             return ps == null ? null : ps.getStyle();
         }
     }
@@ -1243,16 +1262,16 @@
     }
 
     /**
-     * XXX jfdenise, handle case where the Caspian is not the winning style. The
+     * XXX jfdenise, handle case where the Fx Theme is not the winning style. The
      * complex case is that we need to return a propertyState BUT we don't know
-     * if caspian has been overriden, then we do return null.
+     * if Fx Theme has been overriden, then we do return null.
      */
     // "Defaults" column
     private class DefaultValueTableCell extends CssValueTableCell {
 
         @Override
         protected PropertyState getPropertyState(CssProperty item) {
-            PropertyState ret = item.caspianState().get();
+            PropertyState ret = item.fxThemeState().get();
             if (ret == null) {
                 // Do we have an override
                 boolean foundNotApplied = false;
@@ -1276,8 +1295,8 @@
         @Override
         protected CssStyle getStyle(CssProperty item) {
             CssStyle style = null;
-            CssPropertyState caspian = item.caspianState().get();
-            if (caspian == null) {
+            CssPropertyState fxTheme = item.fxThemeState().get();
+            if (fxTheme == null) {
                 // Do we have an override
                 PropertyState winner = item.getWinner();
                 if (winner != null) {
@@ -1291,20 +1310,20 @@
                 }
 
             } else {
-                style = caspian.getStyle();
+                style = fxTheme.getStyle();
             }
             return style;
         }
 
         @Override
         protected boolean isWinner(CssProperty item) {
-            return item.isCaspianSource() || item.isBuiltinSource();
+            return item.isFxThemeSource() || item.isBuiltinSource();
         }
 
         @Override
         protected StyleOrigin getOrigin(CssProperty item) {
             PropertyState state = getPropertyState(item);
-            // If null is returned, means that there is a not applied for caspian
+            // If null is returned, means that there is a not applied for fxTheme
             if (state instanceof CssPropertyState || state == null) {
                 return StyleOrigin.USER_AGENT;
             } else {
@@ -1317,8 +1336,8 @@
         protected String getNavigation(CssProperty item, CssStyle style) {
             PropertyState ps = getPropertyState(item);
             if (ps == null || ps instanceof CssPropertyState) {
-                return I18N.getString("csspanel.caspian.defaults.navigation")
-                        + " (caspian.css)";//NOI18N
+                return I18N.getString("csspanel.fxtheme.defaults.navigation")
+                        + " (" + CssInternal.getThemeName(style.getStyle()) + ".css)";//NOI18N
             } else {
                 return I18N.getString("csspanel.api.defaults.navigation");
             }
@@ -1343,9 +1362,11 @@
     private void navigate(CssProperty item, PropertyState state, CssStyle style, StyleOrigin origin, boolean open) {
 
         if (origin == StyleOrigin.USER) {// Navigate to property
-            BeanPropertyState bp = (BeanPropertyState) state;
-            // XXX TODO, define a Navigation manager in the SB
-            navigator.navigate(item.getTarget(), bp.getPropertyMeta());
+            PropertyName propName = ((BeanPropertyState) state).getPropertyMeta().getName();
+            // Navigate to inspector property
+            if (applicationDelegate != null) {
+                applicationDelegate.revealInspectorEditor(getValuePropertyMeta(propName));
+            }
         }
         if (style != null) {
             if (style.getOrigin() == StyleOrigin.AUTHOR) {// Navigate to file
@@ -1366,9 +1387,10 @@
             } else {
                 if (style.getOrigin() == StyleOrigin.INLINE) {
                     // Navigate to inspector style property
-                    // TODO
-                    throw new UnsupportedOperationException("Navigation to inspector style is not yet supported!");
-//                    navigator.navigate(item.getTarget(), "style"); //NOI18N
+                    if (applicationDelegate != null) {
+                        applicationDelegate.revealInspectorEditor(
+                                getValuePropertyMeta(new PropertyName("style"))); //NOI18N
+                    }
                 }
             }
         }
@@ -1377,7 +1399,7 @@
     private static String getNavigationInfo(
             CssProperty item, CssStyle cssStyle, StyleOrigin origin) {
         if (origin == StyleOrigin.USER_AGENT) {
-            return "caspian.css"; //NOI18N
+             return CssInternal.getThemeName(cssStyle.getStyle()) + ".css"; //NOI18N
         }
         if (origin == StyleOrigin.USER) {
             BeanPropertyState state = (BeanPropertyState) item.modelState().get();
@@ -1419,14 +1441,6 @@
      *
      */
     private static FXOMInstance getFXOMInstance(Selection selection) {
-        // TODO
-        //        SelectionContext context = frame.getProject().getSelection();
-        //        Node pNode = context.getFXOMInstance();
-        //        if(context.getPrimarySelection() != null && 
-        //                (pNode == null || frame.getStageView().getMode() != Mode.CSS_PICK)){
-        //            pNode = CssUtils.getNode(context.getPrimarySelection().getChildComponent());
-        //        }
-
         FXOMInstance fxomInstance = null;
         if (selection == null) {
             return null;
@@ -1445,6 +1459,15 @@
         return fxomInstance;
     }
 
+    private ValuePropertyMetadata getValuePropertyMeta(PropertyName propName) {
+        ValuePropertyMetadata valuePropMeta = null;
+        if (selectedObject instanceof FXOMInstance) {
+            valuePropMeta = Metadata.getMetadata().queryValueProperty(
+                    (FXOMInstance) selectedObject, propName);
+        }
+        return valuePropMeta;
+    }
+
     private static String getPseudoStates(Node node) {
         StringBuilder pseudoClasses = new StringBuilder();
         Set<PseudoClass> pseudoClassSet = node.getPseudoClassStates();
@@ -1792,7 +1815,7 @@
             } catch (MalformedURLException ex) {
                 System.out.println("Invalid URL: " + ex);
             }
-            origin = rule.getOrigin();
+            origin = CssInternal.getOrigin(rule);
         }
         return getSource(url, origin);
     }
@@ -1801,7 +1824,7 @@
         String source = null;
         if (url != null) {
             if (origin == StyleOrigin.USER_AGENT) {
-                source = I18N.getString("csspanel.caspian.origin");
+                source = I18N.getString("csspanel.fxtheme.origin");
             } else {
                 if (origin == StyleOrigin.USER) {
                     source = I18N.getString("csspanel.api.origin")
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/AbstractHierarchyPanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/AbstractHierarchyPanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -194,7 +194,7 @@
      * Public
      */
     public AbstractHierarchyPanelController(URL fxmlURL, EditorController editorController) {
-        super(fxmlURL, editorController);
+        super(fxmlURL, I18N.getBundle(), editorController);
         promptLabel.getStyleClass().add("hierarchy-prompt-label");
     }
 
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/treeview/HierarchyTreeCell.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/hierarchy/treeview/HierarchyTreeCell.java	Tue Dec 10 08:36:28 2013 +0100
@@ -382,88 +382,93 @@
                         } else {
                             final HierarchyItem item = treeItem.getValue();
                             assert item != null;
-                            assert item.isPlaceHolder() == false;
 
-                            // REORDERING :
-                            // To avoid visual movement of the horizontal border when
-                            // dragging from one cell to another,
-                            // we always set the border on the cell bottom location :
-                            // - if we handle REORDER BELOW gesture, just set the bottom 
-                            // border on the current cell
-                            // - if we handle REORDER ABOVE gesture, we set the bottom 
-                            // border on the previous cell
-                            //
-                            switch (location) {
+                            if (item.isPlaceHolder()) {
+                                // The place holder item is filled with a container
+                                // accepting sub components
+                                HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
+                            } else {
+                                // REORDERING :
+                                // To avoid visual movement of the horizontal border when
+                                // dragging from one cell to another,
+                                // we always set the border on the cell bottom location :
+                                // - if we handle REORDER BELOW gesture, just set the bottom 
+                                // border on the current cell
+                                // - if we handle REORDER ABOVE gesture, we set the bottom 
+                                // border on the previous cell
+                                //
+                                switch (location) {
 
-                                // REORDER ABOVE gesture
-                                case TOP:
-                                    if (treeItem == rootTreeItem) {
-                                        HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
-                                    } else {
-                                        final int index = getIndex();
+                                    // REORDER ABOVE gesture
+                                    case TOP:
+                                        if (treeItem == rootTreeItem) {
+                                            HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
+                                        } else {
+                                            final int index = getIndex();
                                         // Retrieve the previous cell
-                                        // Note : we set the border on the bottom of the previous cell 
-                                        // instead of using the top of the current cell in order to avoid
-                                        // visual gap when DND from one cell to another
-                                        final TreeCell<?> previousCell
-                                                = HierarchyTreeViewUtils.getTreeCell(getTreeView(), index - 1);
-                                        // The previous cell is null when the item is not visible
-                                        if (previousCell != null) {
-                                            previousCell.getStyleClass().add(CELL_BORDER_BOTTOM);
+                                            // Note : we set the border on the bottom of the previous cell 
+                                            // instead of using the top of the current cell in order to avoid
+                                            // visual gap when DND from one cell to another
+                                            final TreeCell<?> previousCell
+                                                    = HierarchyTreeViewUtils.getTreeCell(getTreeView(), index - 1);
+                                            // The previous cell is null when the item is not visible
+                                            if (previousCell != null) {
+                                                previousCell.getStyleClass().add(CELL_BORDER_BOTTOM);
+                                            }
+
+                                            // Update vertical insert line
+                                            startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
+                                            startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
+                                            stopCell = previousCell;
+                                            updateInsertLineIndicator(startCell, stopCell);
+                                            panelController.addToPanelControlSkin(insertLineIndicator);
                                         }
+                                        break;
 
-                                        // Update vertical insert line
-                                        startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
-                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
-                                        stopCell = previousCell;
-                                        updateInsertLineIndicator(startCell, stopCell);
-                                        panelController.addToPanelControlSkin(insertLineIndicator);
-                                    }
-                                    break;
+                                    // REPARENT gesture
+                                    case CENTER:
+                                        if (treeItem.isLeaf() || !treeItem.isExpanded()) {
+                                            HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
+                                        } else {
+                                            // Reparent to the treeItem as last child
+                                            final TreeItem<?> lastTreeItem = panelController.getLastVisibleTreeItem(treeItem);
+                                            final TreeCell<?> lastCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), lastTreeItem);
+                                            // Last cell is null when the item is not visible
+                                            if (lastCell != null) {
+                                                lastCell.getStyleClass().add(CELL_BORDER_BOTTOM);
+                                            }
 
-                                // REPARENT gesture
-                                case CENTER:
-                                    if (treeItem.isLeaf() || !treeItem.isExpanded()) {
-                                        HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
-                                    } else {
-                                        // Reparent to the treeItem as last child
-                                        final TreeItem<?> lastTreeItem = panelController.getLastVisibleTreeItem(treeItem);
-                                        final TreeCell<?> lastCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), lastTreeItem);
-                                        // Last cell is null when the item is not visible
-                                        if (lastCell != null) {
-                                            lastCell.getStyleClass().add(CELL_BORDER_BOTTOM);
+                                            // Update vertical insert line
+                                            startTreeItem = getTreeItem();
+                                            startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
+                                            stopCell = lastCell;
+                                            updateInsertLineIndicator(startCell, stopCell);
+                                            panelController.addToPanelControlSkin(insertLineIndicator);
                                         }
+                                        break;
 
-                                        // Update vertical insert line
-                                        startTreeItem = getTreeItem();
-                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
-                                        stopCell = lastCell;
-                                        updateInsertLineIndicator(startCell, stopCell);
-                                        panelController.addToPanelControlSkin(insertLineIndicator);
-                                    }
-                                    break;
+                                    // REORDER BELOW gesture
+                                    case BOTTOM:
+                                        if (treeItem == rootTreeItem
+                                                && (treeItem.isLeaf() || !treeItem.isExpanded())) {
+                                            HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
+                                        } else {
+                                            // Reparent to the treeItem as first child
+                                            HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_BOTTOM);
 
-                                // REORDER BELOW gesture
-                                case BOTTOM:
-                                    if (treeItem == rootTreeItem
-                                            && (treeItem.isLeaf() || !treeItem.isExpanded())) {
-                                        HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_TOP_RIGHT_BOTTOM_LEFT);
-                                    } else {
-                                        // Reparent to the treeItem as first child
-                                        HierarchyTreeCell.this.getStyleClass().add(CELL_BORDER_BOTTOM);
+                                            // Update vertical insert line
+                                            startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
+                                            startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
+                                            stopCell = HierarchyTreeCell.this;
+                                            updateInsertLineIndicator(startCell, stopCell);
+                                            panelController.addToPanelControlSkin(insertLineIndicator);
+                                        }
+                                        break;
 
-                                        // Update vertical insert line
-                                        startTreeItem = panelController.lookupTreeItem(dropTarget.getTargetObject());
-                                        startCell = HierarchyTreeViewUtils.getTreeCell(getTreeView(), startTreeItem);
-                                        stopCell = HierarchyTreeCell.this;
-                                        updateInsertLineIndicator(startCell, stopCell);
-                                        panelController.addToPanelControlSkin(insertLineIndicator);
-                                    }
-                                    break;
-
-                                default:
-                                    assert false;
-                                    break;
+                                    default:
+                                        assert false;
+                                        break;
+                                }
                             }
                         }
                     }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,13 +35,11 @@
 import com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform;
 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
 import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
-import com.oracle.javafx.scenebuilder.kit.editor.job.ModifyFxControllerJob;
 import com.oracle.javafx.scenebuilder.kit.editor.job.ModifyFxIdJob;
 import com.oracle.javafx.scenebuilder.kit.editor.job.ModifySelectionJob;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.AnchorPaneConstraintsEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.BooleanEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.BoundedDoubleEditor;
-import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.ControllerClassEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.CursorEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.DoubleEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.Editor;
@@ -51,6 +49,7 @@
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.FxIdEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.GenericEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.I18nStringEditor;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.ImageEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.InsetsEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.IntegerEditor;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.PropertiesEditor;
@@ -77,6 +76,7 @@
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.DoublePropertyMetadata.DoubleKind;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.EnumerationPropertyMetadata;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.EventHandlerPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.metadata.property.value.ImagePropertyMetadata;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.InsetsPropertyMetadata;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.IntegerPropertyMetadata;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.StringPropertyMetadata;
@@ -107,6 +107,7 @@
 import javafx.beans.value.ObservableValue;
 import javafx.fxml.FXML;
 import javafx.geometry.HPos;
+import javafx.geometry.Point2D;
 import javafx.geometry.Pos;
 import javafx.geometry.VPos;
 import javafx.scene.Node;
@@ -189,6 +190,7 @@
     private static final String fxmlFile = "Inspector.fxml"; //NOI18N
     private String searchPattern;
     private SectionId previousExpandedSection;
+    private PropertyEditor lastPropertyEditorValueChanged = null;
     //
     // Editor pools
     private final Stack<Editor> i18nStringEditorPool = new Stack<>();
@@ -205,11 +207,10 @@
     private final Stack<Editor> styleClassEditorPool = new Stack<>();
     private final Stack<Editor> stylesheetEditorPool = new Stack<>();
     private final Stack<Editor> fxIdEditorPool = new Stack<>();
-    private final Stack<Editor> controllerClassEditorPool = new Stack<>();
     private final Stack<Editor> eventHandlerEditorPool = new Stack<>();
     private final Stack<Editor> cursorEditorPool = new Stack<>();
     private final Stack<Editor> paintPopupEditorPool = new Stack<>();
-//    private final Stack<Editor> fontEditorPool = new Stack<>();
+    private final Stack<Editor> imageEditorPool = new Stack<>();
     // ...
     //
     // Subsection title pool
@@ -243,7 +244,7 @@
      * Public
      */
     public InspectorPanelController(EditorController editorController) {
-        super(InspectorPanelController.class.getResource(fxmlFile), editorController);
+        super(InspectorPanelController.class.getResource(fxmlFile), I18N.getBundle(), editorController);
         this.editorController = editorController;
 
         // Editor pools init
@@ -261,11 +262,10 @@
         editorPools.put(StyleClassEditor.class, styleClassEditorPool);
         editorPools.put(StylesheetEditor.class, stylesheetEditorPool);
         editorPools.put(FxIdEditor.class, fxIdEditorPool);
-        editorPools.put(ControllerClassEditor.class, controllerClassEditorPool);
         editorPools.put(EventHandlerEditor.class, eventHandlerEditorPool);
         editorPools.put(CursorEditor.class, cursorEditorPool);
         editorPools.put(PaintPopupEditor.class, paintPopupEditorPool);
-//        editorPools.put(FontPopupEditor.class, fontEditorPool);
+        editorPools.put(ImageEditor.class, imageEditorPool);
         // ...
     }
 
@@ -560,8 +560,15 @@
 //        System.out.println("Refresh all the editors in use...");
 
         for (Editor editor : editorsInUse) {
+
             if (editor instanceof PropertyEditor) {
+                if (editor == lastPropertyEditorValueChanged) {
+                    // do not reset an editor that just changed its value and initiated the reset
+                    lastPropertyEditorValueChanged = null;
+                    continue;
+                }
                 resetPropertyEditor((PropertyEditor) editor);
+//                System.out.println("reset " + ((PropertyEditor) editor).getPropertyNameText());
             }
             setEditorValueFromSelection(editor);
         }
@@ -615,10 +622,6 @@
         if (sectionId == SectionId.CODE) {
             // add fx:id here, since it is not a property
             lineIndex = addFxIdEditor(gridPane, lineIndex);
-            // Add controller class if single selection, for the root node
-            if ((getSelectedInstances().size() == 1) && isRootSelectedInstance()) {
-                lineIndex = addControllerClassEditor(gridPane, lineIndex);
-            }
         }
         Set<PropertyName> groupProperties = new HashSet<>();
         while (iter.hasNext()) {
@@ -679,17 +682,11 @@
         return addInGridPane(gridPane, propertyEditor, lineIndex);
     }
 
-    private int addControllerClassEditor(GridPane gridPane, int lineIndex) {
-        PropertyEditor propertyEditor = makePropertyEditor(ControllerClassEditor.class, null);
-        setControllerClassFromSelection(propertyEditor);
-        handlePropertyEditorChanges(propertyEditor);
-        return addInGridPane(gridPane, propertyEditor, lineIndex);
-    }
-
     private void handlePropertyEditorChanges(PropertyEditor propertyEditor) {
         handleValueChange(propertyEditor);
         handleEditingChange(propertyEditor);
         handleIndeterminateChange(propertyEditor);
+        handleNavigateRequest(propertyEditor);
     }
 
     private boolean isGroupedProperty(PropertyName propName) {
@@ -997,6 +994,7 @@
         propertyEditor.addValueListener(new ChangeListener<Object>() {
             @Override
             public void changed(ObservableValue<? extends Object> ov, Object oldValue, Object newValue) {
+                lastPropertyEditorValueChanged = propertyEditor;
                 updateValueInModel(propertyEditor, oldValue, newValue);
                 if (propertyEditor.isRuledByCss()) {
                     editorController.getMessageLog().logWarningMessage(
@@ -1015,9 +1013,6 @@
         if (propertyEditor instanceof FxIdEditor) {
             assert (newValue instanceof String) || (newValue == null);
             setSelectedFXOMInstanceFxId(getSelectedInstance(), (String) newValue);
-        } else if (propertyEditor instanceof ControllerClassEditor) {
-            assert (newValue instanceof String) || (newValue == null);
-            setSelectedFXOMInstanceControllerClass(getSelectedInstance(), (String) newValue);
         } else {
             setSelectedFXOMInstances(propertyEditor.getPropertyMeta(), newValue);
         }
@@ -1074,6 +1069,19 @@
 
     }
 
+    private void handleNavigateRequest(PropertyEditor propertyEditor) {
+        // Handle a navigate request from an editor
+        propertyEditor.addNavigateListener(new ChangeListener<String>() {
+
+            @Override
+            public void changed(ObservableValue<? extends String> ov, String oldStr, String newStr) {
+                if (newStr != null) {
+                    setFocusToEditor(new PropertyName(newStr));
+                }
+            }
+        });
+    }
+
     private void setSelectedFXOMInstances(ValuePropertyMetadata propMeta, Object value) {
         final ModifySelectionJob job = new ModifySelectionJob(propMeta, value, getEditorController());
 //        System.out.println(job.getDescription());
@@ -1085,11 +1093,6 @@
         pushJob(job);
     }
 
-    private void setSelectedFXOMInstanceControllerClass(FXOMObject fxomObject, String controllerClass) {
-        final ModifyFxControllerJob job = new ModifyFxControllerJob(fxomObject, controllerClass, getEditorController());
-        pushJob(job);
-    }
-
     private void pushJob(Job job) {
         if (job.isExecutable()) {
             getEditorController().getJobManager().push(job);
@@ -1117,8 +1120,6 @@
     private void setEditorValueFromSelection(Editor editor) {
         if (editor instanceof FxIdEditor) {
             setFxIdFromSelection(editor);
-        } else if (editor instanceof ControllerClassEditor) {
-            setControllerClassFromSelection(editor);
         } else if (isPropertyEditor(editor)) {
             setEditorValueFromSelection((PropertyEditor) editor);
         } else if (isPropertiesEditor(editor)) {
@@ -1146,16 +1147,6 @@
         }
     }
 
-    // Set the controller class from selection
-    private void setControllerClassFromSelection(Editor editor) {
-        assert editor instanceof ControllerClassEditor;
-        ControllerClassEditor controllerClassEditor = (ControllerClassEditor) editor;
-        controllerClassEditor.setDisable(false);
-        controllerClassEditor.setUpdateFromModel(true);
-        controllerClassEditor.setValue(getControllerClass());
-        controllerClassEditor.setUpdateFromModel(false);
-    }
-
     // Set the editor value from selection
     private void setEditorValueFromSelection(PropertyEditor propertyEditor) {
 
@@ -1190,6 +1181,13 @@
             }
         }
 
+        if (isRuledByCss) {
+            propertyEditor.setRuledByCss(true);
+            propertyEditor.setCssInfo(cssInfo);
+        } else {
+            propertyEditor.setRuledByCss(false);
+            propertyEditor.setCssInfo(null);
+        }
         if (isIndeterminate) {
             propertyEditor.setUpdateFromModel(true);
             propertyEditor.setIndeterminate(true);
@@ -1199,14 +1197,7 @@
             propertyEditor.setValue(val);
             propertyEditor.setUpdateFromModel(false);
         }
-        
-        if (isRuledByCss) {
-            propertyEditor.setRuledByCss(true);
-            propertyEditor.setCssInfo(cssInfo);
-        } else {
-            propertyEditor.setRuledByCss(false);
-            propertyEditor.setCssInfo(null);
-        }
+
         if (!(propertyEditor instanceof GenericEditor)) {
             if (!isReadWrite) {
                 propertyEditor.setDisable(true);
@@ -1277,9 +1268,9 @@
         } else if (propMeta instanceof PaintPropertyMetadata) {
             // Paint editor
             propertyEditor = makePropertyEditor(PaintPopupEditor.class, propMeta);
-//        } else if (propMeta instanceof FontPropertyMetadata) {
-//            // Font editor
-//            propertyEditor = makePropertyEditor(FontPopupEditor.class, propMeta);
+        } else if (propMeta instanceof ImagePropertyMetadata) {
+            // Image editor
+            propertyEditor = makePropertyEditor(ImageEditor.class, propMeta);
         } else {
             // Generic editor
             propertyEditor = makePropertyEditor(GenericEditor.class, propMeta);
@@ -1544,12 +1535,6 @@
             } else {
                 propertyEditor = new FxIdEditor(getSuggestedFxIds(controllerClass));
             }
-        } else if (editorClass == ControllerClassEditor.class) {
-            if (propertyEditor != null) {
-                ((ControllerClassEditor) propertyEditor).reset(getSuggestedControllerClasses());
-            } else {
-                propertyEditor = new ControllerClassEditor(getSuggestedControllerClasses());
-            }
         } else if (editorClass == CursorEditor.class) {
             if (propertyEditor != null) {
                 ((CursorEditor) propertyEditor).reset(propMeta, selectedClasses);
@@ -1568,12 +1553,12 @@
             } else {
                 propertyEditor = new PaintPopupEditor(propMeta, selectedClasses);
             }
-//        } else if (editorClass == FontPopupEditor.class) {
-//            if (propertyEditor != null) {
-//                ((FontPopupEditor) propertyEditor).reset(propMeta, selectedClasses);
-//            } else {
-//                propertyEditor = new FontPopupEditor(propMeta, selectedClasses);
-//            }
+        } else if (editorClass == ImageEditor.class) {
+            if (propertyEditor != null) {
+                ((ImageEditor) propertyEditor).reset(propMeta, selectedClasses);
+            } else {
+                propertyEditor = new ImageEditor(propMeta, selectedClasses);
+            }
         } else {
             if (propertyEditor != null) {
                 ((GenericEditor) propertyEditor).reset(propMeta, selectedClasses);
@@ -1700,15 +1685,6 @@
         return glossary.queryEventHandlers(location, controllerClass);
     }
 
-    private List<String> getSuggestedControllerClasses() {
-        Glossary glossary = getEditorController().getGlossary();
-        URL location = null;
-        if (getEditorController().getFxomDocument() != null) {
-            location = getEditorController().getFxomDocument().getLocation();
-        }
-        return glossary.queryControllerClasses(location);
-    }
-
     private String getControllerClass() {
         return getEditorController().getFxomDocument().getFxomRoot().getFxController();
     }
@@ -1742,10 +1718,6 @@
         return (Class<?>) getSelectedClasses().toArray()[0];
     }
 
-    private boolean isRootSelectedInstance() {
-        return getSelectedInstance().getParentObject() == null;
-    }
-
     private Class<?> getCommonParent() {
         return selectionState.getCommonParent();
     }
@@ -1854,4 +1826,76 @@
 
     }
 
+    /*
+     * Set the focus to a given property value editor,
+     * and move the scrolllbar so that it is visible.
+     * Typically used by CSS analyzer.
+     */
+    public void setFocusToEditor(PropertyName propName) {
+        // Retrieve the editor
+        PropertyEditor editor = null;
+        for (Editor ed : editorsInUse) {
+            if (ed instanceof PropertyEditor) {
+                if (propName.equals(((PropertyEditor) ed).getPropertyName())) {
+                    editor = (PropertyEditor) ed;
+                }
+            }
+        }
+        if (editor == null) {
+            // editor not found
+            return;
+        }
+
+        final PropertyEditor editorToFocus = editor;
+
+        final Node valueEditorNode = editorToFocus.getValueEditor();
+        // Search the ScrollPane
+        ScrollPane sp = null;
+        Node node = valueEditorNode.getParent();
+        while (node != null) {
+            if (node instanceof ScrollPane) {
+                sp = (ScrollPane) node;
+                break;
+            }
+            node = node.getParent();
+        }
+        if (sp == null) {
+            return;
+        }
+        
+        // Position the scrollBar such as the editor is centered in the TitledPane (when possible)
+        final ScrollPane scrollPane = sp;
+        double editorHeight = valueEditorNode.getLayoutBounds().getHeight();
+        final Point2D pt = scrollPane.getContent().sceneToLocal(valueEditorNode.localToScene(0, 0));
+        // viewport height
+        double vpHeight = scrollPane.getViewportBounds().getHeight();
+        // Position of the editor in the scrollPane content
+        double selY = pt.getY();
+        // Height of the scrollPane content
+        double contentHeight = scrollPane.getContent().getLayoutBounds().getHeight();
+        // Position of the middle point of the scrollPane content
+        double contentMiddle = contentHeight / 2;
+        // Manage the editor height depending on its position
+        if (selY > contentMiddle) {
+            selY += editorHeight;
+        } else {
+            selY -= editorHeight;
+        }
+        // Compute the move to apply to position the editor on the middle of the scrollPane content
+        double moveContent = selY - contentMiddle;
+        // Size ratio between scrollPane content and viewport
+        double vpRatio = contentHeight / vpHeight;
+        // Move to apply to the editor to position it in the middle of the viewport
+        double moveVp = moveContent / vpRatio;
+        // Position of the editor in the viewport
+        double selYVp = (vpHeight / 2) + moveVp;
+        // Position in percent
+        double scrollPos = selYVp / vpHeight;
+        // Finally, set the scrollBar position
+        scrollPane.setVvalue(scrollPos);
+        
+        // Set the focus to the editor
+        editorToFocus.requestFocus();
+    }
+
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AnchorPaneConstraintsEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AnchorPaneConstraintsEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -339,7 +339,7 @@
         }
 
         @Override
-        protected void requestFocus() {
+        public void requestFocus() {
             EditorUtils.doNextFrame(new Runnable() {
 
                 @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AutoSuggestEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/AutoSuggestEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -53,6 +53,8 @@
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
 
 /**
  * Abstract editor that provide a text field with an auto-suggest popup.
@@ -110,18 +112,19 @@
     private void preInit(List<String> suggestedList) {
         this.suggestedList = suggestedList;
         if (type == Type.ALPHA) {
-            root = EditorUtils.loadFxml("StringAutoSuggestEditor.fxml", this);
+            root = EditorUtils.loadFxml("StringAutoSuggestEditor.fxml", this); //NOI18N
             assert textField != null;
             entryField = textField;
         } else if (type == Type.DOUBLE) {
-            root = EditorUtils.loadFxml("DoubleAutoSuggestEditor.fxml", this);
+            root = EditorUtils.loadFxml("DoubleAutoSuggestEditor.fxml", this); //NOI18N
             entryField = doubleField;
         } else {
             assert type == Type.INTEGER;
-            root = EditorUtils.loadFxml("IntegerAutoSuggestEditor.fxml", this);
+            root = EditorUtils.loadFxml("IntegerAutoSuggestEditor.fxml", this); //NOI18N
             entryField = integerField;
         }
 
+        HBox.setHgrow(root, Priority.ALWAYS);
         initialize();
     }
 
@@ -166,7 +169,7 @@
 
         if (value == null) {
             // Should be set to null, but need a global work on the "null handling"
-            entryField.setText("");
+            entryField.setText(""); //NOI18N
         } else {
             assert value instanceof String;
             entryField.setText((String) value); //NOI18N
@@ -179,7 +182,7 @@
     }
 
     @Override
-    protected void requestFocus() {
+    public void requestFocus() {
         EditorUtils.doNextFrame(new Runnable() {
 
             @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BooleanEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BooleanEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -100,7 +100,13 @@
     }
 
     @Override
-    protected void requestFocus() {
-        checkBox.requestFocus();
+    public void requestFocus() {
+        EditorUtils.doNextFrame(new Runnable() {
+
+            @Override
+            public void run() {
+                checkBox.requestFocus();
+            }
+        });
     }
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BoundedDoubleEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/BoundedDoubleEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -205,7 +205,7 @@
     }
 
     @Override
-    protected void requestFocus() {
+    public void requestFocus() {
         EditorUtils.doNextFrame(new Runnable() {
 
             @Override
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/ControllerClassEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/ControllerClassEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -37,17 +37,18 @@
 
 /**
  * Controller class editor.
- * 
- * 
+ *
+ *
  */
 public class ControllerClassEditor extends AutoSuggestEditor {
+
     private static final String PROPERTY_NAME = "Controller class";
     private static final String DEFAULT_VALUE = "";
-    
+
     @SuppressWarnings("LeakingThisInConstructor")
     public ControllerClassEditor(List<String> suggestedClasses) {
         super(PROPERTY_NAME, DEFAULT_VALUE, suggestedClasses); //NOI18N
-                
+
         // text field events handling
         EventHandler<ActionEvent> onActionListener = new EventHandler<ActionEvent>() {
             @Override
@@ -59,13 +60,19 @@
         };
         setTextEditorBehavior(this, textField, onActionListener);
     }
-    
+
     public void reset(List<String> suggestedClasses) {
         super.reset(PROPERTY_NAME, DEFAULT_VALUE, suggestedClasses);
     }
 
     @Override
-    protected void requestFocus() {
-        textField.requestFocus();
+    public void requestFocus() {
+        EditorUtils.doNextFrame(new Runnable() {
+
+            @Override
+            public void run() {
+                textField.requestFocus();
+            }
+        });
     }
 }
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/CursorEditor.java	Mon Dec 09 21:17:32 2013 -0800
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/CursorEditor.java	Tue Dec 10 08:36:28 2013 +0100
@@ -35,6 +35,7 @@
 import static com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.editors.PropertyEditor.handleIndeterminate;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.CursorPropertyMetadata;
+import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
 import java.io.File;
 import java.net.MalformedURLException;
 import java.util.Arrays;
@@ -59,7 +60,7 @@
 /**
  * Insets editor (for top/right/bottom/left fields).
  *
- * 
+ *
  */
 public class CursorEditor extends PropertyEditor {
 
@@ -83,10 +84,16 @@
     public CursorEditor(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses) {
         super(propMeta, selectedClasses);
         root = EditorUtils.loadFxml("CursorEditor.fxml", this); //NOI18N
-        
+
         EventHandler<ActionEvent> valueListener = new EventHandler<ActionEvent>() {
             @Override
             public void handle(ActionEvent event) {
+                try {
+                    cursor = new ImageCursor(new Image(imagePathTf.getText()));
+                } catch (NullPointerException  | IllegalArgumentException ex) {
+                    handleInvalidValue(imagePathTf.getText());
+                    return;
+                }
                 userUpdateValueProperty(getValue());
             }
         };
@@ -139,7 +146,6 @@
     }
 
     @Override
-    @SuppressWarnings("deprecation")
     public void setValue(Object value) {
         setValueGeneric(value);
         if (isSetValueDone()) {
@@ -156,7 +162,7 @@
                 // Custom cursor
                 ImageCursor imageCursor = (ImageCursor) value;
                 imagePathTfEnabled(true);
-                imagePathTf.setText(imageCursor.getImage().impl_getUrl());
+                imagePathTf.setText(Deprecation.getUrl(imageCursor.getImage()));
                 selectCursor(""); //NOI18N
                 cursorMb.setText(""); //NOI18N
             } else {
@@ -170,9 +176,8 @@
     @Override
     public void reset(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses) {
         super.reset(propMeta, selectedClasses);
-        setLayoutFormat(PropertyEditor.LayoutFormat.SIMPLE_LINE_BOTTOM);
         imagePathTf.setPromptText(null);
-   }
+    }
 
     @Override
     protected void valueIsIndeterminate() {
@@ -188,13 +193,12 @@
         selectCursor(inheritedParentText);
         userUpdateValueProperty(getValue());
     }
-    
+
     @FXML
     void chooseImage(ActionEvent event) {
         imagePathTfEnabled(true);
 
         String[] extensions = {"*.jpg", "*.jpeg", "*.png", "*.gif"}; //NOI18N
-        // !! Do we need a wrapper, as we had in SB 1.1, to allow tests to bypass the dialog ?
         FileChooser fileChooser = new FileChooser();
         fileChooser.setTitle(I18N.getString("inspector.select.image"));
         fileChooser.getExtensionFilters().add(
@@ -237,9 +241,9 @@
                 // set the menu button text
                 if (cursorStr.equals(inheritedParentText)) {
                     // change the menu button text to be shorter in this case...
-                    cursorMb.setText(inheritedText);                    
+                    cursorMb.setText(inheritedText);
                 } else {
-                    cursorMb.setText(cursorStr);                    
+                    cursorMb.setText(cursorStr);
                 }
                 cursor = checkMenuItem.getGraphic().getCursor();
             } else {
@@ -249,11 +253,17 @@
     }
 
     @Override
-    protected void requestFocus() {
-        if (imagePathTf.isVisible()) {
-         imagePathTf.requestFocus();
-        } else {
-            cursorMb.requestFocus();
-        }
+    public void requestFocus() {
+        EditorUtils.doNextFrame(new Runnable() {
+
+            @Override
+            public void run() {
+                if (imagePathTf.isVisible()) {
+                    imagePathTf.requestFocus();
+                } else {
+                    cursorMb.requestFocus();
+                }
+            }
+        });