Author: thomasobrien95
Date: Tue Dec 16 14:35:17 2008
New Revision: 2888

Added:
   trunk/src/ca/sqlpower/architect/swingui/dbtree/SQLObjectSelection.java
Removed:
trunk/src/ca/sqlpower/architect/swingui/dbtree/DnDTreePathTransferable.java
   trunk/src/ca/sqlpower/architect/swingui/query/QueryDropListener.java
Modified:
   trunk/src/ca/sqlpower/architect/swingui/DBTree.java
   trunk/src/ca/sqlpower/architect/swingui/PlayPen.java
   trunk/src/ca/sqlpower/architect/swingui/TablePane.java
   trunk/src/ca/sqlpower/architect/swingui/olap/DnDOLAPTransferable.java

Log:
Fix for bug 1457. Dragging and dropping an object from the tree of
one session to the play pen of another session would cause a NPE or
import the wrong table due to using the DBTree path to get the
object dragged and dropped. The Transferable in Wabit that handled
drag and drop as serialized objects was brought into Architect to
properly handle the drag and drop.

This also fixes a Wabit bug where dragging and dropping from the tree in to the SQL text side of a query resulted in a rejected drop.

Modified: trunk/src/ca/sqlpower/architect/swingui/DBTree.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/DBTree.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/DBTree.java Tue Dec 16 14:35:17 2008
@@ -71,7 +71,7 @@
 import ca.sqlpower.architect.swingui.action.ShowTableContentsAction;
 import ca.sqlpower.architect.swingui.dbtree.DBTreeCellRenderer;
 import ca.sqlpower.architect.swingui.dbtree.DBTreeModel;
-import ca.sqlpower.architect.swingui.dbtree.DnDTreePathTransferable;
+import ca.sqlpower.architect.swingui.dbtree.SQLObjectSelection;
 import ca.sqlpower.sql.SPDataSource;
 import ca.sqlpower.swingui.JTreeCollapseAllAction;
 import ca.sqlpower.swingui.JTreeExpandAllAction;
@@ -811,12 +811,21 @@
                        } else {
                                // export list of DnD-type tree paths
                            StringBuilder userVisibleName = new StringBuilder();
-                               ArrayList<int[]> paths = new 
ArrayList<int[]>(p.length);
+                           List<SQLObject> transferObjects = new 
ArrayList<SQLObject>();
                                for (int i = 0; i < p.length; i++) {
                                        // ignore any playpen tables
                                    SQLObject so = (SQLObject) 
p[i].getLastPathComponent();
- if (DnDTreePathTransferable.getDnDPathToNode(so, (SQLObject) t.getModel().getRoot())[0] != 0) { - paths.add(DnDTreePathTransferable.getDnDPathToNode(so, (SQLObject) t.getModel().getRoot()));
+                                   boolean transferObject = true;
+                                   SQLObject parent = so.getParent();
+                                   while(parent != null) {
+ if (parent instanceof SQLDatabase && ((SQLDatabase) parent).isPlayPenDatabase()) {
+                                           transferObject = false;
+                                           break;
+                                       }
+                                       parent = parent.getParent();
+                                   }
+                    if (transferObject) {
+                        transferObjects.add(so);
                         if (userVisibleName.length() != 0) {
                             userVisibleName.append("\n");
                         }
@@ -829,7 +838,7 @@
                                dge.getDragSource().startDrag
                                        (dge,
                                         null, //DragSource.DefaultCopyNoDrop,
- new DnDTreePathTransferable(paths, userVisibleName.toString(), t.getSelectionPaths()),
+                                        new 
SQLObjectSelection(transferObjects),
                                         t);
                        }
                }
@@ -926,4 +935,5 @@
             }
         }
     }
+
 }

Modified: trunk/src/ca/sqlpower/architect/swingui/PlayPen.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/PlayPen.java        (original)
+++ trunk/src/ca/sqlpower/architect/swingui/PlayPen.java Tue Dec 16 14:35:17 2008
@@ -116,7 +116,7 @@
 import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeDimension;
 import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeMeasure;
 import ca.sqlpower.architect.swingui.action.CancelAction;
-import ca.sqlpower.architect.swingui.dbtree.DnDTreePathTransferable;
+import ca.sqlpower.architect.swingui.dbtree.SQLObjectSelection;
 import ca.sqlpower.architect.swingui.event.PlayPenLifecycleEvent;
 import ca.sqlpower.architect.swingui.event.PlayPenLifecycleListener;
 import ca.sqlpower.architect.swingui.event.SelectionEvent;
@@ -2062,15 +2062,12 @@

                                        
dtde.acceptDrop(DnDConstants.ACTION_COPY);
                                        Point dropLoc = playpen.unzoomPoint(new 
Point(dtde.getLocation()));
-                                       ArrayList paths = (ArrayList) 
t.getTransferData(importFlavor);
+                                       Object[] paths = (Object[]) 
t.getTransferData(importFlavor);
                                        // turn into a Collection of SQLObjects 
