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.fxom;
  33 
  34 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.list.ColumnConstraintsListPropertyMetadata;
  35 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.list.RowConstraintsListPropertyMetadata;
  36 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
  37 import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
  38 import java.util.List;
  39 import javafx.scene.control.TitledPane;
  40 import javafx.scene.layout.GridPane;
  41 
  42 /**
  43  *
  44  *
  45  */
  46 class FXOMNormalizer {
  47 
  48     /*
  49      * We look for properties with $null values and remove them.
  50      * Exemple with ScrollPane.content.
  51      *
  52      *      <ScrollPane content="$null" ... />
  53      *
  54      * is transformed in:
  55      *
  56      *      <ScrollPane ... />
  57      *
  58      */
  59 
  60     /*
  61      *
  62      * We look for the following pattern:
  63      *
  64      * <Accordion>
  65      *   <expandedPane>
  66      *     <TitledPane fx:id="x1" text="B">
  67      *       ...
  68      *     </TitledPane>
  69      *   </expandedPane>
  70      *   <panes>
  71      *     <TitledPane text="A">
  72      *       ...
  73      *     </TitledPane>
  74      *     <fx:reference source="x1" />
  75      *   </panes>
  76      * </Accordion>
  77      *
  78      *
  79      * and transform it as:
  80      *
  81      * <Accordion>
  82      *   <panes>
  83      *     <TitledPane text="A">
  84      *       ...
  85      *     </TitledPane>
  86      *     <TitledPane text="B">
  87      *       ...
  88      *     </TitledPane>
  89      *   </panes>
  90      * </Accordion>
  91      *
  92      *
  93      */
  94 
  95     private static final PropertyName expandedPaneName
  96             = new PropertyName("expandedPane");
  97 
  98     private final FXOMDocument fxomDocument;
  99     private int changeCount;
 100 
 101     public FXOMNormalizer(FXOMDocument fxomDocument) {
 102         this.fxomDocument = fxomDocument;
 103     }
 104 
 105     public void normalize() {
 106         changeCount = 0;
 107         normalizeExpandedPaneProperties();
 108         normalizeGridPanes();
 109         if (changeCount >= 1) {
 110             fxomDocument.refreshSceneGraph();
 111         }
 112     }
 113 
 114     public void normalizeExpandedPaneProperties() {
 115 
 116         final List<FXOMProperty> expandedPaneProperties
 117                 = fxomDocument.getFxomRoot().collectProperties(expandedPaneName);
 118 
 119         for (FXOMProperty p : expandedPaneProperties) {
 120             if (p instanceof FXOMPropertyC) {
 121                 final FXOMPropertyC pc = (FXOMPropertyC) p;
 122                 assert pc.getValues().isEmpty() == false;
 123                 final FXOMObject v0 = pc.getValues().get(0);
 124                 if (v0 instanceof FXOMInstance) {
 125                     normalizeExpandedPaneProperty(pc);
 126                 } else {
 127                     assert v0 instanceof FXOMIntrinsic;
 128                     p.removeFromParentInstance();
 129                 }
 130             } else {
 131                 assert p instanceof FXOMPropertyT;
 132                 final FXOMPropertyT pt = (FXOMPropertyT)p;
 133                 assert pt.getValue().equals("$null");
 134                 p.removeFromParentInstance();
 135             }
 136 
 137             changeCount++;
 138         }
 139     }
 140 
 141     private void normalizeExpandedPaneProperty(FXOMPropertyC p) {
 142 
 143         assert p != null;
 144 
 145         /*
 146          *
 147          * <Accordion>                           // p.getParentInstance()
 148          *   <expandedPane>                      // p
 149          *     <TitledPane fx:id="x1" text="B">  // p.getValues().get(0)
 150          *       ...
 151          *     </TitledPane>
 152          *   </expandedPane>
 153          *   <panes>                             // reference.getParentProperty()
 154          *     <TitledPane text="A">
 155          *       ...
 156          *     </TitledPane>
 157          *     <fx:reference source="x1" />      // reference
 158          *   </panes>
 159          * </Accordion>
 160          *
 161          */
 162 
 163         final FXOMInstance parentInstance = p.getParentInstance();
 164         assert parentInstance != null;
 165         final FXOMObject titledPane = p.getValues().get(0);
 166         assert titledPane.getSceneGraphObject() instanceof TitledPane;
 167         assert titledPane.getFxId() != null;
 168 
 169         final FXOMObject fxomRoot = p.getFxomDocument().getFxomRoot();
 170         final List<FXOMIntrinsic> references
 171                 = fxomRoot.collectReferences(titledPane.getFxId());
 172         assert references.size() == 1;
 173         final FXOMIntrinsic reference = references.get(0);
 174         assert reference.getSource().equals(titledPane.getFxId());
 175         assert reference.getParentObject() == parentInstance;
 176         final int referenceIndex = reference.getIndexInParentProperty();
 177 
 178         p.removeFromParentInstance();
 179         titledPane.removeFromParentProperty();
 180         titledPane.addToParentProperty(referenceIndex, reference.getParentProperty());
 181         reference.removeFromParentProperty();
 182     }
 183 
 184 
 185 
 186     private void normalizeGridPanes() {
 187         final FXOMObject fxomRoot = fxomDocument.getFxomRoot();
 188         for (FXOMObject fxomGridPane : fxomRoot.collectObjectWithSceneGraphObjectClass(GridPane.class)) {
 189             normalizeGridPane(fxomGridPane);
 190             changeCount++;
 191         }
 192     }
 193 
 194     private final static ColumnConstraintsListPropertyMetadata columnConstraintsMeta
 195             = new ColumnConstraintsListPropertyMetadata();
 196     private final static RowConstraintsListPropertyMetadata rowConstraintsMeta
 197             = new RowConstraintsListPropertyMetadata();
 198 
 199     private void normalizeGridPane(FXOMObject fxomGridPane) {
 200         assert fxomGridPane instanceof FXOMInstance;
 201         assert fxomGridPane.getSceneGraphObject() instanceof GridPane;
 202 
 203         final GridPane gridPane = (GridPane) fxomGridPane.getSceneGraphObject();
 204         final int columnCount = Deprecation.getGridPaneColumnCount(gridPane);
 205         final int rowCount = Deprecation.getGridPaneRowCount(gridPane);
 206         columnConstraintsMeta.unpack((FXOMInstance) fxomGridPane, columnCount);
 207         rowConstraintsMeta.unpack((FXOMInstance) fxomGridPane, rowCount);
 208     }
 209 }