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.editor.selection; 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.value.IntegerPropertyMetadata; 40 import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignHierarchyMask; 41 import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath; 42 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName; 43 import java.util.ArrayList; 44 import java.util.Collections; 45 import java.util.HashSet; 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.Set; 49 import javafx.scene.layout.ColumnConstraints; 50 import javafx.scene.layout.GridPane; 51 import javafx.scene.layout.RowConstraints; 52 53 /** 54 * 55 * 56 */ 57 public class GridSelectionGroup extends AbstractSelectionGroup { 58 59 public enum Type { ROW, COLUMN }; 60 61 private final FXOMObject parentObject; 62 private final Type type; 63 private final Set<Integer> indexes = new HashSet<>(); 64 65 public GridSelectionGroup(FXOMObject parentObject, Type type, int index) { 66 assert parentObject != null; 67 assert parentObject.getSceneGraphObject() instanceof GridPane; 68 assert index >= 0; 69 70 this.parentObject = parentObject; 71 this.type = type; 72 this.indexes.add(index); 73 } 74 75 public GridSelectionGroup(FXOMObject parentObject, Type type, Set<Integer> indexes) { 76 assert parentObject != null; 77 assert parentObject.getSceneGraphObject() instanceof GridPane; 78 assert indexes != null; 79 assert indexes.isEmpty() == false; 80 81 this.parentObject = parentObject; 82 this.type = type; 83 this.indexes.addAll(indexes); 84 } 85 86 public FXOMObject getParentObject() { 87 return parentObject; 88 } 89 90 public Type getType() { 91 return type; 92 } 93 94 public Set<Integer> getIndexes() { 95 return Collections.unmodifiableSet(indexes); 96 } 97 98 public List<FXOMInstance> collectConstraintInstances() { 99 final List<FXOMInstance> result; 100 101 switch(type) { 102 case ROW: 103 result = collectRowConstraintsInstances(); 104 break; 105 case COLUMN: 106 result = collectColumnConstraintsInstances(); 107 break; 108 default: 109 throw new RuntimeException("Bug"); 110 } 111 112 return result; 113 } 114 115 public List<FXOMObject> collectSelectedObjects() { 116 final List<FXOMObject> result; 117 118 switch(type) { 119 case ROW: 120 result = collectSelectedObjectsInRow(); 121 break; 122 case COLUMN: 123 result = collectSelectedObjectsInColumn(); 124 break; 125 default: 126 throw new RuntimeException("Bug"); 127 } 128 129 return result; 130 } 131 132 /* 133 * AbstractSelectionGroup 134 */ 135 136 @Override 137 public FXOMObject getAncestor() { 138 return parentObject; 139 } 140 141 @Override 142 public boolean isValid(FXOMDocument fxomDocument) { 143 assert fxomDocument != null; 144 145 final boolean result; 146 final FXOMObject fxomRoot = fxomDocument.getFxomRoot(); 147 if (fxomRoot == null) { 148 result = false; 149 } else { 150 result = (parentObject == fxomRoot) || parentObject.isDescendantOf(fxomRoot); 151 } 152 153 return result; 154 } 155 156 157 /* 158 * Cloneable 159 */ 160 @Override 161 public GridSelectionGroup clone() throws CloneNotSupportedException { 162 return (GridSelectionGroup)super.clone(); 163 } 164 165 166 /* 167 * Object 168 */ 169 @Override 170 public int hashCode() { 171 int hash = 7; 172 hash = 47 * hash + Objects.hashCode(this.parentObject); 173 hash = 47 * hash + Objects.hashCode(this.type); 174 hash = 47 * hash + Objects.hashCode(this.indexes); 175 return hash; 176 } 177 178 @Override 179 public boolean equals(Object obj) { 180 if (obj == null) { 181 return false; 182 } 183 if (getClass() != obj.getClass()) { 184 return false; 185 } 186 final GridSelectionGroup other = (GridSelectionGroup) obj; 187 if (!Objects.equals(this.parentObject, other.parentObject)) { 188 return false; 189 } 190 if (this.type != other.type) { 191 return false; 192 } 193 if (!Objects.equals(this.indexes, other.indexes)) { 194 return false; 195 } 196 return true; 197 } 198 199 200 /* 201 * Private 202 */ 203 204 static private final PropertyName rowConstraintsName 205 = new PropertyName("rowConstraints"); 206 207 private List<FXOMInstance> collectRowConstraintsInstances() { 208 final List<FXOMInstance> result = new ArrayList<>(); 209 210 final FXOMInstance gridPaneInstance 211 = (FXOMInstance) parentObject; 212 final FXOMProperty fxomProperty 213 = gridPaneInstance.getProperties().get(rowConstraintsName); 214 if (fxomProperty != null) { 215 assert fxomProperty instanceof FXOMPropertyC; 216 final FXOMPropertyC fxomPropertyC = (FXOMPropertyC) fxomProperty; 217 int index = 0; 218 for (FXOMObject v : fxomPropertyC.getValues()) { 219 assert v.getSceneGraphObject() instanceof RowConstraints; 220 assert v instanceof FXOMInstance; 221 if (indexes.contains(index++)) { 222 result.add((FXOMInstance)v); 223 } 224 } 225 } 226 227 return result; 228 } 229 230 static private final PropertyName columnConstraintsName 231 = new PropertyName("columnConstraints"); 232 233 private List<FXOMInstance> collectColumnConstraintsInstances() { 234 final List<FXOMInstance> result = new ArrayList<>(); 235 236 final FXOMInstance gridPaneInstance 237 = (FXOMInstance) parentObject; 238 final FXOMProperty fxomProperty 239 = gridPaneInstance.getProperties().get(columnConstraintsName); 240 if (fxomProperty != null) { 241 assert fxomProperty instanceof FXOMPropertyC; 242 final FXOMPropertyC fxomPropertyC = (FXOMPropertyC) fxomProperty; 243 int index = 0; 244 for (FXOMObject v : fxomPropertyC.getValues()) { 245 assert v.getSceneGraphObject() instanceof ColumnConstraints; 246 assert v instanceof FXOMInstance; 247 if (indexes.contains(index++)) { 248 result.add((FXOMInstance)v); 249 } 250 } 251 } 252 253 return result; 254 } 255 256 257 private static final IntegerPropertyMetadata columnIndexMeta = 258 new IntegerPropertyMetadata( 259 new PropertyName("columnIndex", GridPane.class), //NOI18N 260 true, /* readWrite */ 261 0, /* defaultValue */ 262 InspectorPath.UNUSED); 263 264 private List<FXOMObject> collectSelectedObjectsInColumn() { 265 final List<FXOMObject> result = new ArrayList<>(); 266 267 final DesignHierarchyMask m = new DesignHierarchyMask(parentObject); 268 assert m.isAcceptingSubComponent(); 269 270 for (int i = 0, count = m.getSubComponentCount(); i < count; i++) { 271 final FXOMObject childObject = m.getSubComponentAtIndex(i); 272 if (childObject instanceof FXOMInstance) { 273 final FXOMInstance childInstance = (FXOMInstance) childObject; 274 if (indexes.contains(columnIndexMeta.getValue(childInstance))) { 275 // child belongs to a selected column 276 result.add(childInstance); 277 } 278 } 279 } 280 281 return result; 282 } 283 284 private static final IntegerPropertyMetadata rowIndexMeta = 285 new IntegerPropertyMetadata( 286 new PropertyName("rowIndex", GridPane.class), //NOI18N 287 true, /* readWrite */ 288 0, /* defaultValue */ 289 InspectorPath.UNUSED); 290 291 private List<FXOMObject> collectSelectedObjectsInRow() { 292 final List<FXOMObject> result = new ArrayList<>(); 293 294 final DesignHierarchyMask m = new DesignHierarchyMask(parentObject); 295 assert m.isAcceptingSubComponent(); 296 297 for (int i = 0, count = m.getSubComponentCount(); i < count; i++) { 298 final FXOMObject childObject = m.getSubComponentAtIndex(i); 299 if (childObject instanceof FXOMInstance) { 300 final FXOMInstance childInstance = (FXOMInstance) childObject; 301 if (indexes.contains(rowIndexMeta.getValue(childInstance))) { 302 // child belongs to a selected column 303 result.add(childInstance); 304 } 305 } 306 } 307 308 return result; 309 } 310 311 }