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.content.gesture.mouse; 33 34 import com.oracle.javafx.scenebuilder.kit.editor.EditorController; 35 import com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform; 36 import com.oracle.javafx.scenebuilder.kit.editor.drag.source.DocumentDragSource; 37 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController; 38 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup; 39 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection; 40 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject; 41 import javafx.geometry.Point2D; 42 import javafx.scene.Node; 43 import javafx.scene.input.Dragboard; 44 import javafx.scene.input.MouseEvent; 45 import javafx.scene.input.TransferMode; 46 import javafx.stage.Window; 47 48 /** 49 * 50 * 51 */ 52 public class SelectAndMoveGesture extends AbstractMouseDragGesture { 53 54 public SelectAndMoveGesture(ContentPanelController contentPanelController) { 55 super(contentPanelController); 56 } 57 58 private FXOMObject hitObject; 59 private double hitSceneX; 60 private double hitSceneY; 61 62 public FXOMObject getHitObject() { 63 return hitObject; 64 } 65 66 public void setHitObject(FXOMObject hitObject) { 67 this.hitObject = hitObject; 68 } 69 70 public void setHitSceneX(double hitSceneX) { 71 this.hitSceneX = hitSceneX; 72 } 73 74 public void setHitSceneY(double hitSceneY) { 75 this.hitSceneY = hitSceneY; 76 } 77 78 /* 79 * AbstractMouseDragGesture 80 */ 81 82 @Override 83 protected void mousePressed(MouseEvent e) { 84 85 /* 86 * | hitObject | hitObject | 87 * | selected | unselected | 88 * | +--------------------+--------------------+ 89 * | | no selected | an ancestor | 90 * | | ancestor | is selected | 91 * ------------+--------------------+--------------------+--------------------+ 92 * | | | | 93 * | | select hitObject | | 94 * shift up | start drag gesture | start drag gesture | start drag gesture | 95 * | | | | 96 * | (A) | (B.1) | (B.2) | 97 * ------------+--------------------+--------------------+--------------------+ 98 * | | | | 99 * | remove hitObject | add hitObject | remove ancestor | 100 * shift down | from selection | to selection | from selection | 101 * | ignore drag gesture| start drag gesture | ignore drag gesture| 102 * | (C) | (D.1) | (D.2) | 103 * ------------+--------------------+--------------------+--------------------+ 104 */ 105 106 final Selection selection 107 = contentPanelController.getEditorController().getSelection(); 108 final boolean extendKeyDown 109 = EditorPlatform.isContinuousSelectKeyDown(e) 110 || EditorPlatform.isNonContinousSelectKeyDown(e); 111 112 if (selection.isSelected(hitObject)) { 113 if (extendKeyDown) { // Case C 114 selection.toggleSelection(hitObject); 115 } // else Case A 116 } else { 117 final FXOMObject ancestor = selection.lookupSelectedAncestor(hitObject); 118 if (ancestor == null) { 119 if (extendKeyDown) { // Case D.1 120 selection.toggleSelection(hitObject); 121 } else { // Case B.1 122 selection.select(hitObject); 123 } 124 } else { 125 if (extendKeyDown) { // Case D.2 126 selection.toggleSelection(ancestor); 127 } // else Case B.2 128 } 129 } 130 } 131 132 @Override 133 protected void mouseDragDetected(MouseEvent e) { 134 final Selection selection 135 = contentPanelController.getEditorController().getSelection(); 136 137 /* 138 * | hitObject | hitObject | 139 * | selected | unselected | 140 * | +--------------------+--------------------+ 141 * | | no selected | an ancestor | 142 * | | ancestor | is selected | 143 * ------------+--------------------+--------------------+--------------------+ 144 * | | | | 145 * | | select hitObject | | 146 * shift up | start drag gesture | start drag gesture | start drag gesture | 147 * | | | | 148 * | (A) | (B.1) | (B.2) | 149 * ------------+--------------------+--------------------+--------------------+ 150 * | | | | 151 * | remove hitObject | add hitObject | remove ancestor | 152 * shift down | from selection | to selection | from selection | 153 * | ignore drag gesture| start drag gesture | ignore drag gesture| 154 * | (C) | (D.1) | (D.2) | 155 * ------------+--------------------+--------------------+--------------------+ 156 */ 157 158 final FXOMObject selectedHitObject; 159 if (selection.isSelected(hitObject)) { // Case A, B.1 or D.1 160 selectedHitObject = hitObject; 161 } else { 162 selectedHitObject = selection.lookupSelectedAncestor(hitObject); // Case B.2 163 } 164 165 if (selectedHitObject != null) { 166 167 assert selection.getGroup() instanceof ObjectSelectionGroup; 168 169 final ObjectSelectionGroup 170 osg = (ObjectSelectionGroup) selection.getGroup(); 171 172 if (osg.hasSingleParent()) { 173 final EditorController editorController 174 = contentPanelController.getEditorController(); 175 final Window ownerWindow 176 = contentPanelController.getPanelRoot().getScene().getWindow(); 177 final Point2D hitPoint 178 = computeHitPoint(selectedHitObject); 179 final DocumentDragSource dragSource = new DocumentDragSource( 180 osg.getSortedItems(), selectedHitObject, 181 hitPoint.getX(), hitPoint.getY(), ownerWindow); 182 183 if (dragSource.isAcceptable()) { 184 final Node glassLayer = contentPanelController.getGlassLayer(); 185 final Dragboard db = glassLayer.startDragAndDrop(TransferMode.COPY_OR_MOVE); 186 db.setContent(dragSource.makeClipboardContent()); 187 db.setDragView(dragSource.makeDragView()); 188 189 assert editorController.getDragController().getDragSource() == null; 190 editorController.getDragController().begin(dragSource); 191 } 192 } 193 } 194 } 195 196 private Point2D computeHitPoint(FXOMObject fxomObject) { 197 198 final FXOMObject nodeObject = fxomObject.getClosestNode(); 199 assert nodeObject != null; // At least the root is a Node 200 assert nodeObject.getSceneGraphObject() instanceof Node; 201 final Node sceneGraphNode = (Node) nodeObject.getSceneGraphObject(); 202 return sceneGraphNode.sceneToLocal(hitSceneX, hitSceneY, true /* rootScene */); 203 } 204 205 @Override 206 protected void mouseReleased(MouseEvent e) { 207 208 // Click but no move : in that case, we make sure that 209 // the hit object *only* is selected when shift is up. 210 211 final Selection selection 212 = contentPanelController.getEditorController().getSelection(); 213 final boolean extendKeyDown 214 = EditorPlatform.isContinuousSelectKeyDown(e) 215 || EditorPlatform.isNonContinousSelectKeyDown(e); 216 if (extendKeyDown == false) { 217 selection.select(hitObject); 218 } 219 220 /* 221 * | hitObject | hitObject | 222 * | selected | unselected | 223 * | +--------------------+--------------------+ 224 * | | no selected | an ancestor | 225 * | | ancestor | is selected | 226 * ------------+--------------------+--------------------+--------------------+ 227 * | | | | 228 * | | select hitObject | | 229 * shift up | start drag gesture | start drag gesture | start drag gesture | 230 * | | | | 231 * | (A) | (B.1) | (B.2) | 232 * ------------+--------------------+--------------------+--------------------+ 233 * | | | | 234 * | remove hitObject | add hitObject | remove ancestor | 235 * shift down | from selection | to selection | from selection | 236 * | ignore drag gesture| start drag gesture | ignore drag gesture| 237 * | (C) | (D.1) | (D.2) | 238 * ------------+--------------------+--------------------+--------------------+ 239 */ 240 241 } 242 243 @Override 244 protected void mouseExited(MouseEvent e) { 245 // Should be not called because mouse should exit glass layer 246 // during this gesture 247 248 // Commenting the assertion : in some cases, this method is executed ; 249 // is it related to DTL-6393 ? 250 // assert false; 251 } 252 253 }