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.editor.i18n.I18N; 35 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata; 36 import com.oracle.javafx.scenebuilder.kit.util.JavaLanguage; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.Set; 41 42 import javafx.event.ActionEvent; 43 import javafx.event.EventHandler; 44 import javafx.geometry.Pos; 45 import javafx.scene.Node; 46 import javafx.scene.control.Label; 47 import javafx.scene.control.MenuItem; 48 import javafx.scene.layout.HBox; 49 import javafx.scene.layout.Priority; 50 import javafx.scene.layout.StackPane; 51 52 /** 53 * Event handler editor. An event handler in FXML can be of 2 types: - script 54 * event handler - controller method event handler. 55 * 56 * 57 */ 58 public class EventHandlerEditor extends AutoSuggestEditor { 59 60 private static final String HASH_STR = "#"; //NOI18N 61 private final MenuItem controllerMethodMenuItem = new MenuItem(I18N.getString("inspector.event.menu.methodmode")); 62 private final MenuItem scriptMenuItem = new MenuItem(I18N.getString("inspector.event.menu.scriptmode")); 63 private boolean methodNameMode; 64 private StackPane root = new StackPane(); 65 private HBox hbox = null; 66 private List<String> suggestedMethods; 67 68 public EventHandlerEditor(ValuePropertyMetadata propMeta, Set<Class<?>> selectedClasses, List<String> suggestedMethods) { 69 super(propMeta, selectedClasses, suggestedMethods); //NOI18N 70 initialize(suggestedMethods); 71 } 72 73 private void initialize(List<String> suggestedMethods) { 74 this.suggestedMethods = suggestedMethods; 75 76 // text field events handling 77 EventHandler<ActionEvent> onActionListener = event -> { 78 String tfValue = getTextField().getText(); 79 if (tfValue == null || tfValue.isEmpty()) { 80 userUpdateValueProperty(null); 81 return; 82 } 83 if (methodNameMode) { 84 // method name should be a java identifier 85 if (!JavaLanguage.isIdentifier(tfValue)) { 86 System.err.println(I18N.getString("inspector.event.invalid.method", tfValue)); // Will go in message panel 87 handleInvalidValue(tfValue); 88 return; 89 } 90 } 91 Object value = getValue(); 92 assert value instanceof String; 93 userUpdateValueProperty((String) value); 94 getTextField().selectAll(); 95 }; 96 setTextEditorBehavior(this, getTextField(), onActionListener); 97 98 scriptMenuItem.setOnAction(e -> { 99 getTextField().setText(null); 100 userUpdateValueProperty(null); 101 switchToScriptMode(); 102 }); 103 104 controllerMethodMenuItem.setOnAction(e -> { 105 getTextField().setText(null); 106 userUpdateValueProperty(null); 107 switchToMethodNameMode(); 108 }); 109 getMenu().getItems().add(controllerMethodMenuItem); 110 111 // methodeName mode by default 112 switchToMethodNameMode(); 113 } 114 115 @Override 116 public Object getValue() { 117 String valueTf = getTextField().getText(); 118 if (valueTf == null || valueTf.isEmpty()) { 119 return null; // default value 120 } 121 String value; 122 if (methodNameMode) { 123 value = HASH_STR + getTextField().getText(); 124 } else { 125 value = getTextField().getText(); 126 } 127 // System.out.println("EventHandlerEditor : getValue() returns: '" + value + "'"); 128 return value; 129 } 130 131 @Override 132 public void setValue(Object value) { 133 // System.out.println("EventHandlerEditor : setValue to '" + value + "'"); 134 setValueGeneric(value); 135 if (isSetValueDone()) { 136 return; 137 } 138 139 String valueStr; 140 if (value == null) { 141 if (!methodNameMode) { 142 switchToMethodNameMode(); 143 } 144 valueStr = null; 145 } else { 146 assert value instanceof String; 147 valueStr = (String) value; 148 if (valueStr.startsWith(HASH_STR)) { 149 if (!methodNameMode) { 150 switchToMethodNameMode(); 151 } 152 valueStr = valueStr.substring(1); 153 } else if (!valueStr.startsWith(HASH_STR) && methodNameMode) { 154 switchToScriptMode(); 155 } 156 } 157 getTextField().setText(valueStr); 158 } 159 160 @Override 161 public Node getValueEditor() { 162 return super.handleGenericModes(root); 163 } 164 165 @Override 166 public void reset(String name, String defaultValue, List<String> suggestedList) { 167 super.reset(name, defaultValue, suggestedList); 168 switchToMethodNameMode(); 169 } 170 171 private void wrapInHBox() { 172 hbox = new HBox(); 173 hbox.setAlignment(Pos.CENTER); 174 Label hashLabel = new Label(HASH_STR); 175 hashLabel.getStyleClass().add("symbol-prefix"); 176 hbox.getChildren().addAll(hashLabel, getRoot()); 177 HBox.setHgrow(hashLabel, Priority.NEVER); 178 root.getChildren().clear(); 179 root.getChildren().add(hbox); 180 } 181 182 private void unwrapHBox() { 183 root.getChildren().clear(); 184 root.getChildren().add(getRoot()); 185 } 186 187 private void switchToMethodNameMode() { 188 methodNameMode = true; 189 resetSuggestedList(suggestedMethods); 190 replaceMenuItem(controllerMethodMenuItem, scriptMenuItem); 191 wrapInHBox(); 192 } 193 194 private void switchToScriptMode() { 195 methodNameMode = false; 196 resetSuggestedList(new ArrayList<>()); 197 replaceMenuItem(scriptMenuItem, controllerMethodMenuItem); 198 unwrapHBox(); 199 } 200 }