Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.ui / src / main / java / org / gvsig / gui / beans / controls / dnd / JDnDTable.java @ 40561

History | View | Annotate | Download (10.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/* CVS MESSAGES:
25
*
26
* $Id: JDnDTable.java 13655 2007-09-12 16:28:55Z bsanchez $
27
* $Log$
28
* Revision 1.3  2007-09-12 16:28:23  bsanchez
29
* *** empty log message ***
30
*
31
* Revision 1.2  2007/08/21 09:56:44  bsanchez
32
* - Variable no usada
33
*
34
* Revision 1.1  2007/08/20 08:34:46  evercher
35
* He fusionado LibUI con LibUIComponents
36
*
37
* Revision 1.1  2006/09/21 16:35:12  jaume
38
* *** empty log message ***
39
*
40
*
41
*/
42
package org.gvsig.gui.beans.controls.dnd;
43

    
44
import java.awt.Component;
45
import java.awt.Point;
46
import java.awt.datatransfer.DataFlavor;
47
import java.awt.datatransfer.StringSelection;
48
import java.awt.datatransfer.Transferable;
49
import java.awt.datatransfer.UnsupportedFlavorException;
50
import java.awt.dnd.DnDConstants;
51
import java.awt.dnd.DragGestureEvent;
52
import java.awt.dnd.DragGestureListener;
53
import java.awt.dnd.DragSource;
54
import java.awt.dnd.DragSourceDragEvent;
55
import java.awt.dnd.DragSourceDropEvent;
56
import java.awt.dnd.DragSourceEvent;
57
import java.awt.dnd.DragSourceListener;
58
import java.awt.dnd.DropTarget;
59
import java.awt.dnd.DropTargetDragEvent;
60
import java.awt.dnd.DropTargetDropEvent;
61
import java.awt.dnd.DropTargetEvent;
62
import java.awt.dnd.DropTargetListener;
63
import java.awt.geom.Point2D;
64
import java.io.IOException;
65
import java.util.ArrayList;
66
import java.util.StringTokenizer;
67

    
68
import javax.swing.JTable;
69
import javax.swing.table.TableCellRenderer;
70
/**
71
 * Preten ser una taula que accepte arrossegar i soltar. Ja mou coses i aix?
72
 * per? encara est? en proves.
73
 *
74
 * La intenci? ?s que pugues moure columnes, per? una volta posats, que moga
75
 * l?nies i cel?les lliurement.
76
 * @author jaume dominguez faus - jaume.dominguez@iver.es
77
 *
78
 */
79
public class JDnDTable extends JTable implements DragSourceListener,
80
                                                                DragGestureListener, DropTargetListener{
81
  private static final long serialVersionUID = -5479369256188567414L;
82
        private CellCoordinates        overCellCoordinates = null;
83
        private DragSource        dragSource;
84
        private CellCoordinates[]        selectedCells;
85
        private boolean        dragging;
86
        private CellCoordinates currSelectedCell;
87
        static final short FREE_CELL_MOVING = -4;
88
        public static final short ONLY_ALLOW_MOVING_ROWS = -2;
89
        public static final short ONLY_ALLOW_MOVING_COLUMNS = -1;
90

    
91

    
92

    
93
        public JDnDTable() {
94
                // Configure ourselves to be a drag source
95
                dragSource = new DragSource();
96
                dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
97

    
98
                // Configure ourselves to be a drop target
99
                new DropTarget(this, this);
100
        }
101

    
102
        public JDnDTable( JDnDTableModel model ) {
103
        super( model );
104
        // Configure ourselves to be a drag source
105
        dragSource = new DragSource();
106
        dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, this);
107

    
108
        // Configure ourselves to be a drop target
109
        new DropTarget( this, this );
110
    }
111

    
112
        public void dragEnter(DragSourceDragEvent dsde) {
113
                Point thisLocation = this.getLocationOnScreen();
114
                Point clickLocation = dsde.getLocation();
115

    
116
                Point2D relativeLocation = new Point2D.Double(
117
                                (clickLocation.getX() - thisLocation.getX()),
118
                                (clickLocation.getY() - thisLocation.getY()));
119

    
120
                this.overCellCoordinates = locationToCellCoord(relativeLocation);
121
        }
122

    
123
        public void setSelectionMode(short mode) {
124
                if (mode == ONLY_ALLOW_MOVING_COLUMNS) {
125
                        setColumnSelectionAllowed(true);
126
                        setRowSelectionAllowed(false);
127
                } else if ( mode == ONLY_ALLOW_MOVING_ROWS) {
128
                        setColumnSelectionAllowed(false);
129
                        setRowSelectionAllowed(true);
130
                }
131
                ((JDnDTableModel) this.getModel()).setSelectionMode(mode);
132
        }
133
        private CellCoordinates locationToCellCoord(Point2D location) {
134

    
135
                int[] ij = new int[2];
136
                int width = (int) location.getX();
137
                int height = (int) location.getY();
138

    
139
                for (int i = 0; i < this.getColumnCount(); i++) {
140
                        int iColumnWidth = this.getColumnModel().getColumn(i).getWidth();
141
                        // it seems to be right, but just in case consideer to use:
142
                        // ? int iColumnWidth = this.getColumnModel().getColumn(i).getPreferredWidth();
143
                        if ((width - iColumnWidth) <= 0) {
144
                                ij[1] = i;
145
                                break;
146
                        }
147
                        width = width - iColumnWidth;
148
                }
149

    
150
                // Get the current default height for all rows
151
        int jRowHeight = this.getRowHeight();
152
                for (int j = 0; j < this.getRowCount(); j++) {
153
                // Determine highest cell in the row
154
                for (int c=0; c<this.getColumnCount(); c++) {
155
                    TableCellRenderer renderer = this.getCellRenderer(j, c);
156
                    Component comp = this.prepareRenderer(renderer, j, c);
157
                    int h = comp.getPreferredSize().height - 2*rowMargin;
158
                    jRowHeight = Math.max(jRowHeight, h);
159
                }
160

    
161
                if ((height - jRowHeight) <= 0) {
162
                        ij[0] = j;
163
                        break;
164
                }
165
                height = height - jRowHeight;
166
                }
167

    
168
                return new CellCoordinates(ij[0], ij[1]);
169
        }
170

    
171

    
172
        public void dragOver(DragSourceDragEvent dsde) {
173
                // TODO Auto-generated method stub
174
        }
175

    
176
        public void dropActionChanged(DragSourceDragEvent dsde) {
177
                // TODO Auto-generated method stub
178
        }
179

    
180
        public void dragDropEnd(DragSourceDropEvent dsde) {
181
                System.out.println("dragDropEnd");
182
                this.dragging = false;
183
        }
184

    
185
        public void dragExit(DragSourceEvent dse) {
186
                this.overCellCoordinates = null;
187
        }
188

    
189
        public void dragGestureRecognized(DragGestureEvent dge) {
190
                // TODO Auto-generated method stub
191
                this.selectedCells = this.getSelectedCells();
192
                Object[] selectedObjects = this.getSelectedValues();
193
                if (selectedObjects.length>0) {
194
                        StringBuffer sb = new StringBuffer();
195
            for( int i=0; i<selectedObjects.length; i++ ) {
196
                sb.append( selectedObjects[ i ].toString() + "\n" );
197
            }
198

    
199
            // Build a StringSelection object that the Drag Source
200
            // can use to transport a string to the Drop Target
201
            StringSelection text = new StringSelection( sb.toString() );
202

    
203
            // Start dragging the object
204
            this.dragging = true;
205
            dragSource.startDrag( dge, DragSource.DefaultMoveDrop, text, this );
206
            System.err.println("Selected objects\n"+sb.toString());
207
                }
208
        }
209

    
210
        private Object[] getSelectedValues() {
211
                ArrayList values = new ArrayList(selectedCells.length);
212
                for (int i = 0; i < selectedCells.length; i++) {
213
                        values.add(this.getValueAt(selectedCells[i].i, selectedCells[i].j));
214
                }
215
                return values.toArray();
216
        }
217

    
218
        private CellCoordinates[] getSelectedCells() {
219
                ArrayList cells = new ArrayList();
220
                for (int i = 0; i < this.getColumnCount(); i++) {
221
                        for (int j = 0; j < this.getRowCount(); j++) {
222
                                if (this.isCellSelected(i, j))
223
                                        cells.add( new CellCoordinates(i,j) );
224
                        }
225
                }
226
                return (CellCoordinates[]) cells.toArray(new CellCoordinates[0]);
227
        }
228

    
229
        public void dragEnter(DropTargetDragEvent dtde) {
230
                // TODO
231
                System.out.println("dragEnter");
232
        }
233

    
234
        public void dragOver(DropTargetDragEvent dtde) {
235
                 // See who we are over...
236
                CellCoordinates overCellCoordinates = this.locationToCellCoord( dtde.getLocation());
237
        if( overCellCoordinates != null && !overCellCoordinates.equals(this.overCellCoordinates) ) {
238
            // If the value has changed from what we were previously over
239
            // then change the selected object to the one we are over; this
240
            // is a visual representation that this is where the drop will occur
241
            this.overCellCoordinates = overCellCoordinates;
242

    
243
            currSelectedCell = this.overCellCoordinates;
244
            System.out.println("Current cell  ["+currSelectedCell.i+","+currSelectedCell.j+"]");
245

    
246
        }
247
        }
248

    
249
        public void dropActionChanged(DropTargetDragEvent dtde) {
250
                // TODO Auto-generated method stub
251
        }
252

    
253
        public void drop(DropTargetDropEvent dtde) {
254
                try {
255
                        Transferable transferable = dtde.getTransferable();
256
                        if( transferable.isDataFlavorSupported( DataFlavor.stringFlavor ) ) {
257
                                dtde.acceptDrop( DnDConstants.ACTION_MOVE );
258

    
259
                                // Find out where the item was dropped
260
                                CellCoordinates newCellCoord = locationToCellCoord(dtde.getLocation());
261

    
262
                                // Get the items out of the transferable object and build an
263
                                // array out of them...
264
                                String s = ( String ) transferable.getTransferData( DataFlavor.stringFlavor );
265
                                StringTokenizer st = new StringTokenizer( s );
266
                                ArrayList items = new ArrayList();
267
                                while( st.hasMoreTokens() ) {
268
                                        items.add( st.nextToken() );
269
                                }
270

    
271
                                JDnDTableModel model = (JDnDTableModel) this.getModel();
272

    
273
                // If we are dragging from our this to our list them move the items,
274
                // otherwise just add them...
275
                if( this.dragging ) {
276
                    //model.itemsMoved( newIndex, items );
277
                    model.itemsMoved( newCellCoord, this.selectedCells );
278
                } else {
279
                    model.insertItems( newCellCoord, items );
280
                }
281

    
282
                // Update the selected cells
283
                /* TODO
284
                int[] newIndicies = new int[ items.size() ];
285
                for( int i=0; i<items.size(); i++ ) {
286
                    newIndicies[ i ] = newIndex + i;
287
                }
288
                this.setSelectedIndices( newIndicies );
289
                */
290
                // Reset the over index
291
                this.overCellCoordinates = null;
292

    
293
                dtde.getDropTargetContext().dropComplete( true );
294
                        } else {
295
                                dtde.rejectDrop();
296
                        }
297
                } catch( IOException exception ) {
298
                        exception.printStackTrace();
299
                        System.err.println( "Exception" + exception.getMessage());
300
                        dtde.rejectDrop();
301
                } catch( UnsupportedFlavorException ufException ) {
302
                        ufException.printStackTrace();
303
                        System.err.println( "Exception" + ufException.getMessage());
304
                        dtde.rejectDrop();
305
                }
306
        }
307

    
308
        public void dragExit(DropTargetEvent dte) {
309
                // TODO Auto-generated method stub
310
                System.out.println("dragExit");
311
        }
312

    
313
}
314

    
315
class CellCoordinates {
316
        int i, j;
317

    
318
        public CellCoordinates(int i, int j) {
319
                this.i = i;
320
                this.j = j;
321
        }
322

    
323
        public boolean equals(Object obj) {
324
                if (!(obj instanceof CellCoordinates))
325
                        return false;
326

    
327
                CellCoordinates other = (CellCoordinates) obj;
328
                return (this.i == other.i) && (this.j == other.j);
329
        }
330
}