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.TableViewDesignInfoX;
  36 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.AbstractGesture;
  37 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse.ResizeTableColumnGesture;
  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.TableColumn;
  48 import javafx.scene.control.TableView;
  49 import javafx.scene.paint.Color;
  50 import javafx.scene.shape.Line;
  51 
  52 /**
  53  *
  54  *
  55  */
  56 public class TableViewHandles extends AbstractNodeHandles<Node> {
  57 
  58     private final Group grips = new Group();
  59 
  60     public TableViewHandles(ContentPanelController contentPanelController,
  61             FXOMInstance fxomInstance) {
  62         super(contentPanelController, fxomInstance, Node.class);
  63         assert fxomInstance.getSceneGraphObject() instanceof TableView;
  64 
  65         getRootNode().getChildren().add(grips); // Above handles
  66     }
  67 
  68     public TableView<?> getTableView() {
  69         return (TableView<?>) 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 = getTableView().getColumns().size(); i < count; i++) {
  84             layoutGrip(i);
  85         }
  86     }
  87 
  88     @Override
  89     public AbstractGesture findGesture(Node node) {
  90 
  91         final AbstractGesture result;
  92 
  93         final int gripIndex = grips.getChildren().indexOf(node);
  94         if (gripIndex != -1) {
  95             final DesignHierarchyMask m = new DesignHierarchyMask(getFxomInstance());
  96             final FXOMObject columnObject = m.getSubComponentAtIndex(gripIndex);
  97             assert columnObject instanceof FXOMInstance;
  98             result = new ResizeTableColumnGesture(getContentPanelController(),
  99                     (FXOMInstance)columnObject);
 100         } else {
 101             result = super.findGesture(node);
 102         }
 103 
 104         return result;
 105     }
 106 
 107 
 108     /*
 109      * Private
 110      */
 111 
 112     private void adjustGripCount() {
 113         final int columnCount = getTableView().getColumns().size();
 114         final List<Node> gripChildren = grips.getChildren();
 115 
 116         while (gripChildren.size() < columnCount) {
 117             gripChildren.add(makeGripLine());
 118         }
 119         while (gripChildren.size() > columnCount) {
 120             gripChildren.remove(gripChildren.size()-1);
 121         }
 122     }
 123 
 124     private Line makeGripLine() {
 125         final Line result = new Line();
 126         result.setStrokeWidth(SELECTION_HANDLES_SIZE);
 127         result.setStroke(Color.TRANSPARENT);
 128         result.setCursor(Cursor.H_RESIZE);
 129         attachHandles(result);
 130         return result;
 131     }
 132 
 133     private void layoutGrip(int gripIndex) {
 134         assert grips.getChildren().get(gripIndex) instanceof Line;
 135 
 136         final TableColumn<?,?> tc = getTableView().getColumns().get(gripIndex);
 137         if (tc.isVisible()) {
 138             final TableViewDesignInfoX di = new TableViewDesignInfoX();
 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 }