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.DropTarget;
039import java.awt.dnd.DropTargetDragEvent;
040import java.awt.dnd.DropTargetDropEvent;
041import java.awt.dnd.DropTargetEvent;
042import java.awt.dnd.DropTargetListener;
043import java.io.IOException;
044
045import javax.swing.RepaintManager;
046import javax.swing.SwingUtilities;
047
048import org.kepler.objectmanager.data.db.DSSchemaIFace;
049
050/**
051 * This class is used to draw the nested where clause. The needs all the items
052 * in a linar vector. But the where object is really a nested object tree. Also,
053 * each operator needs to have a terminating node be displayed, which a problem
054 * because the terminator really isn't in the model
055 */
056public class DBWhereList extends javax.swing.JList implements
057                DropTargetListener {
058        protected DBWhereModel mModel = null;
059        protected DSSchemaIFace mSchema = null;
060
061        protected int mAceptableActions = DnDConstants.ACTION_COPY_OR_MOVE;
062        protected DBWhereListCellRenderer mRenderer = new DBWhereListCellRenderer();
063        protected DropTarget mDropTarget = new DropTarget(this, mAceptableActions,
064                        this);
065        protected DataFlavor mDataFlavor = new DataFlavor(DBTableField.class,
066                        "DBTableField");
067        protected DBWhereIFace mDragOverItem = null;
068
069        /**
070         * Constructor with DBWhereModel DataModel
071         * 
072         * @param aDataModel
073         */
074        public DBWhereList(DSSchemaIFace aSchema, DBWhereModel aDataModel) {
075                super(aDataModel);
076                mModel = aDataModel;
077                mSchema = aSchema;
078                setCellRenderer(mRenderer);
079        }
080
081        /**
082         * Dirties the "this" list
083         * 
084         */
085        protected void dirtyAll() {
086                RepaintManager mgr = RepaintManager.currentManager(this);
087                mgr.markCompletelyDirty(this);
088        }
089
090        /**
091         * Dirties the Root (the TableDesktopPane)
092         */
093        protected void dirtyRoot() {
094                RepaintManager mgr = RepaintManager.currentManager(this);
095                mgr.markCompletelyDirty(this);
096
097        }
098
099        // --------------------------------------------------------------
100        // ------------------ Drag Target Methods -----------------------
101        // --------------------------------------------------------------
102        /**
103   *
104   */
105        public void dragEnter(DropTargetDragEvent e) {
106                dragOver(e);
107        }
108
109        /**
110         * update to remove and highlighted item rendering
111         */
112        public void dragExit(DropTargetEvent dropTargetEvent) {
113                if (mDragOverItem != null) {
114                        mDragOverItem.setDragOver(false);
115                        mDragOverItem = null;
116                }
117                SwingUtilities.invokeLater(new Runnable() {
118                        public void run() {
119                                dirtyAll();
120                        }
121                });
122        }
123
124        /**
125         * Make sure the right item is highlighted
126         */
127        public void dragOver(DropTargetDragEvent e) {
128                if (!isDragOk(e)) {
129                        e.rejectDrag();
130                        return;
131                }
132
133                Point pnt = e.getLocation();
134                for (int i = 0; i < mModel.getSize(); i++) {
135                        DBWhereIFace whereCell = (DBWhereIFace) mModel.getElementAt(i);
136
137                        Rectangle rect = whereCell.getBounds();
138                        if (rect.contains(pnt)) {
139                                e.acceptDrag(mAceptableActions);
140                                if (mDragOverItem != whereCell) {
141                                        if (mDragOverItem != null) {
142                                                mDragOverItem.setDragOver(false);
143                                        }
144
145                                        boolean isOK = true;
146                                        if (whereCell.isOperator()
147                                                        && whereCell instanceof DBWhereOperator) {
148                                                if (((DBWhereOperator) mModel.getElementAt(0))
149                                                                .getClosure() == whereCell) {
150                                                        isOK = false;
151                                                }
152                                        }
153
154                                        mDragOverItem = whereCell;
155                                        mDragOverItem.setDragOver(isOK);
156
157                                        SwingUtilities.invokeLater(new Runnable() {
158                                                public void run() {
159                                                        dirtyAll();
160                                                }
161                                        });
162                                }
163                                return;
164                        }
165                }
166        }
167
168        /**
169         * Indicates whether a drop can happen
170         * 
171         * @param e
172         *       */
173        private boolean isDragOk(DropTargetDragEvent e) {
174                if (!e.isDataFlavorSupported(mDataFlavor)) {
175                        return false;
176                }
177
178                // the actions specified when the source
179                // created the DragGestureRecognizer
180                int sa = e.getSourceActions();
181
182                // we're saying that these actions are necessary
183                if ((sa & mAceptableActions) == 0)
184                        return false;
185
186                return true;
187        }
188
189        /**
190   *
191   */
192        public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) {
193        }
194
195        /*
196         * protected boolean isOKToDropOnOper(DBWhereOperator aOper) { if
197         * (aOper.isClosure()) { for (Enumeration e = tables.elements();
198         * e.hasMoreElements();) { DBWhereIFace item =
199         * (DBWhereIFace)e.nextElement(); if (item.isOperator() && item instanceof
200         * DBWhereOperator) { DBWhereOperator oper = (DBWhereOperator)item; if
201         * (oper.isClosure() && oper.getClosure() == aOper) { } if
202         * (aOper.getStartClose().getParent() == null) { return false; }
203         * 
204         * } return true; }
205         */
206
207        /**
208         * Allows the drop from the table frame (JList) Checks to see if there was
209         * already some items there (mDragOverItem) and it will insert it below the
210         * item. The import part is figuring out who the parent is in order for it
211         * to get inserts correctly.
212         */
213        public synchronized void drop(DropTargetDropEvent e) {
214                try {
215                        Transferable tr = e.getTransferable();
216                        if (tr.isDataFlavorSupported(mDataFlavor)) {
217                                e.acceptDrop(mAceptableActions);
218                                DBTableField dbTableField = (DBTableField) tr
219                                                .getTransferData(mDataFlavor);
220                                e.getDropTargetContext().dropComplete(true);
221                                if (dbTableField != null) {
222                                        DBWhereOperator oper = null;
223                                        if (mDragOverItem != null) {
224                                                DBWhereIFace parent = mDragOverItem;
225                                                if (!(parent instanceof DBWhereOperator)) {
226                                                        parent = parent.getParent();
227                                                }
228
229                                                if (parent instanceof DBWhereOperator) {
230                                                        if (((DBWhereOperator) mModel.getElementAt(0))
231                                                                        .getClosure() != (DBWhereOperator) parent) {
232                                                                oper = (DBWhereOperator) parent;
233                                                        }
234                                                }
235                                        }
236
237                                        if ((oper == null && mModel.getSize() == 0 || oper != null)) {
238                                                DBWhereCondition cond = new DBWhereCondition(oper,
239                                                                dbTableField.getTable().getName(), dbTableField
240                                                                                .getName(), dbTableField.getDataType());
241                                                cond.setDepth(oper != null ? oper.getDepth() + 1 : 1);
242                                                int inx = mModel.add(cond);
243                                                this.setSelectedIndex(inx);
244                                                mModel.fireContentsChanged();
245                                        }
246
247                                        // mModel.fireContentsChanged();
248                                        if (mDragOverItem != null) {
249                                                mDragOverItem.setDragOver(false);
250                                        }
251                                }
252                                mDragOverItem = null;
253                                SwingUtilities.invokeLater(new Runnable() {
254                                        public void run() {
255                                                dirtyRoot();
256                                        }
257                                });
258                                dragExit((DropTargetEvent) null);
259                                e.dropComplete(true);
260                                return;
261                        } else {
262                                // System.err.println ("Rejected");
263                        }
264                } catch (IOException io) {
265                        io.printStackTrace();
266
267                } catch (UnsupportedFlavorException ufe) {
268                        ufe.printStackTrace();
269                }
270                e.dropComplete(false);
271                dragExit((DropTargetEvent) null);
272        }
273
274}