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.panel.inspector.editors; 33 34 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.List; 38 import java.util.Set; 39 import javafx.event.EventHandler; 40 import javafx.scene.Node; 41 import javafx.scene.layout.VBox; 42 43 /** 44 * Generic class for property editors based on a list of inline items. 45 * 46 * 47 */ 48 public abstract class InlineListEditor extends PropertyEditor implements EditorItemDelegate { 49 private final VBox vbox = new VBox(1); 50 private final List<EditorItem> editorItems = new ArrayList<>(); 51 52 public InlineListEditor(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses) { 53 super(propMeta, selectedClasses); 54 setLayoutFormat(PropertyEditor.LayoutFormat.DOUBLE_LINE); 55 } 56 57 @Override 58 public Node getValueEditor() { 59 return super.handleGenericModes(vbox); 60 } 61 62 @Override 63 public void reset(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses) { 64 reset(propMeta, selectedClasses, true); 65 } 66 67 public void reset(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses, boolean removeAll) { 68 super.reset(propMeta, selectedClasses); 69 setLayoutFormat(PropertyEditor.LayoutFormat.DOUBLE_LINE); 70 reset(removeAll); 71 } 72 73 @Override 74 protected void valueIsIndeterminate() { 75 // Set all the items as undeterminate, whathever is the value 76 for (EditorItem editorItem : editorItems) { 77 editorItem.setValueAsIndeterminate(); 78 } 79 } 80 81 @Override 82 public void commit(EditorItem source) { 83 // System.out.println("COMMIT"); 84 userUpdateValueProperty(getValue()); 85 } 86 87 @Override 88 public void editing(boolean editing, EventHandler<?> editingHandler) { 89 editingProperty().setValue(editing); 90 setCommitListener(editingHandler); 91 } 92 93 @Override 94 public void add(EditorItem previousItem, EditorItem newItem) { 95 // System.out.println("ADD"); 96 addItem(previousItem, newItem); 97 userUpdateValueProperty(getValue()); 98 } 99 100 @Override 101 public void remove(EditorItem source) { 102 // By default, keep 1 item 103 remove(source, false); 104 } 105 106 public void remove(EditorItem source, boolean removeAll) { 107 // System.out.println("REMOVE"); 108 removeItem(source, removeAll); 109 userUpdateValueProperty(getValue()); 110 } 111 112 @Override 113 public void up(EditorItem source) { 114 // System.out.println("UP"); 115 upItem(source); 116 userUpdateValueProperty(getValue()); 117 } 118 119 @Override 120 public void down(EditorItem source) { 121 // System.out.println("DOWN"); 122 downItem(source); 123 userUpdateValueProperty(getValue()); 124 } 125 126 final protected List<EditorItem> getEditorItems() { 127 return editorItems; 128 } 129 130 final protected EditorItem addItem(EditorItem newItem) { 131 return addItem(null, newItem); 132 } 133 134 final protected EditorItem addItem(EditorItem previousItem, EditorItem newItem) { 135 int index = -1; 136 if (previousItem != null) { 137 // Add the new item under the source EditorItem 138 index = editorItems.indexOf(previousItem) + 1; 139 } 140 if (index != -1) { 141 editorItems.add(index, newItem); 142 vbox.getChildren().add(index, newItem.getNode()); 143 } else { 144 editorItems.add(newItem); 145 vbox.getChildren().add(newItem.getNode()); 146 } 147 updateMenuItems(); 148 return newItem; 149 } 150 151 protected void removeItem(EditorItem editorItem) { 152 // By default, keep 1 item 153 removeItem(editorItem, false); 154 } 155 156 protected void removeItem(EditorItem editorItem, boolean removeAll) { 157 if (!removeAll && editorItems.size() == 1) { 158 // Do not remove last item, but reset it 159 editorItem.reset(); 160 if (editorItem.getRemoveMenuItem() != null) { 161 editorItem.getRemoveMenuItem().setDisable(true); 162 } 163 return; 164 } 165 editorItems.remove(editorItem); 166 vbox.getChildren().remove(editorItem.getNode()); 167 updateMenuItems(); 168 } 169 170 protected void upItem(EditorItem editorItem) { 171 int indexItem = editorItems.indexOf(editorItem); 172 // item should be in the list, and not the 1st item 173 assert (indexItem != -1) && (indexItem != 0); 174 assert vbox.getChildren().indexOf(editorItem.getNode()) == indexItem; 175 Collections.swap(editorItems, indexItem, indexItem - 1); 176 EditorUtils.swap(vbox.getChildren(), indexItem, indexItem - 1); 177 vbox.requestLayout(); 178 updateMenuItems(); 179 } 180 181 protected void downItem(EditorItem editorItem) { 182 int indexItem = editorItems.indexOf(editorItem); 183 // item should be in the list, and not the last item 184 assert (indexItem != -1) && (indexItem != editorItems.size() - 1); 185 assert vbox.getChildren().indexOf(editorItem.getNode()) == indexItem; 186 Collections.swap(editorItems, indexItem, indexItem + 1); 187 EditorUtils.swap(vbox.getChildren(), indexItem, indexItem + 1); 188 updateMenuItems(); 189 } 190 191 protected void reset() { 192 // By default, keep 1 item 193 reset(false); 194 } 195 196 protected void reset(boolean removeAll) { 197 List<EditorItem> items = new ArrayList<>(editorItems); 198 for (EditorItem editorItem : items) { 199 removeItem(editorItem, removeAll); 200 } 201 updateMenuItems(); 202 } 203 204 private void updateMenuItems() { 205 for (int ii = 0; ii < editorItems.size(); ii++) { 206 EditorItem item = editorItems.get(ii); 207 if (item.getMoveUpMenuItem() == null || item.getMoveDownMenuItem() == null) { 208 continue; 209 } 210 if (ii == 0) { 211 // first item 212 item.getMoveUpMenuItem().setDisable(true); 213 } else { 214 item.getMoveUpMenuItem().setDisable(false); 215 } 216 if (ii == (editorItems.size() - 1)) { 217 // last item 218 item.getMoveDownMenuItem().setDisable(true); 219 } else { 220 item.getMoveDownMenuItem().setDisable(false); 221 } 222 } 223 } 224 225 }