apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/editors/StyleEditor.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization


  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.EditorController;
  35 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
  36 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
  37 import com.oracle.javafx.scenebuilder.kit.util.CssInternal;
  38 import com.sun.javafx.css.CssError;
  39 import com.sun.javafx.css.StyleManager;
  40 import com.sun.javafx.css.parser.CSSParser;
  41 
  42 import java.util.ArrayList;
  43 import java.util.Collections;
  44 import java.util.Iterator;
  45 import java.util.List;
  46 import java.util.Set;
  47 
  48 import javafx.beans.value.ChangeListener;
  49 import javafx.collections.FXCollections;
  50 import javafx.collections.ListChangeListener;
  51 import javafx.collections.ObservableList;
  52 import javafx.collections.ObservableSet;
  53 import javafx.css.CssMetaData;
  54 import javafx.css.PseudoClass;
  55 import javafx.css.Styleable;
  56 import javafx.event.ActionEvent;
  57 import javafx.event.EventHandler;
  58 import javafx.fxml.FXML;
  59 import javafx.scene.Node;
  60 import javafx.scene.Parent;


 218     private class StyleItem extends AutoSuggestEditor implements EditorItem {
 219 
 220         @FXML
 221         private Button plusBt;
 222         @FXML
 223         private MenuItem removeMi;
 224         @FXML
 225         private MenuItem moveUpMi;
 226         @FXML
 227         private MenuItem moveDownMi;
 228         @FXML
 229         private TextField valueTf;
 230         @FXML
 231         private StackPane propertySp;
 232 
 233         private Parent root;
 234         private TextField propertyTf;
 235         private String currentValue;
 236         private EditorItemDelegate editor;
 237         private boolean parsingError = false;
 238         private ListChangeListener<CssError> errorListener;
 239 
 240         public StyleItem(EditorItemDelegate editor, List<String> suggestedList) {
 241 //            System.out.println("New StyleItem.");
 242             // It is an AutoSuggestEditor without MenuButton
 243             super("", "", suggestedList, false);
 244             initialize(editor);
 245         }
 246 
 247         // Method to please FindBugs
 248         private void initialize(EditorItemDelegate editor) {
 249             this.editor = editor;
 250             root = EditorUtils.loadFxml("StyleEditorItem.fxml", this);
 251 
 252             // Add the AutoSuggest text field in the scene graph
 253             propertySp.getChildren().add(super.getRoot());
 254 
 255             propertyTf = super.getTextField();
 256             EventHandler<ActionEvent> onActionListener = event -> {
 257 //                    System.out.println("StyleItem : onActionListener");
 258                 if (getValue().equals(currentValue)) {


 292             ChangeListener<Boolean> focusListener = (observable, oldValue, newValue) -> {
 293                 if (!newValue) {
 294                     // focus lost: commit
 295                     editor.editing(false, onActionListener);
 296                 } else {
 297                     // got focus
 298                     editor.editing(true, onActionListener);
 299                 }
 300             };
 301             propertyTf.focusedProperty().addListener(focusListener);
 302             valueTf.focusedProperty().addListener(focusListener);
 303 
 304             // Initialize menu items text
 305             removeMi.setText(I18N.getString("inspector.list.remove"));
 306             moveUpMi.setText(I18N.getString("inspector.list.moveup"));
 307             moveDownMi.setText(I18N.getString("inspector.list.movedown"));
 308 
 309             errorListener = change -> {
 310                 while (change.next()) {
 311                     if (change.wasAdded()) {
 312                         for (CssError error : change.getAddedSubList()) {
 313                             if (error instanceof CssError.InlineStyleParsingError) {
 314                                 parsingError = true;
 315                                 break;
 316                             }
 317                         }
 318                     }
 319                 }
 320             };
 321 
 322         }
 323 
 324         @Override
 325         public final Node getNode() {
 326             return root;
 327         }
 328 
 329         @Override
 330         public Object getValue() {
 331             String value;
 332             if (propertyTf.getText().isEmpty() && valueTf.getText().isEmpty()) {
 333                 return ""; //NOI18N
 334             } else {
 335                 String propertyVal = EditorUtils.getPlainString(propertyTf.getText()).trim();
 336                 String valueVal = EditorUtils.getPlainString(valueTf.getText()).trim();
 337                 value = propertyVal + ": " + valueVal + ";"; //NOI18N
 338             }
 339 
 340             // Parse the style, and set the parsingError boolean if any error
 341             parsingError = false;
 342             StyleManager.errorsProperty().addListener(errorListener);
 343             new CSSParser().parseInlineStyle(new StyleableStub(value));
 344             StyleManager.errorsProperty().removeListener(errorListener);
 345 
 346             return value;
 347         }
 348 
 349         public boolean hasParsingError() {
 350             return parsingError;
 351         }
 352 
 353         @Override
 354         public void setValue(Object style) {
 355             String styleStr = EditorUtils.toString(style);
 356             // remove last ';' if any
 357             if (styleStr.endsWith(";")) { //NOI18N
 358                 styleStr = styleStr.substring(0, styleStr.length() - 1);
 359             }
 360             // split in property and value
 361             int dotIndex = styleStr.indexOf(':');
 362             String propertyStr;
 363             String valueStr = ""; //NOI18N
 364             if (dotIndex != -1) {




  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.EditorController;
  35 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
  36 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
  37 import com.oracle.javafx.scenebuilder.kit.util.CssInternal;
  38 import javafx.css.CssParser;


  39 
  40 import java.util.ArrayList;
  41 import java.util.Collections;
  42 import java.util.Iterator;
  43 import java.util.List;
  44 import java.util.Set;
  45 
  46 import javafx.beans.value.ChangeListener;
  47 import javafx.collections.FXCollections;
  48 import javafx.collections.ListChangeListener;
  49 import javafx.collections.ObservableList;
  50 import javafx.collections.ObservableSet;
  51 import javafx.css.CssMetaData;
  52 import javafx.css.PseudoClass;
  53 import javafx.css.Styleable;
  54 import javafx.event.ActionEvent;
  55 import javafx.event.EventHandler;
  56 import javafx.fxml.FXML;
  57 import javafx.scene.Node;
  58 import javafx.scene.Parent;


 216     private class StyleItem extends AutoSuggestEditor implements EditorItem {
 217 
 218         @FXML
 219         private Button plusBt;
 220         @FXML
 221         private MenuItem removeMi;
 222         @FXML
 223         private MenuItem moveUpMi;
 224         @FXML
 225         private MenuItem moveDownMi;
 226         @FXML
 227         private TextField valueTf;
 228         @FXML
 229         private StackPane propertySp;
 230 
 231         private Parent root;
 232         private TextField propertyTf;
 233         private String currentValue;
 234         private EditorItemDelegate editor;
 235         private boolean parsingError = false;
 236         private ListChangeListener<CssParser.ParseError> errorListener;
 237 
 238         public StyleItem(EditorItemDelegate editor, List<String> suggestedList) {
 239 //            System.out.println("New StyleItem.");
 240             // It is an AutoSuggestEditor without MenuButton
 241             super("", "", suggestedList, false);
 242             initialize(editor);
 243         }
 244 
 245         // Method to please FindBugs
 246         private void initialize(EditorItemDelegate editor) {
 247             this.editor = editor;
 248             root = EditorUtils.loadFxml("StyleEditorItem.fxml", this);
 249 
 250             // Add the AutoSuggest text field in the scene graph
 251             propertySp.getChildren().add(super.getRoot());
 252 
 253             propertyTf = super.getTextField();
 254             EventHandler<ActionEvent> onActionListener = event -> {
 255 //                    System.out.println("StyleItem : onActionListener");
 256                 if (getValue().equals(currentValue)) {


 290             ChangeListener<Boolean> focusListener = (observable, oldValue, newValue) -> {
 291                 if (!newValue) {
 292                     // focus lost: commit
 293                     editor.editing(false, onActionListener);
 294                 } else {
 295                     // got focus
 296                     editor.editing(true, onActionListener);
 297                 }
 298             };
 299             propertyTf.focusedProperty().addListener(focusListener);
 300             valueTf.focusedProperty().addListener(focusListener);
 301 
 302             // Initialize menu items text
 303             removeMi.setText(I18N.getString("inspector.list.remove"));
 304             moveUpMi.setText(I18N.getString("inspector.list.moveup"));
 305             moveDownMi.setText(I18N.getString("inspector.list.movedown"));
 306 
 307             errorListener = change -> {
 308                 while (change.next()) {
 309                     if (change.wasAdded()) {
 310                         for (CssParser.ParseError error : change.getAddedSubList()) {
 311                             if ("InlineStyleParsingError".equals(error.getClass().getSimpleName())) {
 312                                 parsingError = true;
 313                                 break;
 314                             }
 315                         }
 316                     }
 317                 }
 318             };
 319 
 320         }
 321 
 322         @Override
 323         public final Node getNode() {
 324             return root;
 325         }
 326 
 327         @Override
 328         public Object getValue() {
 329             String value;
 330             if (propertyTf.getText().isEmpty() && valueTf.getText().isEmpty()) {
 331                 return ""; //NOI18N
 332             } else {
 333                 String propertyVal = EditorUtils.getPlainString(propertyTf.getText()).trim();
 334                 String valueVal = EditorUtils.getPlainString(valueTf.getText()).trim();
 335                 value = propertyVal + ": " + valueVal + ";"; //NOI18N
 336             }
 337 
 338             // Parse the style, and set the parsingError boolean if any error
 339             parsingError = false;
 340             CssParser.errorsProperty().addListener(errorListener);
 341             new CssParser().parseInlineStyle(new StyleableStub(value));
 342             CssParser.errorsProperty().removeListener(errorListener);
 343 
 344             return value;
 345         }
 346 
 347         public boolean hasParsingError() {
 348             return parsingError;
 349         }
 350 
 351         @Override
 352         public void setValue(Object style) {
 353             String styleStr = EditorUtils.toString(style);
 354             // remove last ';' if any
 355             if (styleStr.endsWith(";")) { //NOI18N
 356                 styleStr = styleStr.substring(0, styleStr.length() - 1);
 357             }
 358             // split in property and value
 359             int dotIndex = styleStr.indexOf(':');
 360             String propertyStr;
 361             String valueStr = ""; //NOI18N
 362             if (dotIndex != -1) {