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 }