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 
  33 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse;
  34 
  35 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
  36 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
  37 import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.ModifyObjectJob;
  38 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.gridpane.GridPaneHandles;
  39 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.resizer.GridPaneRowResizer;
  40 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
  41 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
  42 import com.oracle.javafx.scenebuilder.kit.metadata.property.value.list.RowConstraintsListPropertyMetadata;
  43 import com.oracle.javafx.scenebuilder.kit.metadata.util.InspectorPath;
  44 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
  45 import com.oracle.javafx.scenebuilder.kit.util.Deprecation;
  46 import java.util.ArrayList;
  47 import java.util.Collections;
  48 import java.util.HashMap;
  49 import java.util.List;
  50 import java.util.Map;
  51 import javafx.geometry.Point2D;
  52 import javafx.scene.input.KeyEvent;
  53 import javafx.scene.layout.GridPane;
  54 import javafx.scene.layout.RowConstraints;
  55 
  56 /**
  57  *
  58  */
  59 public class ResizeRowGesture extends AbstractMouseGesture {
  60 
  61     private static final PropertyName rowConstraintsName
  62             = new PropertyName("rowConstraints"); //NOI18N
  63     private static final ValuePropertyMetadata rowConstraintsMeta
  64             = new RowConstraintsListPropertyMetadata(
  65                 rowConstraintsName,
  66                 true, /* readWrite */
  67                 Collections.emptyList(), /* defaultValue */
  68                 InspectorPath.UNUSED);
  69 
  70     private final GridPaneHandles gridPaneHandles;
  71     private final FXOMInstance fxomInstance;
  72     private final int rowIndex;
  73     private final GridPane gridPane;
  74     private GridPaneRowResizer resizer;
  75 
  76 
  77     public ResizeRowGesture(GridPaneHandles gridPaneHandles, int rowIndex) {
  78         super(gridPaneHandles.getContentPanelController());
  79 
  80         assert rowIndex >= 0;
  81 
  82         this.gridPaneHandles = gridPaneHandles;
  83         this.fxomInstance = gridPaneHandles.getFxomInstance(); // Shortcut
  84         this.gridPane = (GridPane) fxomInstance.getSceneGraphObject(); // Shortcut
  85         this.rowIndex = rowIndex;
  86 
  87         assert this.rowIndex < Deprecation.getGridPaneRowCount(this.gridPane);
  88     }
  89 
  90     /*
  91      * AbstractMouseGesture
  92      */
  93 
  94     @Override
  95     protected void mousePressed() {
  96         // Everthing is done in mouseDragStarted
  97     }
  98 
  99     @Override
 100     protected void mouseDragStarted() {
 101         assert resizer == null;
 102 
 103         resizer = new GridPaneRowResizer(gridPane, rowIndex);
 104 
 105         // Now same as mouseDragged
 106         mouseDragged();
 107     }
 108 
 109     @Override
 110     protected void mouseDragged() {
 111         assert resizer != null;
 112 
 113         final double startSceneX = getMousePressedEvent().getSceneX();
 114         final double startSceneY = getMousePressedEvent().getSceneY();
 115         final double currentSceneX = getLastMouseEvent().getSceneX();
 116         final double currentSceneY = getLastMouseEvent().getSceneY();
 117         final Point2D start = gridPane.sceneToLocal(startSceneX, startSceneY, true /* rootScene */);
 118         final Point2D current = gridPane.sceneToLocal(currentSceneX, currentSceneY, true /* rootScene */);
 119         final double dy = current.getY() - start.getY();
 120 
 121         resizer.updateHeight(dy);
 122         gridPane.layout();
 123         gridPaneHandles.layoutDecoration();
 124     }
 125 
 126     @Override
 127     protected void mouseDragEnded() {
 128         assert resizer != null;
 129 
 130         /*
 131          * Three steps
 132          *
 133          * 1) Collects the modified row constraints list
 134          * 2) Reverts to initial sizing
 135          *    => this step is equivalent to userDidCancel()
 136          * 3) Push a BatchModifyObjectJob to officially resize the rows
 137          */
 138 
 139         // Step #1
 140         final List<RowConstraints> newConstraints
 141                 = cloneRowConstraintsList(gridPane);
 142 
 143         // Step #2
 144         userDidCancel();
 145 
 146         // Step #3
 147         final Map<ValuePropertyMetadata, Object> metaValueMap = new HashMap<>();
 148         metaValueMap.put(rowConstraintsMeta, newConstraints);
 149 
 150         final EditorController editorController
 151                 = contentPanelController.getEditorController();
 152         final ModifyObjectJob j = new ModifyObjectJob(
 153                 fxomInstance,
 154                 rowConstraintsMeta,
 155                 newConstraints,
 156                 editorController,
 157                 I18N.getString("label.action.edit.resize.row"));
 158         editorController.getJobManager().push(j);
 159 
 160         gridPaneHandles.layoutDecoration();
 161         resizer = null; // For sake of symetry...
 162     }
 163 
 164     @Override
 165     protected void mouseReleased() {
 166         // Everything is done in mouseDragEnded
 167     }
 168 
 169     @Override
 170     protected void keyEvent(KeyEvent e) {
 171         // Nothing special here
 172     }
 173 
 174     @Override
 175     protected void userDidCancel() {
 176         resizer.revertToOriginalSize();
 177         gridPane.layout();
 178     }
 179 
 180 
 181 
 182     /*
 183      * Private
 184      */
 185 
 186     private List<RowConstraints> cloneRowConstraintsList(GridPane gridPane) {
 187         final List<RowConstraints> result = new ArrayList<>();
 188 
 189         for (RowConstraints rc : gridPane.getRowConstraints()) {
 190             result.add(cloneRowConstraints(rc));
 191         }
 192 
 193         return result;
 194     }
 195 
 196 
 197     private RowConstraints cloneRowConstraints(RowConstraints cc) {
 198         final RowConstraints result = new RowConstraints();
 199 
 200         result.setFillHeight(cc.isFillHeight());
 201         result.setValignment(cc.getValignment());
 202         result.setVgrow(cc.getVgrow());
 203         result.setMaxHeight(cc.getMaxHeight());
 204         result.setMinHeight(cc.getMinHeight());
 205         result.setPercentHeight(cc.getPercentHeight());
 206         result.setPrefHeight(cc.getPrefHeight());
 207 
 208         return result;
 209     }
 210 }