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.TreeTableViewDesignInfoX;
  36 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.AbstractGesture;
  37 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse.ResizeTreeTableColumnGesture;
  38 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
  39 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
  40 import com.oracle.javafx.scenebuilder.kit.metadata.util.DesignHierarchyMask;
  41 import java.util.List;
  42 import javafx.geometry.Bounds;
  43 import javafx.geometry.Point2D;
  44 import javafx.scene.Cursor;
  45 import javafx.scene.Group;
  46 import javafx.scene.Node;
  47 import javafx.scene.control.TreeTableColumn;
  48 import javafx.scene.control.TreeTableView;
  49 import javafx.scene.paint.Color;
  50 import javafx.scene.shape.Line;
  51 
  52 /**
  53  *
  54  *
  55  */
  56 public class TreeTableViewHandles extends AbstractNodeHandles<Node> {
  57 
  58     private final Group grips = new Group();
  59 
  60     public TreeTableViewHandles(ContentPanelController contentPanelController,
  61             FXOMInstance fxomInstance) {
  62         super(contentPanelController, fxomInstance, Node.class);
  63         assert fxomInstance.getSceneGraphObject() instanceof TreeTableView;
  64 
  65         getRootNode().getChildren().add(grips); // Above handles
  66     }
  67 
  68     public TreeTableView<?> getTreeTableView() {
  69         return (TreeTableView<?>) getSceneGraphObject();
  70     }
  71 
  72     /*
  73      * AbstractNodeHandles
  74      */
  75     @Override
  76     protected void layoutDecoration() {
  77         super.layoutDecoration();
  78 
  79         // Adjusts the number of grip lines to the number of dividers
  80         adjustGripCount();
  81 
  82         // Updates grip positions
  83         for (int i = 0, count = getTreeTableView().getColumns().size(); i < count; i++) {
  84             layoutGrip(i);
  85         }
  86     }
  87 
  88     @Override
  89     public AbstractGesture findGesture(Node node) {
  90         final AbstractGesture result;
  91 
  92         final int gripIndex = grips.getChildren().indexOf(node);
  93         if (gripIndex != -1) {
  94             final DesignHierarchyMask m = new DesignHierarchyMask(getFxomInstance());
  95             final FXOMObject columnObject = m.getSubComponentAtIndex(gripIndex);
  96             assert columnObject instanceof FXOMInstance;
  97             result = new ResizeTreeTableColumnGesture(getContentPanelController(),
  98                     (FXOMInstance) columnObject);
  99         } else {
 100             result = super.findGesture(node);
 101         }
 102 
 103         return result;
 104     }
 105 
 106 
 107     /*
 108      * Private
 109      */
 110 
 111     private void adjustGripCount() {
 112         final int columnCount = getTreeTableView().getColumns().size();
 113         final List<Node> gripChildren = grips.getChildren();
 114 
 115         while (gripChildren.size() < columnCount) {
 116             gripChildren.add(makeGripLine());
 117         }
 118         while (gripChildren.size() > columnCount) {
 119             gripChildren.remove(gripChildren.size()-1);
 120         }
 121     }
 122 
 123     private Line makeGripLine() {
 124         final Line result = new Line();
 125         result.setStrokeWidth(SELECTION_HANDLES_SIZE);
 126         result.setStroke(Color.TRANSPARENT);
 127         result.setCursor(Cursor.H_RESIZE);
 128         attachHandles(result);
 129         return result;
 130     }
 131 
 132     private void layoutGrip(int gripIndex) {
 133         assert grips.getChildren().get(gripIndex) instanceof Line;
 134 
 135         final TreeTableColumn<?,?> tc = getTreeTableView().getColumns().get(gripIndex);
 136 
 137         if (tc.isVisible()) {
 138             final TreeTableViewDesignInfoX di = new TreeTableViewDesignInfoX();
 139             final Bounds b = di.getColumnHeaderBounds(tc);
 140             final double startX = b.getMaxX();
 141             final double startY = b.getMinY();
 142             final double endY = b.getMaxY();
 143 
 144             final boolean snapToPixel = true;
 145             final Point2D startPoint = sceneGraphObjectToDecoration(startX, startY, snapToPixel);
 146             final Point2D endPoint = sceneGraphObjectToDecoration(startX, endY, snapToPixel);
 147 
 148             final Line gripLine = (Line) grips.getChildren().get(gripIndex);
 149             gripLine.setVisible(true);
 150             gripLine.setManaged(true);
 151             gripLine.setStartX(startPoint.getX());
 152             gripLine.setStartY(startPoint.getY());
 153             gripLine.setEndX(endPoint.getX());
 154             gripLine.setEndY(endPoint.getY());
 155         } else {
 156             final Line gripLine = (Line) grips.getChildren().get(gripIndex);
 157             gripLine.setVisible(false);
 158             gripLine.setManaged(false);
 159         }
 160     }
 161 
 162 
 163     /*
 164      * Wrapper to avoid the 'leaking this in constructor' warning emitted by NB.
 165      */
 166     private void attachHandles(Node node) {
 167         attachHandles(node, this);
 168     }
 169 }