001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ecoinformatics.seek.querybuilder;
031
032import java.awt.Point;
033import java.awt.Rectangle;
034import java.awt.datatransfer.DataFlavor;
035import java.awt.datatransfer.Transferable;
036import java.awt.datatransfer.UnsupportedFlavorException;
037import java.awt.dnd.DnDConstants;
038import java.awt.dnd.DragGestureEvent;
039import java.awt.dnd.DragGestureListener;
040import java.awt.dnd.DragSource;
041import java.awt.dnd.DragSourceContext;
042import java.awt.dnd.DragSourceDragEvent;
043import java.awt.dnd.DragSourceDropEvent;
044import java.awt.dnd.DragSourceEvent;
045import java.awt.dnd.DragSourceListener;
046import java.awt.dnd.DropTarget;
047import java.awt.dnd.DropTargetDragEvent;
048import java.awt.dnd.DropTargetDropEvent;
049import java.awt.dnd.DropTargetEvent;
050import java.awt.dnd.DropTargetListener;
051import java.io.IOException;
052
053import javax.swing.JComponent;
054import javax.swing.RepaintManager;
055import javax.swing.SwingUtilities;
056
057/**
058 * The JList that resides inside the TableFrame. This listens for drops of other
059 * field items to represent a join being made. It does not allow drops from
060 * itself to itself.
061 */
062public class DBTableList extends javax.swing.JList implements
063                DropTargetListener, DragSourceListener, DragGestureListener {
064        protected int mAceptableActions = DnDConstants.ACTION_COPY_OR_MOVE;
065        protected DropTarget mDropTarget = new DropTarget(this, mAceptableActions,
066                        this);
067        protected DragSource mDragSource = DragSource.getDefaultDragSource();
068        protected DataFlavor mDataFlavor = new DataFlavor(DBTableField.class,
069                        "DBTableField");
070        protected DBTableField mDragOverItem = null;
071
072        protected DBTableListCellRenderer mRenderer = new DBTableListCellRenderer();
073
074        protected DBTableListModel mModel = null;
075        protected DBTableJoin mTableJoins = null;
076
077        protected static DBTableList mSrcList = null;
078
079        /**
080         * Constructor with DBTableListModel DataModel
081         * 
082         * @param aDataModel
083         */
084        public DBTableList(DBTableListModel aDataModel)
085
086        {
087                super(aDataModel);
088                mModel = aDataModel;
089                mRenderer.setModel(aDataModel);
090                setCellRenderer(mRenderer);
091                mDragSource.createDefaultDragGestureRecognizer(this, mAceptableActions,
092                                this);
093
094                /*
095                 * MouseListener mouseListener = new MouseAdapter() { public void
096                 * mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) {
097                 * 
098                 * } } }; addMouseListener(mouseListener);
099                 */
100        }
101
102        /**
103         * Sets the Joins object (TODO need to make a listener instead)
104         * 
105         * @param aJoins
106         */
107        public void setJoins(DBTableJoin aJoins) {
108                mTableJoins = aJoins;
109        }
110
111        /**
112         * Dirties the "this" list
113         */
114        protected void dirtyAll() {
115                RepaintManager mgr = RepaintManager.currentManager(this);
116                mgr.markCompletelyDirty(this);
117        }
118
119        /**
120         * Dirties the Root (the TableDesktopPane)
121         */
122        protected void dirtyRoot() {
123                JComponent root = (JComponent) this.getParent();
124                while (root.getClass() != DBTableDesktopPane.class) {
125                        root = (JComponent) root.getParent();
126                }
127                RepaintManager mgr = RepaintManager.currentManager(root);
128                mgr.markCompletelyDirty(root);
129        }
130
131        // --------------------------------------------------------------
132        // ------------------ Drag Source Methods -----------------------
133        // --------------------------------------------------------------
134
135        /**
136         * Clear the selection
137         */
138        public void dragDropEnd(DragSourceDropEvent e) {
139                clearSelection();
140                SwingUtilities.invokeLater(new Runnable() {
141                        public void run() {
142                                dirtyAll();
143                        }
144                });
145
146        }
147
148        /**
149         * Sets the cursor appropriately to whether it can be dropped here
150         */
151        public void dragEnter(DragSourceDragEvent e) {
152                DragSourceContext context = e.getDragSourceContext();
153
154                // intersection of the users selected action, and the source and target
155                // actions
156                int myaction = e.getDropAction();
157                // System.out.println("dragEnter Src- dropAction: "+myaction +
158                // " mAceptableActions "+mAceptableActions +"  "+(((myaction &
159                // mAceptableActions) != 0)));
160
161                if ((myaction & mAceptableActions) != 0) {
162                        context.setCursor(DragSource.DefaultLinkDrop);
163                } else {
164                        context.setCursor(DragSource.DefaultLinkNoDrop);
165                }
166        }
167
168        /**
169         * Sets the cursor
170         */
171        public void dragExit(DragSourceEvent e) {
172                e.getDragSourceContext().setCursor(DragSource.DefaultLinkNoDrop);
173        }
174
175        /**
176         * Do the same as Do the same as dragOver
177         */
178        public void dragOver(DragSourceDragEvent e) {
179                dragEnter(e);
180        }
181
182        /**
183         * stubbed
184         */
185        public void dropActionChanged(DragSourceDragEvent DragSourceDragEvent) {
186        }
187
188        // --------------------------------------------------------------
189        // ------------------ Drag Target Methods -----------------------
190        // --------------------------------------------------------------
191
192        /**
193         * Do the same as dragOver
194         */
195        public void dragEnter(DropTargetDragEvent e) {
196
197                dragOver(e);
198        }
199
200        /**
201         * Clear everything when it is dragged out
202         */
203        public void dragExit(DropTargetEvent dropTargetEvent) {
204                if (mDragOverItem != null) {
205                        mDragOverItem.setDragOver(false);
206                        mDragOverItem = null;
207                }
208                SwingUtilities.invokeLater(new Runnable() {
209                        public void run() {
210                                dirtyAll();
211                        }
212                });
213        }
214
215        /**
216         * On DragOver highlight the appropriate item and save a pointer to it in a
217         * static data member so we know where it will be dropped
218         */
219        public void dragOver(DropTargetDragEvent e) {
220                if (!isDragOk(e) || mSrcList == this) {
221                        e.rejectDrag();
222                        return;
223                }
224
225                Point pnt = e.getLocation();
226                for (int i = 0; i < mModel.getSize(); i++) {
227                        DBTableField dbTableField = (DBTableField) mModel.getElementAt(i);
228
229                        Rectangle rect = dbTableField.getBounds();
230                        if (rect.contains(pnt)) {
231                                if (dbTableField.getName().equals(DBUIUtils.ALL_FIELDS)) {
232                                        e.rejectDrag();
233                                        return;
234                                }
235                                e.acceptDrag(mAceptableActions);
236                                if (mDragOverItem != dbTableField) {
237                                        if (mDragOverItem != null) {
238                                                mDragOverItem.setDragOver(false);
239                                        }
240                                        mDragOverItem = dbTableField;
241                                        mDragOverItem.setDragOver(true);
242                                        SwingUtilities.invokeLater(new Runnable() {
243                                                public void run() {
244                                                        dirtyAll();
245                                                }
246                                        });
247                                }
248                                return;
249                        }
250                }
251        }
252
253        /**
254         * Checks to make sure the action is correct for dropping
255         */
256        private boolean isDragOk(DropTargetDragEvent e) {
257                // System.out.println("isDragOk: "+e.getSourceActions() +
258                // " mAceptableActions "+mAceptableActions +"  "+(((e.getSourceActions()
259                // & mAceptableActions) != 0)));
260                if (!e.isDataFlavorSupported(mDataFlavor)) {
261                        return false;
262                }
263
264                // the actions specified when the source
265                // created the DragGestureRecognizer
266                int sa = e.getSourceActions();
267
268                // we're saying that these actions are necessary
269                if ((sa & mAceptableActions) == 0)
270                        return false;
271
272                return true;
273        }
274
275        /**
276         * stubbed
277         */
278        public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) {
279        }
280
281        /**
282         * Drop craetes a link from one table to the other
283         */
284        public synchronized void drop(DropTargetDropEvent e) {
285                if (mSrcList != this) {
286                        try {
287                                Transferable tr = e.getTransferable();
288                                if (tr.isDataFlavorSupported(mDataFlavor)) {
289                                        e.acceptDrop(mAceptableActions);
290                                        DBTableField dbTableField = (DBTableField) tr
291                                                        .getTransferData(mDataFlavor);
292                                        e.getDropTargetContext().dropComplete(true);
293                                        if (mDragOverItem != null && dbTableField != null) {
294                                                mTableJoins.addJoin(dbTableField, mDragOverItem);
295                                        }
296                                        mDragOverItem = null;
297                                        SwingUtilities.invokeLater(new Runnable() {
298                                                public void run() {
299                                                        dirtyRoot();
300                                                }
301                                        });
302                                        dragExit((DropTargetEvent) null);
303                                        e.dropComplete(true);
304                                        mSrcList = null;
305                                        return;
306                                } else {
307                                        // System.err.println ("Rejected");
308                                }
309                        } catch (IOException io) {
310                                io.printStackTrace();
311
312                        } catch (UnsupportedFlavorException ufe) {
313                                ufe.printStackTrace();
314                        }
315                }
316                e.dropComplete(false);
317                dragExit((DropTargetEvent) null);
318                mSrcList = null;
319        }
320
321        // --------------------------------------------------------------
322        // -------------- DragGestureListener Methods -------------------
323        // --------------------------------------------------------------
324        public void dragGestureRecognized(DragGestureEvent dragGestureEvent) {
325                if (getSelectedIndex() == -1)
326                        return;
327
328                Object obj = getSelectedValue();
329                if (obj == null) {
330                        // Nothing selected, nothing to drag
331                        // System.out.println ("Nothing selected - beep");
332                        getToolkit().beep();
333                } else {
334                        DBTableField dbTableField = (DBTableField) obj;
335                        mSrcList = this;
336                        dragGestureEvent.startDrag(DragSource.DefaultLinkNoDrop,
337                                        dbTableField, this);
338                }
339        }
340}