changeset 7934:5ee50928c1d6

[SCENEBUILDER] Added CombineReferenceJob and ExpandReferenceJob classes (to be used for DTL-6774).
author eric.le.ponner@oracle.com
date Mon, 01 Sep 2014 16:24:02 +0200
parents 481f8d61b1cd
children b0a0f059cc4e
files apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/atomic/ReplaceObjectJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/atomic/ReplacePropertyValueJobT.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/CombineExpressionReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/CombineIntrinsicReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/CombineReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandExpressionReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandIntrinsicReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandReferenceJob.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMCloner.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMNodes.java
diffstat 10 files changed, 938 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/atomic/ReplaceObjectJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, 2014, 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.atomic;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMCollection;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyC;
+
+/**
+ *
+ */
+public class ReplaceObjectJob extends Job {
+    
+    private final FXOMObject original;
+    private final FXOMObject replacement;
+    private FXOMPropertyC parentProperty;
+    private FXOMCollection parentCollection;
+    private int indexInParentProperty;
+    private int indexInParentCollection;
+
+    public ReplaceObjectJob(FXOMObject original, FXOMObject replacement, EditorController editorController) {
+        super(editorController);
+        this.original = original;
+        this.replacement = replacement;
+    }
+    
+    /*
+     * Job
+     */
+    @Override
+    public boolean isExecutable() {
+        return ((original.getParentCollection() != null) || 
+                (original.getParentProperty() != null))
+              &&
+               ((replacement.getParentCollection() == null) &&
+                (replacement.getParentProperty() == null));
+    }
+
+    @Override
+    public void execute() {
+        parentProperty = original.getParentProperty();
+        parentCollection = original.getParentCollection();
+        indexInParentProperty = original.getIndexInParentProperty();
+        indexInParentCollection = original.getIndexInParentCollection();
+        
+        // Now same as redo()
+        redo();
+    }
+
+    @Override
+    public void undo() {
+        assert original.getParentProperty() == null;
+        assert original.getParentCollection() == null;
+        assert replacement.getParentProperty() == parentProperty;
+        assert replacement.getParentCollection() == parentCollection;
+        assert replacement.getIndexInParentProperty() == indexInParentProperty;
+        assert replacement.getIndexInParentCollection() == indexInParentCollection;
+        
+        if (parentProperty != null) {
+            original.addToParentProperty(indexInParentProperty, parentProperty);
+            replacement.removeFromParentProperty();
+        } else {
+            assert parentCollection != null;
+            original.addToParentCollection(indexInParentCollection, parentCollection);
+            replacement.removeFromParentCollection();
+        }
+    }
+
+    @Override
+    public void redo() {
+        assert original.getParentProperty() == parentProperty;
+        assert original.getParentCollection() == parentCollection;
+        assert original.getIndexInParentProperty() == indexInParentProperty;
+        assert original.getIndexInParentCollection() == indexInParentCollection;
+        assert replacement.getParentProperty() == null;
+        assert replacement.getParentCollection() == null;
+        
+        if (parentProperty != null) {
+            replacement.addToParentProperty(indexInParentProperty, parentProperty);
+            original.removeFromParentProperty();
+        } else {
+            assert parentCollection != null;
+            replacement.addToParentCollection(indexInParentCollection, parentCollection);
+            original.removeFromParentCollection();
+        }
+    }
+
+    @Override
+    public String getDescription() {
+        return getClass().getSimpleName(); // Not intended for user
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/atomic/ReplacePropertyValueJobT.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2012, 2014, 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.atomic;
+
+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.fxom.FXOMPropertyC;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyT;
+
+/**
+ *
+ */
+public class ReplacePropertyValueJobT extends Job {
+    
+    private final FXOMPropertyT hostProperty;
+    private final FXOMObject newValue;
+    
+    private FXOMInstance hostInstance;
+    private FXOMPropertyC newProperty;
+
+    public ReplacePropertyValueJobT(FXOMPropertyT hostProperty, FXOMObject newValue, EditorController editorController) {
+        super(editorController);
+        
+        assert hostProperty != null;
+        assert newValue != null;
+        
+        this.hostProperty = hostProperty;
+        this.newValue = newValue;
+    }
+
+    
+    /*
+     * Job
+     */
+    @Override
+    public boolean isExecutable() {
+        return (hostProperty.getParentInstance() != null);
+    }
+
+    @Override
+    public void execute() {
+        hostInstance = hostProperty.getParentInstance();
+        newProperty = new FXOMPropertyC(hostProperty.getFxomDocument(), hostProperty.getName());
+        
+        // Now same as redo()
+        redo();
+    }
+
+    @Override
+    public void undo() {
+        assert hostProperty.getParentInstance() == null;
+        assert newProperty.getParentInstance() == hostInstance;
+        
+        newProperty.removeFromParentInstance();
+        newValue.removeFromParentProperty();
+        hostProperty.addToParentInstance(-1, hostInstance);
+    }
+
+    @Override
+    public void redo() {
+        assert hostProperty.getParentInstance() == hostInstance;
+        assert newProperty.getParentInstance() == null;
+        
+        hostProperty.removeFromParentInstance();
+        newValue.addToParentProperty(-1, newProperty);
+        newProperty.addToParentInstance(-1, hostInstance);
+    }
+
+    @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/reference/CombineExpressionReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.InlineDocumentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.RemoveObjectJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.ReplacePropertyValueJobT;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNodes;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyT;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PrefixedValue;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class CombineExpressionReferenceJob extends InlineDocumentJob {
+    
+    private final FXOMPropertyT reference;
+
+    public CombineExpressionReferenceJob(
+            FXOMPropertyT reference, 
+            EditorController editorController) {
+        super(editorController);
+        
+        assert reference != null;
+        assert reference.getFxomDocument() == editorController.getFxomDocument();
+        
+        this.reference = reference;
+    }
+    
+    /*
+     * InlineDocumentJob
+     */
+    @Override
+    protected List<Job> makeAndExecuteSubJobs() {
+        final List<Job> result = new LinkedList<>();
+        
+        // 1) Locate the referee
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        final String fxId = FXOMNodes.extractReferenceSource(reference);
+        final FXOMObject referee = fxomDocument.searchWithFxId(fxId);
+        
+        // 2) Remove the referee
+        final Job removeJob = new RemoveObjectJob(referee, getEditorController());
+        removeJob.execute();
+        result.add(removeJob);
+        
+        // 3) Replace ther reference by the referee
+        final Job replaceJob = new ReplacePropertyValueJobT(reference, referee, getEditorController());
+        replaceJob.execute();
+        result.add(replaceJob);
+                
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName(); // Not expected to reach the user
+    }
+
+    @Override
+    public boolean isExecutable() {
+        final PrefixedValue pv = new PrefixedValue(reference.getValue());
+        return pv.isExpression();
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/CombineIntrinsicReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.InlineDocumentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.RemoveObjectJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.ReplaceObjectJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMIntrinsic;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNodes;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class CombineIntrinsicReferenceJob extends InlineDocumentJob {
+    
+    private final FXOMIntrinsic reference;
+
+    public CombineIntrinsicReferenceJob(
+            FXOMIntrinsic reference, 
+            EditorController editorController) {
+        super(editorController);
+        
+        assert reference != null;
+        assert reference.getFxomDocument() == editorController.getFxomDocument();
+        
+        this.reference = reference;
+    }
+    
+    /*
+     * InlineDocumentJob
+     */
+    @Override
+    protected List<Job> makeAndExecuteSubJobs() {
+        final List<Job> result = new LinkedList<>();
+        
+        // 1) Locate the referee
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        final String fxId = FXOMNodes.extractReferenceSource(reference);
+        final FXOMObject referee = fxomDocument.searchWithFxId(fxId);
+        
+        // 2) Remove the referee
+        final Job removeJob = new RemoveObjectJob(referee, getEditorController());
+        removeJob.execute();
+        result.add(removeJob);
+        
+        // 3) Replace ther reference by the referee
+        final Job replaceJob = new ReplaceObjectJob(reference, referee, getEditorController());
+        replaceJob.execute();
+        result.add(replaceJob);
+                
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName(); // Not expected to reach the user
+    }
+
+    @Override
+    public boolean isExecutable() {
+        return ((reference.getType() == FXOMIntrinsic.Type.FX_COPY) ||
+                (reference.getType() == FXOMIntrinsic.Type.FX_REFERENCE)) &&
+               ((reference.getParentProperty() != null) ||
+                (reference.getParentCollection() != null));
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/CombineReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMIntrinsic;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNode;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyT;
+
+/**
+ *
+ */
+public class CombineReferenceJob  extends Job {
+    
+    private final Job subJob;
+    
+    public CombineReferenceJob(FXOMNode reference, EditorController editorController) {
+        super(editorController);
+        if (reference instanceof FXOMIntrinsic) {
+            final FXOMIntrinsic fxomIntrinsic = (FXOMIntrinsic) reference;
+            subJob = new CombineIntrinsicReferenceJob(fxomIntrinsic, getEditorController());
+        } else if (reference instanceof FXOMPropertyT) {
+            final FXOMPropertyT fxomProperty = (FXOMPropertyT) reference;
+            subJob = new CombineExpressionReferenceJob(fxomProperty, getEditorController());
+        } else {
+            throw new RuntimeException("Bug"); //NOI18N
+        }
+    }
+    
+    /*
+     * Job
+     */
+    @Override
+    public boolean isExecutable() {
+        return subJob.isExecutable();
+    }
+
+    @Override
+    public void execute() {
+        subJob.execute();
+    }
+
+    @Override
+    public void undo() {
+        subJob.undo();
+    }
+
+    @Override
+    public void redo() {
+        subJob.redo();
+    }
+
+    @Override
+    public String getDescription() {
+        return subJob.getDescription();
+    }
+
+
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandExpressionReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.InlineDocumentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.AddPropertyJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.RemovePropertyJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMCloner;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNodes;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyC;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyT;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PrefixedValue;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class ExpandExpressionReferenceJob extends InlineDocumentJob {
+    
+    private final FXOMPropertyT reference;
+    private final FXOMCloner cloner;
+
+    public ExpandExpressionReferenceJob(
+            FXOMPropertyT reference, 
+            FXOMCloner cloner,
+            EditorController editorController) {
+        super(editorController);
+        
+        assert reference != null;
+        assert reference.getFxomDocument() == editorController.getFxomDocument();
+        assert (cloner == null) || (cloner.getTargetDocument() == editorController.getFxomDocument());
+        
+        this.reference = reference;
+        this.cloner = cloner;
+    }
+    
+    /*
+     * InlineDocumentJob
+     */
+    @Override
+    protected List<Job> makeAndExecuteSubJobs() {
+        final List<Job> result = new LinkedList<>();
+        
+        // 1) remove the reference
+        final FXOMInstance parentInstance = reference.getParentInstance();
+        final Job removeReference = new RemovePropertyJob(reference, getEditorController());
+        removeReference.execute();
+        result.add(removeReference);
+        
+        // 2.1) clone the referee 
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        final String fxId = FXOMNodes.extractReferenceSource(reference);
+        final FXOMObject referee = fxomDocument.searchWithFxId(fxId);
+        final FXOMObject refereeClone = cloner.clone(referee);
+        
+        // 3) insert the clone in place of the reference
+        final FXOMPropertyC cloneProperty 
+                = new FXOMPropertyC(fxomDocument, reference.getName(), refereeClone);
+        final Job addCloneJob 
+                = new AddPropertyJob(cloneProperty, parentInstance, -1, getEditorController());
+        addCloneJob.execute();
+        result.add(addCloneJob);
+                
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName(); // Not expected to reach the user
+    }
+
+    @Override
+    public boolean isExecutable() {
+        final PrefixedValue pv = new PrefixedValue(reference.getValue());
+        return pv.isExpression();
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandIntrinsicReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.InlineDocumentJob;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.ReplaceObjectJob;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMCloner;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMIntrinsic;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNodes;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class ExpandIntrinsicReferenceJob extends InlineDocumentJob {
+    
+    private final FXOMIntrinsic reference;
+    private final FXOMCloner cloner;
+
+    public ExpandIntrinsicReferenceJob(
+            FXOMIntrinsic reference, 
+            FXOMCloner cloner,
+            EditorController editorController) {
+        super(editorController);
+        
+        assert reference != null;
+        assert cloner != null;
+        assert reference.getFxomDocument() == editorController.getFxomDocument();
+        assert cloner.getTargetDocument() == editorController.getFxomDocument();
+        
+        this.reference = reference;
+        this.cloner = cloner;
+    }
+    
+    /*
+     * InlineDocumentJob
+     */
+    @Override
+    protected List<Job> makeAndExecuteSubJobs() {
+        final List<Job> result = new LinkedList<>();
+        
+        // 1) clone the referee
+        final FXOMDocument fxomDocument = getEditorController().getFxomDocument();
+        final String fxId = FXOMNodes.extractReferenceSource(reference);
+        final FXOMObject referee = fxomDocument.searchWithFxId(fxId);
+        final FXOMObject refereeClone = cloner.clone(referee);
+        
+        // 2) replace the reference by the referee clone
+        final Job replaceJob = new ReplaceObjectJob(reference, refereeClone, getEditorController());
+        replaceJob.execute();
+        result.add(replaceJob);
+        
+        return result;
+    }
+
+    @Override
+    protected String makeDescription() {
+        return getClass().getSimpleName(); // Not expected to reach the user
+    }
+
+    @Override
+    public boolean isExecutable() {
+        return ((reference.getType() == FXOMIntrinsic.Type.FX_COPY) ||
+                (reference.getType() == FXOMIntrinsic.Type.FX_REFERENCE)) &&
+               ((reference.getParentProperty() != null) ||
+                (reference.getParentCollection() != null));
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/job/reference/ExpandReferenceJob.java	Mon Sep 01 16:24:02 2014 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, 2014, 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.reference;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMCloner;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMIntrinsic;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMNode;
+import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyT;
+
+/**
+ *
+ */
+public class ExpandReferenceJob  extends Job {
+    
+    private final Job subJob;
+    
+    public ExpandReferenceJob(FXOMNode reference, FXOMCloner cloner, EditorController editorController) {
+        super(editorController);
+        if (reference instanceof FXOMIntrinsic) {
+            final FXOMIntrinsic fxomIntrinsic = (FXOMIntrinsic) reference;
+            subJob = new ExpandIntrinsicReferenceJob(fxomIntrinsic, cloner, getEditorController());
+        } else if (reference instanceof FXOMPropertyT) {
+            final FXOMPropertyT fxomProperty = (FXOMPropertyT) reference;
+            subJob = new ExpandExpressionReferenceJob(fxomProperty, cloner, getEditorController());
+        } else {
+            throw new RuntimeException("Bug"); //NOI18N
+        }
+    }
+    
+    /*
+     * Job
+     */
+    @Override
+    public boolean isExecutable() {
+        return subJob.isExecutable();
+    }
+
+    @Override
+    public void execute() {
+        subJob.execute();
+    }
+
+    @Override
+    public void undo() {
+        subJob.undo();
+    }
+
+    @Override
+    public void redo() {
+        subJob.redo();
+    }
+
+    @Override
+    public String getDescription() {
+        return subJob.getDescription();
+    }
+
+
+    
+}
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMCloner.java	Mon Sep 01 15:23:49 2014 +0200
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMCloner.java	Mon Sep 01 16:24:02 2014 +0200
@@ -54,6 +54,10 @@
         this.fxIdCollector = new FxIdCollector(targetDocument);
     }
     
+    public FXOMDocument getTargetDocument() {
+        return targetDocument;
+    }
+    
     public FXOMObject clone(FXOMObject clonee) {
         return clone(clonee, false /* preserveCloneFxId */);
     }
@@ -264,7 +268,7 @@
                     source.getValue());
         } else {
             assert sourceObject != null;
-            if (getNoClonePropertyNames().contains(source.getName())) {
+            if (FXOMNodes.isWeakReference(source)) {
                 result = null;
             } else {
                 result = new FXOMPropertyC(
@@ -280,21 +284,7 @@
     private boolean isInsideClonee(FXOMObject object) {
         assert object != null;
         return (object == clonee) || object.isDescendantOf(clonee);
-    }
-    
-    private static Set<PropertyName> noClonePropertyNames;
-    
-    private static synchronized Set<PropertyName> getNoClonePropertyNames() {
-        if (noClonePropertyNames == null) {
-            noClonePropertyNames = new HashSet<>();
-            noClonePropertyNames.add(new PropertyName("labelFor")); //NOI18N
-            noClonePropertyNames.add(new PropertyName("expandedPane")); //NOI18N
-        }
-        
-        return noClonePropertyNames;
-    }
-    
-    
+    }    
     
     private void renameFxIds(FXOMObject clone, boolean preserveCloneeFxId) {
         
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMNodes.java	Mon Sep 01 15:23:49 2014 +0200
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/fxom/FXOMNodes.java	Mon Sep 01 16:24:02 2014 +0200
@@ -41,6 +41,7 @@
 import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignImage;
 import com.oracle.javafx.scenebuilder.kit.metadata.util.PrefixedValue;
 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
+import com.oracle.javafx.scenebuilder.kit.util.JavaLanguage;
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
@@ -552,6 +553,93 @@
     }
     
     
+    public static String extractReferenceSource(FXOMNode node) {
+        final String result;
+        
+        if (node instanceof FXOMIntrinsic) {
+            final FXOMIntrinsic intrinsic = (FXOMIntrinsic) node;
+            switch(intrinsic.getType()) {
+                case FX_REFERENCE:
+                case FX_COPY:
+                    result = intrinsic.getSource();
+                    break;
+                default:
+                    result = null;
+            }
+        } else if (node instanceof FXOMPropertyT) {
+            final FXOMPropertyT property = (FXOMPropertyT) node;
+            final PrefixedValue pv = new PrefixedValue(property.getValue());
+            if (pv.isExpression() && JavaLanguage.isIdentifier(pv.getSuffix())) {
+                result = pv.getSuffix();
+            } else {
+                result = null;
+            }
+        } else {
+            result = null;
+        }
+        
+        return result;
+    }
+    
+    
+    public static boolean isWeakReference(FXOMNode node) {
+        final boolean result;
+        
+        if (node instanceof FXOMIntrinsic) {
+            final FXOMIntrinsic intrinsic = (FXOMIntrinsic) node;
+            switch(intrinsic.getType()) {
+                case FX_REFERENCE:
+                case FX_COPY:
+                    if (intrinsic.getParentProperty() != null) {
+                        final PropertyName propertyName = intrinsic.getParentProperty().getName();
+                        if (propertyName.getResidenceClass() == null) {
+                            result = getWeakPropertyNames().contains(propertyName.getName());
+                        } else {
+                            result = false;
+                        }
+                    } else {
+                        result = false;
+                    }
+                    break;
+                default:
+                    result = false;
+            }
+        } else if (node instanceof FXOMPropertyT) {
+            final FXOMPropertyT property = (FXOMPropertyT) node;
+            final PrefixedValue pv = new PrefixedValue(property.getValue());
+            if (pv.isExpression() && JavaLanguage.isIdentifier(pv.getSuffix())) {
+                final PropertyName propertyName = property.getName();
+                if (propertyName.getResidenceClass() == null) {
+                    result = getWeakPropertyNames().contains(propertyName.getName());
+                } else {
+                    result = false;
+                }
+            } else {
+                result = false;
+            }
+        } else {
+            result = false;
+        }
+        
+        return result;
+    }
+    
+    
+    private static Set<String> weakPropertyNames;
+    
+    public static synchronized Set<String> getWeakPropertyNames() {
+        
+        if (weakPropertyNames == null) {
+            weakPropertyNames = new HashSet<>();
+            weakPropertyNames.add("labelFor");
+            weakPropertyNames.add("expandedPane");
+            weakPropertyNames.add("clip");
+        }
+        
+        return weakPropertyNames;
+    }
+    
+    
     /*
      * Private
      */