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 }