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.driver.handles; 33 34 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController; 35 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.SplitPaneDesignInfoX; 36 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.AbstractGesture; 37 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse.AdjustDividerGesture; 38 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance; 39 import java.util.List; 40 import javafx.geometry.Bounds; 41 import javafx.geometry.Point2D; 42 import javafx.scene.Cursor; 43 import javafx.scene.Group; 44 import javafx.scene.Node; 45 import javafx.scene.control.SplitPane; 46 import javafx.scene.paint.Color; 47 import javafx.scene.shape.Line; 48 49 /** 50 * 51 * 52 */ 53 public class SplitPaneHandles extends AbstractNodeHandles<SplitPane> { 54 55 private final Group grips = new Group(); 56 57 public SplitPaneHandles(ContentPanelController contentPanelController, 58 FXOMInstance fxomInstance) { 59 super(contentPanelController, fxomInstance, SplitPane.class); 60 61 getRootNode().getChildren().add(grips); // Above handles 62 } 63 64 65 /* 66 * AbstractNodeHandles 67 */ 68 @Override 69 protected void layoutDecoration() { 70 super.layoutDecoration(); 71 72 // Adjusts the number of grip lines to the number of dividers 73 adjustGripCount(); 74 75 // Updates grip positions 76 final double[] positions = getSceneGraphObject().getDividerPositions(); 77 for (int i = 0, count = positions.length; i < count; i++) { 78 layoutDivider(i); 79 } 80 } 81 82 @Override 83 public AbstractGesture findGesture(Node node) { 84 85 int gripIndex = 0; 86 final int gripCount = grips.getChildren().size(); 87 final List<Node> gripNodes = grips.getChildren(); 88 while ((gripIndex < gripCount) && (gripNodes.get(gripIndex) != node)) { 89 gripIndex++; 90 } 91 92 final AbstractGesture result; 93 if (gripIndex < gripCount) { 94 assert gripNodes.get(gripIndex) == node; 95 result = new AdjustDividerGesture(getContentPanelController(), 96 getFxomInstance(), gripIndex); 97 } else { 98 result = super.findGesture(node); 99 } 100 101 return result; 102 } 103 104 105 /* 106 * Private 107 */ 108 109 private void adjustGripCount() { 110 final int dividerCount = getSceneGraphObject().getDividerPositions().length; 111 final List<Node> gripChildren = grips.getChildren(); 112 113 while (gripChildren.size() < dividerCount) { 114 gripChildren.add(makeGripLine()); 115 } 116 while (gripChildren.size() > dividerCount) { 117 gripChildren.remove(gripChildren.size()-1); 118 } 119 } 120 121 private Line makeGripLine() { 122 final Line result = new Line(); 123 result.setStrokeWidth(SELECTION_HANDLES_SIZE); 124 result.setStroke(Color.TRANSPARENT); 125 switch(getSceneGraphObject().getOrientation()) { 126 default: 127 case HORIZONTAL: 128 result.setCursor(Cursor.H_RESIZE); 129 break; 130 case VERTICAL: 131 result.setCursor(Cursor.V_RESIZE); 132 break; 133 } 134 attachHandles(result); 135 return result; 136 } 137 138 private void layoutDivider(int gripIndex) { 139 assert grips.getChildren().get(gripIndex) instanceof Line; 140 141 142 /* 143 * HORIZONTAL 144 * 145 * startX 146 * endX 147 * +----------+--------------+ startY 148 * | | | 149 * | | | 150 * | | | 151 * | | | 152 * | | | 153 * | | | 154 * | | | 155 * +----------+--------------+ endY 156 * 157 * 158 * VERTICAL 159 * 160 * startX endX 161 * +--------------------+ 162 * | | 163 * | | 164 * | | 165 * +--------------------+ startY endY 166 * | | 167 * | | 168 * | | 169 * | | 170 * | | 171 * +--------------------+ 172 */ 173 174 final SplitPaneDesignInfoX di = new SplitPaneDesignInfoX(); 175 final double pos = getSceneGraphObject().getDividerPositions()[gripIndex]; 176 final double xy = di.dividerPositionToSplitPaneLocal(getSceneGraphObject(), pos); 177 final Bounds lb = getSceneGraphObject().getLayoutBounds(); 178 179 final double startX, startY, endX, endY; 180 switch(getSceneGraphObject().getOrientation()) { 181 default: 182 case HORIZONTAL: 183 startX = xy; 184 startY = lb.getMinY(); 185 endX = xy; 186 endY = lb.getMaxY(); 187 break; 188 case VERTICAL: 189 startX = lb.getMinX(); 190 startY = xy; 191 endX = lb.getMaxX(); 192 endY = xy; 193 break; 194 } 195 196 final boolean snapToPixel = true; 197 final Point2D startPoint = sceneGraphObjectToDecoration(startX, startY, snapToPixel); 198 final Point2D endPoint = sceneGraphObjectToDecoration(endX, endY, snapToPixel); 199 200 final Line gripLine = (Line) grips.getChildren().get(gripIndex); 201 gripLine.setStartX(startPoint.getX()); 202 gripLine.setStartY(startPoint.getY()); 203 gripLine.setEndX(endPoint.getX()); 204 gripLine.setEndY(endPoint.getY()); 205 } 206 207 208 /* 209 * Wrapper to avoid the 'leaking this in constructor' warning emitted by NB. 210 */ 211 private void attachHandles(Node node) { 212 attachHandles(node, this); 213 } 214 }