1 /* 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.oracle.javafx.scenebuilder.kit.metadata.property.value; 33 34 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument; 35 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance; 36 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject; 37 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMProperty; 38 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMPropertyC; 39 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata; 40 import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath; 41 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName; 42 import java.util.Objects; 43 import javafx.util.Callback; 44 45 /** 46 * 47 */ 48 49 public abstract class CallbackPropertyMetadata extends ValuePropertyMetadata { 50 51 private final Object defaultValue; 52 53 public CallbackPropertyMetadata(PropertyName name, boolean readWrite, Object defaultValue, InspectorPath inspectorPath) { 54 super(name, readWrite, inspectorPath); 55 this.defaultValue = defaultValue; 56 } 57 58 public Object getDefaultValue() { 59 return defaultValue; 60 } 61 62 public Object getValue(FXOMInstance fxomInstance) { 63 final Object result; 64 65 if (isReadWrite()) { 66 final FXOMProperty fxomProperty = fxomInstance.getProperties().get(getName()); 67 if (fxomProperty instanceof FXOMPropertyC) { 68 69 final FXOMPropertyC fxomPropertyC = (FXOMPropertyC) fxomProperty; 70 assert fxomPropertyC.getValues().size() == 1; 71 72 final FXOMObject valueFxomObject = fxomPropertyC.getValues().get(0); 73 final Object sceneGraphObject = valueFxomObject.getSceneGraphObject(); 74 75 result = castValue(sceneGraphObject); 76 } else { 77 assert fxomProperty == null; 78 79 // propertyName is not specified in the fxom instance. 80 // We return the default value specified in the metadata of the 81 // property 82 result = defaultValue; 83 } 84 } else { 85 result = castValue(getName().getValue(fxomInstance.getSceneGraphObject())); 86 } 87 88 return result; 89 } 90 91 public void setValue(FXOMInstance fxomInstance, Object value) { 92 assert isReadWrite(); 93 94 final FXOMProperty fxomProperty = fxomInstance.getProperties().get(getName()); 95 96 if (Objects.equals(value, getDefaultValueObject())) { 97 // We must remove the fxom property if any 98 if (fxomProperty != null) { 99 fxomProperty.removeFromParentInstance(); 100 } 101 } else { 102 if (fxomProperty == null) { 103 // propertyName is not specified in the fxom instance. 104 // We insert a new fxom property 105 final FXOMProperty newProperty 106 = makeFxomPropertyFromValue(fxomInstance, value); 107 newProperty.addToParentInstance(-1, fxomInstance); 108 } else { 109 updateFxomPropertyWithValue(fxomProperty, value); 110 } 111 } 112 } 113 114 115 protected abstract void updateFxomInstanceWithValue(FXOMInstance valueInstance, Object value); 116 protected abstract Class<?> getFxConstantClass(); 117 protected abstract Object castValue(Object value); 118 119 120 121 122 /* 123 * ValuePropertyMetadata 124 */ 125 126 @Override 127 public Class<?> getValueClass() { 128 return Callback.class; 129 } 130 131 @Override 132 public Object getDefaultValueObject() { 133 return defaultValue; 134 } 135 136 @Override 137 public Object getValueObject(FXOMInstance fxomInstance) { 138 return getValue(fxomInstance); 139 } 140 141 @Override 142 public void setValueObject(FXOMInstance fxomInstance, Object valueObject) { 143 setValue(fxomInstance, castValue(valueObject)); 144 } 145 146 147 /* 148 * Private 149 */ 150 151 protected FXOMProperty makeFxomPropertyFromValue(FXOMInstance fxomInstance, Object value) { 152 assert fxomInstance != null; 153 assert value != null; 154 155 final FXOMDocument fxomDocument = fxomInstance.getFxomDocument(); 156 final FXOMInstance valueInstance = new FXOMInstance(fxomDocument, getFxConstantClass()); 157 updateFxomInstanceWithValue(valueInstance, value); 158 return new FXOMPropertyC(fxomDocument, getName(), valueInstance); 159 } 160 161 protected void updateFxomPropertyWithValue(FXOMProperty fxomProperty, Object value) { 162 assert value != null; 163 assert fxomProperty instanceof FXOMPropertyC; // Because Callback are expressed using fx:constant 164 165 final FXOMPropertyC fxomPropertyC = (FXOMPropertyC) fxomProperty; 166 assert fxomPropertyC.getValues().size() == 1; 167 168 FXOMObject valueObject = fxomPropertyC.getValues().get(0); 169 if (valueObject instanceof FXOMInstance) { 170 updateFxomInstanceWithValue((FXOMInstance) valueObject, value); 171 } else { 172 final FXOMDocument fxomDocument = fxomProperty.getFxomDocument(); 173 final FXOMInstance valueInstance = new FXOMInstance(fxomDocument, getFxConstantClass()); 174 updateFxomInstanceWithValue(valueInstance, value); 175 valueInstance.addToParentProperty(0, fxomPropertyC); 176 valueObject.removeFromParentProperty(); 177 } 178 } 179 180 }