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 }