to make this more generic
-                                       Iterator it = paths.iterator();
-                                       DBTree dbtree = 
session.getSourceDatabases();
-                                       List sqlObjects = new ArrayList();
-                                       while(it.hasNext()) {
- Object oo = DnDTreePathTransferable.getNodeForDnDPath((SQLObject) dbtree.getModel().getRoot(), (int[])it.next());
+                                       List<SQLObject> sqlObjects = new 
ArrayList<SQLObject>();
+                                       for (Object oo : paths) {
                                                if (oo instanceof SQLObject) {
-                                                       sqlObjects.add(oo);
+                                                       
sqlObjects.add((SQLObject) oo);
                                                } else {
logger.error("Unknown object dropped in PlayPen: "+oo); //$NON-NLS-1$
                                                }
@@ -2130,7 +2127,7 @@
logger.debug("isLocalObject = "+flavors[i].getMimeType().equals(DataFlavor.javaJVMLocalObjectMimeType)); //$NON-NLS-1$


- if (flavors[i].equals(DnDTreePathTransferable.TREEPATH_ARRAYLIST_FLAVOR)) { + if (flavors[i].equals(SQLObjectSelection.LOCAL_SQLOBJECT_ARRAY_FLAVOUR)) {
                                        logger.debug("YES"); //$NON-NLS-1$
                                        best = flavors[i];
                                } else {

Modified: trunk/src/ca/sqlpower/architect/swingui/TablePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/TablePane.java      (original)
+++ trunk/src/ca/sqlpower/architect/swingui/TablePane.java Tue Dec 16 14:35:17 2008
@@ -65,7 +65,7 @@
 import ca.sqlpower.architect.SQLTable;
 import ca.sqlpower.architect.layout.LayoutEdge;
 import ca.sqlpower.architect.swingui.action.EditSpecificIndexAction;
-import ca.sqlpower.architect.swingui.dbtree.DnDTreePathTransferable;
+import ca.sqlpower.architect.swingui.dbtree.SQLObjectSelection;
 import ca.sqlpower.swingui.ColorIcon;
 import ca.sqlpower.swingui.ColourScheme;
 import ca.sqlpower.swingui.SPSUtils;
@@ -703,16 +703,12 @@
DBTree dbtree = pp.getSession().getSourceDatabases(); // XXX: bad
                 int insertionPoint = pointToItemIndex(loc);

- ArrayList<int[]> paths = (ArrayList<int[]>) t.getTransferData(importFlavor); - logger.debug("Importing items from tree: "+paths); //$NON-NLS-1$
-
                 // put the undo event adapter into a drag and drop state
                 pp.startCompoundEdit("Drag and Drop"); //$NON-NLS-1$

- ArrayList<SQLObject> droppedItems = new ArrayList<SQLObject>();
-                for (int[] path : paths) {
- droppedItems.add(DnDTreePathTransferable.getNodeForDnDPath((SQLObject) dbtree.getModel().getRoot(), path));
-                }
+ List<SQLObject> droppedItems = Arrays.asList((SQLObject[]) t.getTransferData(importFlavor));
+
+ logger.debug("Importing items: " + droppedItems); //$NON-NLS-1$

                 boolean success = false;

@@ -812,7 +808,7 @@
logger.debug("isLocalObject = "+flavors[i].getMimeType().equals(DataFlavor.javaJVMLocalObjectMimeType)); //$NON-NLS-1$


- if (flavors[i].equals(DnDTreePathTransferable.TREEPATH_ARRAYLIST_FLAVOR)) { + if (flavors[i].equals(SQLObjectSelection.LOCAL_SQLOBJECT_ARRAY_FLAVOUR)) {
                 logger.debug("YES"); //$NON-NLS-1$
                 return flavors[i];
             }
@@ -1118,26 +1114,10 @@
     }

     public Transferable createTransferableForSelection() {
-        ArrayList<int[]> paths = new ArrayList<int[]>();
-        StringBuilder userVisibleName = new StringBuilder();
-        for (SQLColumn column: getSelectedItems()) {
-
- int[] path = DnDTreePathTransferable.getDnDPathToNode(column, getPlayPen().getSession().getRootObject());
-            if (logger.isDebugEnabled()) {
- logger.debug("Path to dragged node: "+Arrays.toString(path)); //$NON-NLS-1$
-            }
-            // export list of DnD-type tree paths
-            paths.add(path);
-
-            if (userVisibleName.length() != 0) {
-                userVisibleName.append("\n");
-            }
-            userVisibleName.append(column.getName());
-        }
-        if (paths.isEmpty()) {
+        if (getSelectedItems().isEmpty()) {
             return null;
         } else {
- return new DnDTreePathTransferable(paths, userVisibleName.toString()); + return new SQLObjectSelection(new ArrayList<SQLObject>(getSelectedItems()));
         }
     }
 }

Added: trunk/src/ca/sqlpower/architect/swingui/dbtree/SQLObjectSelection.java
==============================================================================
--- (empty file)
+++ trunk/src/ca/sqlpower/architect/swingui/dbtree/SQLObjectSelection.java Tue Dec 16 14:35:17 2008
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Wabit.
+ *
+ * Wabit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Wabit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.dbtree;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.Collection;
+
+import ca.sqlpower.architect.SQLColumn;
+import ca.sqlpower.architect.SQLObject;
+import ca.sqlpower.architect.SQLTable;
+
+/**
+ * A transferable implementation that passes a reference to an array of SQLObjects.
+ */
+public class SQLObjectSelection implements Transferable {
+
+    /**
+ * Data flavour that indicates a JVM-local reference to an array containing
+     * 0 or more SQLObjects.
+     */
+    public static final DataFlavor LOCAL_SQLOBJECT_ARRAY_FLAVOUR =
+        new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
+ "; class=\"[Lca.sqlpower.architect.SQLObject;\"", "Local Array of SQLObject");
+
+    /**
+ * Data flavour that indicates a reference to a string array containing a string
+     * representation of 0 or more SQLObjects.
+     */
+ public static final DataFlavor SQLOBJECT_NAMES = new DataFlavor(String[].class, "List of selected object names");
+
+    /**
+     * These are the actual SQLObjects we're transfering.
+     */
+    private final SQLObject[] sqlObjects;
+
+    /**
+     * These are the names of the SQLObjects we're transfering.
+     */
+    private final String[] sqlObjectNames;
+
+    /**
+     * Creates a new transferable for the given collection of SQLObjects.
+     *
+     * @param sqlObjects
+ * converted to an array in the order the elements are returned
+     *            by the iterator.
+     */
+    public SQLObjectSelection(Collection<SQLObject> sqlObjects) {
+        this(sqlObjects.toArray(new SQLObject[sqlObjects.size()]));
+    }
+
+    /**
+     * Creates a new transferable for the given array of SQLObjects.
+     *
+     * @param sqlObjects
+     *            the exact array that will be returned by
+ * {...@link #getTransferData(DataFlavor)}. Must not be null, but
+     *            can have a length of 0.
+     */
+    public SQLObjectSelection(SQLObject[] sqlObjects) {
+        if (sqlObjects == null) {
+ throw new NullPointerException("Can't transfer a null array. Try an empty one instead!");
+        }
+        this.sqlObjects = sqlObjects;
+        sqlObjectNames = getObjectNames(sqlObjects);
+    }
+
+    public Object getTransferData(DataFlavor flavor)
+            throws UnsupportedFlavorException, IOException {
+        if (flavor == LOCAL_SQLOBJECT_ARRAY_FLAVOUR) {
+            return sqlObjects;
+        } else if (flavor == SQLOBJECT_NAMES) {
+            return sqlObjectNames;
+        } else {
+            throw new UnsupportedFlavorException(flavor);
+        }
+    }
+
+    public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { LOCAL_SQLOBJECT_ARRAY_FLAVOUR, SQLOBJECT_NAMES };
+    }
+
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return (flavor == LOCAL_SQLOBJECT_ARRAY_FLAVOUR || flavor == SQLOBJECT_NAMES);
+    }
+
+    /**
+ * Takes the tree paths to store the names of the SQLObjects into an ArrayList which will be used as a flavor.
+     */
+     private String[] getObjectNames(SQLObject[] objects){
+         String[] nodeNames = new String[objects.length];
+         for (int i = 0; i < objects.length; i++) {
+             if (objects[i] instanceof SQLTable) {
+                 nodeNames[i] = ((SQLTable) objects[i]).toQualifiedName();
+             } else if (objects[i] instanceof SQLColumn) {
+ nodeNames[i] = ((SQLColumn) objects[i]).getParentTable().getName() + "." + ((SQLColumn) objects[i]).getName();
+             } else {
+                 nodeNames[i] = objects[i].getName();
+             }
+         }
+         return nodeNames;
+     }
+
+}

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/DnDOLAPTransferable.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/DnDOLAPTransferable.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/DnDOLAPTransferable.java Tue Dec 16 14:35:17 2008
@@ -33,7 +33,6 @@
 import ca.sqlpower.architect.swingui.PlayPenComponent;
 import ca.sqlpower.architect.swingui.PlayPenContentPane;
 import ca.sqlpower.architect.swingui.PlayPenCoordinate;
-import ca.sqlpower.architect.swingui.dbtree.DnDTreePathTransferable;

public class DnDOLAPTransferable implements Transferable, java.io.Serializable {

Reply via email to