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 
  33 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.gesture.mouse;
  34 
  35 import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
  36 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N;
  37 import com.oracle.javafx.scenebuilder.kit.editor.job.BatchJob;
  38 import com.oracle.javafx.scenebuilder.kit.editor.job.Job;
  39 import com.oracle.javafx.scenebuilder.kit.editor.job.atomic.ModifyObjectJob;
  40 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
  41 import com.oracle.javafx.scenebuilder.kit.editor.panel.content.driver.resizer.TableColumnResizer;
  42 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMInstance;
  43 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject;
  44 import com.oracle.javafx.scenebuilder.kit.metadata.Metadata;
  45 import com.oracle.javafx.scenebuilder.kit.metadata.property.ValuePropertyMetadata;
  46 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
  47 import java.util.ArrayList;
  48 import java.util.HashMap;
  49 import java.util.List;
  50 import java.util.Map;
  51 import javafx.geometry.Point2D;
  52 import javafx.scene.control.TableColumn;
  53 import javafx.scene.control.TableView;
  54 import javafx.scene.input.KeyEvent;
  55 
  56 /**
  57  *
  58  */
  59 public class ResizeTableColumnGesture extends AbstractMouseGesture {
  60 
  61     private final FXOMInstance columnInstance;
  62     private TableColumnResizer resizer;
  63 
  64 
  65     public ResizeTableColumnGesture(ContentPanelController contentPanelController,
  66             FXOMInstance fxomInstance) {
  67         super(contentPanelController);
  68 
  69         assert fxomInstance != null;
  70         assert fxomInstance.getSceneGraphObject() instanceof TableColumn;
  71 
  72         this.columnInstance = fxomInstance;
  73     }
  74 
  75     /*
  76      * AbstractMouseGesture
  77      */
  78 
  79     @Override
  80     protected void mousePressed() {
  81         // Everthing is done in mouseDragStarted
  82     }
  83 
  84     @Override
  85     protected void mouseDragStarted() {
  86         assert resizer == null;
  87         assert columnInstance.getSceneGraphObject() instanceof TableColumn;
  88 
  89         resizer = new TableColumnResizer((TableColumn<?,?>)columnInstance.getSceneGraphObject());
  90 
  91         // Now same as mouseDragged
  92         mouseDragged();
  93     }
  94 
  95     @Override
  96     protected void mouseDragged() {
  97         assert resizer != null;
  98 
  99         final double startSceneX = getMousePressedEvent().getSceneX();
 100         final double startSceneY = getMousePressedEvent().getSceneY();
 101         final double currentSceneX = getLastMouseEvent().getSceneX();
 102         final double currentSceneY = getLastMouseEvent().getSceneY();
 103         final TableView<?> tableView = resizer.getTableColumn().getTableView();
 104         final Point2D start = tableView.sceneToLocal(startSceneX, startSceneY, true /* rootScene */);
 105         final Point2D current = tableView.sceneToLocal(currentSceneX, currentSceneY, true /* rootScene */);
 106         final double dx = current.getX() - start.getX();
 107 
 108         resizer.updateWidth(dx);
 109         tableView.layout();
 110     }
 111 
 112     @Override
 113     protected void mouseDragEnded() {
 114         assert resizer != null;
 115 
 116         /*
 117          * Three steps
 118          *
 119          * 1) Collects sizing properties that have changed
 120          * 2) Reverts to initial sizing
 121          *    => this step is equivalent to userDidCancel()
 122          * 3) Push a BatchModifyObjectJob to officially resize the columns
 123          */
 124 
 125         // Step #1
 126         final Map<PropertyName, Object> changeMap = resizer.getChangeMap();
 127         final Map<PropertyName, Object> changeMapNext = resizer.getChangeMapNext();
 128 
 129 
 130         // Step #2
 131         userDidCancel();
 132 
 133         // Step #3
 134         final EditorController editorController
 135                 = contentPanelController.getEditorController();
 136         final BatchJob batchJob
 137                 = new BatchJob(editorController, true,
 138                 I18N.getString("label.action.edit.resize.column"));
 139         if (changeMap.isEmpty() == false) {
 140             batchJob.addSubJobs(makeResizeJob(columnInstance, changeMap));
 141         }
 142         if (changeMapNext.isEmpty() == false) {
 143             batchJob.addSubJobs(makeResizeJob(columnInstance.getNextSlibing(), changeMapNext));
 144         }
 145         if (batchJob.isExecutable()) {
 146             editorController.getJobManager().push(batchJob);
 147         }
 148 
 149         resizer = null; // For sake of symetry...
 150     }
 151 
 152     @Override
 153     protected void mouseReleased() {
 154         // Everything is done in mouseDragEnded
 155     }
 156 
 157     @Override
 158     protected void keyEvent(KeyEvent e) {
 159         // Nothing special here
 160     }
 161 
 162     @Override
 163     protected void userDidCancel() {
 164         resizer.revertToOriginalSize();
 165         resizer.getTableColumn().getTableView().layout();
 166     }
 167 
 168 
 169     /*
 170      * Private
 171      */
 172 
 173     private List<Job> makeResizeJob(FXOMObject columnObject, Map<PropertyName, Object> changeMap) {
 174         assert columnObject.getSceneGraphObject() instanceof TableColumn;
 175         assert columnObject instanceof FXOMInstance;
 176 
 177         final List<Job> result = new ArrayList<>();
 178 
 179         final Metadata metadata = Metadata.getMetadata();
 180         final Map<ValuePropertyMetadata, Object> metaValueMap = new HashMap<>();
 181         for (Map.Entry<PropertyName,Object> e : changeMap.entrySet()) {
 182             final ValuePropertyMetadata vpm = metadata.queryValueProperty(columnInstance, e.getKey());
 183             assert vpm != null;
 184             metaValueMap.put(vpm, e.getValue());
 185         }
 186 
 187         for (Map.Entry<ValuePropertyMetadata, Object> e : metaValueMap.entrySet()) {
 188             final ModifyObjectJob job = new ModifyObjectJob(
 189                     (FXOMInstance) columnObject,
 190                     e.getKey(),
 191                     e.getValue(),
 192                     contentPanelController.getEditorController());
 193             result.add(job);
 194         }
 195         return result;
 196     }
 197 }