Statistics
| Revision:

svn-gvsig-desktop / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / project / documents / view / legend / gui / SymbolTable.java @ 25872

History | View | Annotate | Download (22 KB)

1
/*
2
 * Created on 27-abr-2004
3
 *
4
 * To change the template for this generated file go to
5
 * Window>Preferences>Java>Code Generation>Code and Comments
6
 */
7
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
8
 *
9
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
10
 *
11
 * This program is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU General Public License
13
 * as published by the Free Software Foundation; either version 2
14
 * of the License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
24
 *
25
 * For more information, contact:
26
 *
27
 *  Generalitat Valenciana
28
 *   Conselleria d'Infraestructures i Transport
29
 *   Av. Blasco Ib??ez, 50
30
 *   46010 VALENCIA
31
 *   SPAIN
32
 *
33
 *      +34 963862235
34
 *   gvsig@gva.es
35
 *      www.gvsig.gva.es
36
 *
37
 *    or
38
 *
39
 *   IVER T.I. S.A
40
 *   Salamanca 50
41
 *   46005 Valencia
42
 *   Spain
43
 *
44
 *   +34 963163400
45
 *   dac@iver.es
46
 */
47
package com.iver.cit.gvsig.project.documents.view.legend.gui;
48

    
49
import java.awt.Component;
50
import java.awt.Dimension;
51
import java.awt.GridLayout;
52
import java.awt.Point;
53
import java.awt.Rectangle;
54
import java.awt.event.ActionListener;
55
import java.awt.event.MouseAdapter;
56
import java.awt.event.MouseEvent;
57
import java.util.ArrayList;
58
import java.util.Hashtable;
59
import java.util.Vector;
60

    
61
import javax.swing.JPanel;
62
import javax.swing.JScrollPane;
63
import javax.swing.event.ChangeEvent;
64
import javax.swing.table.DefaultTableModel;
65
import javax.swing.table.TableCellEditor;
66
import javax.swing.table.TableColumn;
67
import javax.swing.table.TableModel;
68

    
69
import com.hardcode.gdbms.engine.values.NullValue;
70
import com.iver.andami.PluginServices;
71
import com.iver.andami.ui.mdiFrame.JMenuItem;
72
import com.iver.andami.ui.mdiFrame.JPopUpMenu;
73
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
74
import com.iver.cit.gvsig.fmap.rendering.NullIntervalValue;
75
import com.iver.cit.gvsig.fmap.rendering.NullUniqueValue;
76
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelClass;
77
import com.iver.cit.gvsig.project.documents.gui.SymbolCellEditor;
78
import com.iver.cit.gvsig.project.documents.gui.TableSymbolCellRenderer;
79
import com.iver.cit.gvsig.project.documents.view.legend.edition.gui.IntervalCellEditor;
80
import com.iver.cit.gvsig.project.documents.view.legend.edition.gui.ValueCellEditor;
81
import com.iver.utiles.swing.jtable.JTable;
82
import com.iver.utiles.swing.jtable.TextFieldCellEditor;
83

    
84
/**
85
 * JPanel que contiene la tabla con los s?mbolos intervalos o valores y
86
 * etiquetado de estos valores.
87
 *
88
 * @author Vicente Caballero Navarro
89
 */
90
public class SymbolTable extends JPanel {
91
    private static final long serialVersionUID = -8694846716328735113L;
92
    private static Hashtable<String,TableCellEditor> cellEditors = new Hashtable<String,TableCellEditor>();
93

    
94
    public static final String VALUES_TYPE = "values";
95
    public static final String INTERVALS_TYPE = "intervals";
96
    private JTable table;
97
    private String type;
98
    private int shapeType;
99
    private OnTableMouseAdapter rightClickActions;
100

    
101
    /**
102
     * Crea un nuevo FSymbolTable.
103
     *
104
     * @param type
105
     *            tipo de valor si es intervalo: "intervals" y si es por
106
     *            valores: "values".
107
     */
108
    public SymbolTable(Component ownerComponent, String type, int shapeType) {
109
        super(new GridLayout(1, 0));
110
        this.type = type;
111
        this.shapeType = shapeType;
112

    
113
        rightClickActions = new OnTableMouseAdapter();
114
        table = new JTable();
115
        table.setModel(new MyTableModel());
116
        table.setPreferredScrollableViewportSize(new Dimension(480, 110));
117

    
118
        initializeCellEditors();
119

    
120
        // Create the scroll pane and add the table to it.
121
        JScrollPane scrollPane = new JScrollPane(table);
122

    
123
        // Set up column sizes.
124
        // initColumnSizes(table);
125
        setUpSymbolColumn(table, table.getColumnModel().getColumn(0));
126

    
127
        if(cellEditors.get(type) == null)
128
            throw new Error("Symbol table type not set!");
129

    
130
        setUpValueColumn(table, table.getColumnModel().getColumn(1),cellEditors.get(this.type));
131
        setUpLabelColumn(table, table.getColumnModel().getColumn(2));
132

    
133
        // Add the scroll pane to this panel.
134
        add(scrollPane);
135
        table.setRowSelectionAllowed(true);
136
        table.addMouseListener(rightClickActions);
137
    }
138
    /**
139
     * Inicializa los valores de los CellEditors que la SymbolTable poseer? por defecto
140
     */
141
    private void initializeCellEditors() {
142
        this.cellEditors.put(this.INTERVALS_TYPE,new IntervalCellEditor());
143
        this.cellEditors.put(this.VALUES_TYPE, new ValueCellEditor());
144
    }
145
    /**
146
     * A?ade un nuevo CellEditor a la lista de disponibles
147
     *
148
     * @param key String con el nombre identificativo del CellEditor
149
     * @param cellEditor CellEditor que va a ser a?adido
150
     */
151
    public static void addCellEditor(String key,TableCellEditor cellEditor ) {
152
        cellEditors.put(key, cellEditor);
153
    }
154
    /**
155
     * Obtiene el valor de los elementos de una fila seleccionada
156
     *
157
     * @return Object[] Array con los objetos de cada una de las columnas de la fila seleccionada
158
     */
159
    public Object[] getSelectedRowElements() {
160
        Object[] values = new Object[3];
161

    
162
        MyTableModel m = (MyTableModel) table.getModel();
163
        int[] selectedRows = table.getSelectedRows();
164

    
165
        if(selectedRows.length != 1)
166
            return null;
167

    
168
        for (int i = 0; i < 3; i++) {
169
            values[i] = m.getValueAt(selectedRows[0], i);
170
        }
171

    
172
        return values;
173
    }
174
    /**
175
     * A?ade una fila al modelo.
176
     *
177
     * @param vector
178
     *            Fila en forma de vector de Object para a?adir al modelo.
179
     */
180
    public void addRow(Object[] vector) {
181
        MyTableModel m = (MyTableModel) table.getModel();
182
        m.addRow(vector);
183

    
184
    }
185

    
186
    /**
187
     * Elimina la fila que tiene como clave el objeto que se pasa como
188
     * par?metro.
189
     *
190
     * @param obj
191
     *            clave del objeto a eliminar.
192
     */
193
    public void removeRow(Object obj) {
194
        MyTableModel m = (MyTableModel) table.getModel();
195

    
196
        for (int i = 0; i < m.getRowCount(); i++) {
197
            if (m.getValueAt(i, 1) instanceof NullUniqueValue
198
                    || m.getValueAt(i, 1) instanceof NullIntervalValue) {
199
                m.removeRow(i);
200
            }
201
        }
202
    }
203

    
204
    /**
205
     * Elimina las filas que est?n seleccionadas.
206
     */
207
    public void removeSelectedRows() {
208
        if (table.getCellEditor() != null) {
209
            table.getCellEditor().cancelCellEditing();
210
        }
211

    
212
        MyTableModel m = (MyTableModel) table.getModel();
213
        int[] selectedRows = table.getSelectedRows();
214

    
215
        for (int i = selectedRows.length - 1; i >= 0; i--) {
216
            m.removeRow(selectedRows[i]);
217
        }
218
    }
219

    
220
    /**
221
     * Rellena la tabla con los s?mbolos valores y descripciones que se pasan
222
     * como par?metro.
223
     *
224
     * @param symbols
225
     *            Array de s?mbolos
226
     * @param values
227
     *            Array de valores.
228
     * @param descriptions
229
     *            Array de descripciones.
230
     */
231
    public void fillTableFromSymbolList(ISymbol[] symbols, Object[] values,
232
            String[] descriptions) {
233
        ISymbol theSymbol;
234

    
235
        for (int i = 0; i < symbols.length; i++) {
236
            theSymbol = symbols[i];
237
            if(!(values[i] instanceof NullIntervalValue) && !(values[i] instanceof NullUniqueValue))
238
                addTableRecord(theSymbol, values[i], descriptions[i]);
239
        }
240
    }
241

    
242
    /**
243
     * A?ade una fila con los objetos que se pasan como par?metros.
244
     *
245
     * @param symbol
246
     *            s?mbolo de la fila.
247
     * @param value
248
     *            Valor de la fila.
249
     * @param description
250
     *            Descripci?n.
251
     */
252
    public void addTableRecord(ISymbol symbol, Object value, String description) {
253
        Object[] theRow = new Object[3];
254
        theRow[0] = symbol;
255
        theRow[1] = value;
256
        theRow[2] = description;
257
        addRow(theRow);
258
    }
259

    
260
    /**
261
     * Devuelve el valor a partie del n?mero de fila y columna.
262
     *
263
     * @param row
264
     *            n?mero de fila.
265
     * @param col
266
     *            n?mero de columna.
267
     *
268
     * @return Objeto.
269
     */
270
    public Object getFieldValue(int row, int col) {
271
        MyTableModel m = (MyTableModel) table.getModel();
272

    
273
        return m.getValueAt(row, col);
274
    }
275

    
276
    /**
277
     * Devuelve el n?mero total de filas que contiene el modelo.
278
     *
279
     * @return N?mero de filas.
280
     */
281
    public int getRowCount() {
282
        MyTableModel m = (MyTableModel) table.getModel();
283

    
284
        return m.getRowCount();
285
    }
286

    
287
    /**
288
     * Elimina todas las filas del modelo.
289
     */
290
    public void removeAllItems() {
291
        table.setModel(new MyTableModel());
292
        setUpSymbolColumn(table, table.getColumnModel().getColumn(0));
293
        setUpValueColumn(table, table.getColumnModel().getColumn(1),cellEditors.get(this.type));
294
        setUpLabelColumn(table, table.getColumnModel().getColumn(2));
295
    }
296

    
297
    /**
298
     * Inicializa el cell editor de tipo descripci?n de la columna que se pasa
299
     * como par?metro.
300
     *
301
     * @param table2
302
     *            Tabla.
303
     * @param column
304
     *            Columna.
305
     */
306
    public void setUpLabelColumn(JTable table2, TableColumn column) {
307
        TextFieldCellEditor labeleditor = new TextFieldCellEditor();
308
        column.setCellEditor(labeleditor);
309
    }
310

    
311
    /**
312
     * Inicializa el cell editor de tipo valor de la columna que se pasa como
313
     * par?metro.
314
     *
315
     * @param table2
316
     *            Tabla.
317
     * @param column
318
     *            Columna.
319
     * @param tableCellEditor
320
     */
321
    public void setUpValueColumn(JTable table2,TableColumn column, TableCellEditor tableCellEditor) {
322
        column.setCellEditor(tableCellEditor);
323
    }
324
    /**
325
     * Inicializa el cell editor de tipo s?mbolo de la columna que se pasa como
326
     * par?metro.
327
     *
328
     * @param table2
329
     *            Tabla.
330
     * @param column
331
     *            Columna.
332
     */
333
    public void setUpSymbolColumn(JTable table2, TableColumn column) {
334
        // Set up the editor
335
        column.setMaxWidth(100);
336
        column.setWidth(60);
337
        column.setPreferredWidth(60);
338
        column.setMinWidth(50);
339

    
340
        // FSymbolCellEditor symboleditor = new FSymbolCellEditor();
341
        SymbolCellEditor symboleditor = new SymbolCellEditor();
342
        column.setCellEditor(symboleditor);
343

    
344
        TableSymbolCellRenderer renderer = new TableSymbolCellRenderer(true);
345
        column.setCellRenderer(renderer);
346
    }
347

    
348
    public int[] getSelectedRows(){
349
            return table.getSelectedRows();
350
    }
351

    
352
    public void moveDownRows(int startPos, int endPos, int numOfElements) {
353
            if(startPos > endPos)
354
                    return;
355
            if(startPos >= getRowCount()-1 )
356
                    return;
357
            if(startPos == getRowCount()-1)
358
                    return;
359

    
360
            Object[][] values = new Object[getRowCount()][3];
361
        for (int i = 0; i < getRowCount(); i++) {
362
                        values[i][0] = table.getModel().getValueAt(i,0);
363
                        values[i][1] = table.getModel().getValueAt(i,1);
364
                        values[i][2] = table.getModel().getValueAt(i,2);
365
                }
366

    
367
        Object[][]aux = new Object[numOfElements][3];
368
        for (int i = 0; i < numOfElements; i++) {
369

    
370
                aux[numOfElements - i - 1][0] = values[startPos - i][0];
371
                aux[numOfElements - i - 1][1] = values[startPos - i][1];
372
                aux[numOfElements - i - 1][2] = values[startPos - i][2];
373
                }
374

    
375
        Object [][] targetVal = {{values[endPos][0],values[endPos][1],values[endPos][2]}};
376

    
377
        values[startPos - numOfElements + 1][0] = targetVal[0][0];
378
        values[startPos - numOfElements + 1][1] = targetVal[0][1];
379
        values[startPos - numOfElements + 1][2] = targetVal[0][2];
380

    
381
        for (int i = 0; i < numOfElements; i++) {
382
                values[endPos - i][0] = aux[numOfElements - i - 1][0];
383
                values[endPos - i][1] = aux[numOfElements - i - 1][1];
384
                values[endPos - i][2] = aux[numOfElements - i - 1][2];
385
                }
386

    
387
        ISymbol[] symbols = new ISymbol[getRowCount()];
388
        Object[] objects = new Object[getRowCount()];
389
        String[] cads = new String[getRowCount()];
390

    
391
        for (int i = 0; i < getRowCount(); i++) {
392
                        symbols[i] = (ISymbol) values[i][0];
393
                        objects[i] = values[i][1];
394
                        cads[i] = (String) values[i][2];
395
                }
396

    
397
        removeAllItems();
398
        fillTableFromSymbolList(symbols,objects,cads);
399
            table.addRowSelectionInterval(endPos-numOfElements+1,endPos);
400
    }
401

    
402

    
403
    public void moveUpRows(int startPos, int endPos, int numOfElements) {
404

    
405
            if(startPos == 0)
406
                    return;
407
            if(endPos > startPos)
408
                    return;
409

    
410

    
411
        Object[][] values = new Object[getRowCount()][3];
412
        for (int i = 0; i < getRowCount(); i++) {
413
                        values[i][0] = table.getModel().getValueAt(i,0);
414
                        values[i][1] = table.getModel().getValueAt(i,1);
415
                        values[i][2] = table.getModel().getValueAt(i,2);
416
                }
417

    
418
        Object[][]aux = new Object[numOfElements][3];
419
        for (int i = 0; i < numOfElements; i++) {
420

    
421
                aux[i][0] = values[startPos + i][0];
422
                aux[i][1] = values[startPos + i][1];
423
                aux[i][2] = values[startPos + i][2];
424
                }
425

    
426
        Object [][] targetVal = {{values[endPos][0],values[endPos][1],values[endPos][2]}};
427

    
428
        values[startPos + numOfElements - 1][0] = targetVal[0][0];
429
        values[startPos + numOfElements - 1][1] = targetVal[0][1];
430
        values[startPos + numOfElements - 1][2] = targetVal[0][2];
431

    
432
        for (int i = 0; i < numOfElements; i++) {
433

    
434
                values[endPos + i][0] = aux[i][0];
435
                values[endPos + i][1] = aux[i][1];
436
                values[endPos + i][2] = aux[i][2];
437
                }
438

    
439
        ISymbol[] symbols = new ISymbol[getRowCount()];
440
        Object[] objects = new Object[getRowCount()];
441
        String[] cads = new String[getRowCount()];
442

    
443
        for (int i = 0; i < getRowCount(); i++) {
444
                        symbols[i] = (ISymbol) values[i][0];
445
                        objects[i] = values[i][1];
446
                        cads[i] = (String) values[i][2];
447
                }
448

    
449
        removeAllItems();
450
        fillTableFromSymbolList(symbols,objects,cads);
451
        table.addRowSelectionInterval(endPos,endPos+numOfElements-1);
452
    }
453

    
454

    
455
    /**
456
     * Modelo que propio que se aplica a la tabla.
457
     *
458
     * @author Vicente Caballero Navarro
459
     */
460
    class MyTableModel extends DefaultTableModel {
461
        private static final long serialVersionUID = 1L;
462

    
463
        // AbstractTableModel {
464
        private String[] columnNames = {
465
                PluginServices.getText(this, "Simbolo"),
466
                PluginServices.getText(this, "Valor"),
467
                PluginServices.getText(this, "Etiqueta") };
468

    
469
        /**
470
         * Devuelve el n?mero de columnas.
471
         *
472
         * @return N?mero de columnas.
473
         */
474
        public int getColumnCount() {
475
            return columnNames.length;
476
        }
477

    
478
        /**
479
         * Devuelve el String del valor de la columna.
480
         *
481
         * @param col
482
         *            N?mero de columna.
483
         *
484
         * @return Nombre de la columna.
485
         */
486
        public String getColumnName(int col) {
487
            return columnNames[col];
488
        }
489

    
490
        /**
491
         * JTable uses this method to determine the default renderer/ editor for
492
         * each cell. If we didn't implement this method, then the last column
493
         * would contain text ("true"/"false"), rather than a check box.
494
         */
495
        public Class getColumnClass(int c) {
496
            if (getValueAt(0, c) == null) {
497
                return NullValue.class;
498
            }
499
            return getValueAt(0, c).getClass();
500
        }
501

    
502
        /*
503
         * Don't need to implement this method unless your table's editable.
504
         */
505
        public boolean isCellEditable(int row, int col) {
506
            // Note that the data/cell address is constant,
507
            // no matter where the cell appears onscreen.
508
            // if (col > 0) {
509
            return true;
510
        }
511

    
512
        @Override
513
        public Object getValueAt(int row, int column) {
514
            if(column == 2)
515
                return ((ISymbol)getValueAt(row,0)).getDescription();
516

    
517
            return super.getValueAt(row, column);
518
        }
519

    
520
        @Override
521
        public void setValueAt(Object aValue, int row, int column) {
522

    
523
            if(column == 2){
524
                ISymbol symbol = (ISymbol) getValueAt(row,0);
525
                symbol.setDescription((String) aValue);
526
                setValueAt(symbol,row,0);
527
            }
528

    
529
            super.setValueAt(aValue, row, column);
530
        }
531

    
532
    }
533

    
534
    private class OnTableMouseAdapter extends MouseAdapter {
535

    
536
        private JPopUpMenu menu = new JPopUpMenu();
537

    
538
        // group option
539
        private JMenuItem groupItem = new JMenuItem(
540
                PluginServices.getText(this, "group"));
541
        private ActionListener groupAction = new ActionListener() {
542
            public void actionPerformed(java.awt.event.ActionEvent e) {
543
                hidePopUp();
544
                int[] selectedRows = table.getSelectedRows();
545
                if (selectedRows.length > 1) {
546
                    DefaultTableModel model = (DefaultTableModel) table
547
                            .getModel();
548
                    int theRow = selectedRows[0];
549
                    ISymbol symboToBeApplied = (ISymbol) model.getValueAt(
550
                            theRow, 0);
551
                    String labelToBeApplied = (String) model.getValueAt(
552
                            theRow, 2);
553
                    ArrayList<Object> valuesToBeApplied = new ArrayList<Object>(
554
                            selectedRows.length);
555
                    for (int i = 0; i < selectedRows.length; i++) {
556
                        valuesToBeApplied.add(model.getValueAt(selectedRows[i],
557
                                1));
558
                    }
559

    
560
                    for (int i = selectedRows.length - 1; i > 0; i--) {
561
                        model.removeRow(selectedRows[i]);
562
                    }
563

    
564
                    model.setValueAt(symboToBeApplied, theRow, 0);
565
                    model.setValueAt(labelToBeApplied, theRow, 2);
566
                    table.clearSelection();
567
                    table.doLayout();
568
                }
569
            }
570
        };
571

    
572
        // combine option
573
        private JMenuItem combineItem = new JMenuItem(
574
                PluginServices.getText(this, "combine"));
575
        private ActionListener combineAction = new ActionListener() {
576
            public void actionPerformed(java.awt.event.ActionEvent e) {
577
                hidePopUp();
578
                int[] selectedRows = table.getSelectedRows();
579
                if (selectedRows.length > 1) {
580
                    DefaultTableModel model = (DefaultTableModel) table
581
                            .getModel();
582
                    int theRow = selectedRows[0];
583
                    ISymbol symboToBeApplied = (ISymbol) model.getValueAt(
584
                            theRow, 0);
585
                    String labelToBeApplied = (String) model.getValueAt(
586
                            theRow, 2);
587
                    ArrayList<Object> valuesToBeApplied = new ArrayList<Object>(
588
                            selectedRows.length);
589
                    for (int i = 0; i < selectedRows.length; i++) {
590
                        valuesToBeApplied.add(model.getValueAt(selectedRows[i],
591
                                1));
592
                    }
593

    
594
                    for (int i = selectedRows.length - 1; i > 0; i--) {
595
                        model.removeRow(selectedRows[i]);
596
                    }
597

    
598
                    model.setValueAt(symboToBeApplied, theRow, 0);
599
                    model.setValueAt(labelToBeApplied, theRow, 2);
600
                    table.clearSelection();
601
                    table.doLayout();
602
                }
603
            }
604
        };
605

    
606
        private boolean menuEmpty = false;
607

    
608

    
609
        {
610
            groupItem.addActionListener(groupAction);
611
            if (VALUES_TYPE.equals(type)) {
612
                menu.add(groupItem);
613
            } else if (INTERVALS_TYPE.equals(type)) {
614
                menu.add(combineItem);
615
            } else {
616
                menuEmpty = true;
617
            }
618

    
619
        }
620

    
621
        @Override
622
        public void mouseExited(MouseEvent e) {
623
            // if we click outside the popup menu
624
            if (menu.isVisible()) {
625
                Rectangle tableBounds = table.getBounds();
626
                tableBounds.setLocation(table.getLocationOnScreen());
627
                if (!tableBounds.contains(getClickLocation(e))) {
628
                    hidePopUp();
629
                }
630
            }
631

    
632
        }
633

    
634
        @Override
635
        public void mouseClicked(MouseEvent e) {
636
            super.mouseClicked(e);
637

    
638
            // if we click outside the popup menu
639
            if (menu.isVisible()
640
                    && !menu.getBounds().contains(getClickLocation(e))) {
641
                hidePopUp();
642
            }
643

    
644
            if (e.getButton() == MouseEvent.BUTTON3) {
645
                e.consume();
646
                int[] selectedRows = table.getSelectedRows();
647
                if (selectedRows.length > 0) {
648
                    Point realClickLocation = getClickLocation(e);
649
                    menu.setLocation(realClickLocation);
650
                    showPopUp();
651
                }
652
            }
653

    
654
        }
655

    
656
        private void showPopUp() {
657
            if (!menuEmpty) {
658
                table.setEnabled(false);
659
                table.editingCanceled(new ChangeEvent(table));
660
                menu.setVisible(true);
661
            }
662
        }
663

    
664
        private void hidePopUp() {
665
            if (!menuEmpty ) {
666
                menu.setVisible(false);
667
                table.setEnabled(true);
668
            }
669
        }
670

    
671
        private Point getClickLocation(MouseEvent e) {
672
            Point tableLocation = table.getLocationOnScreen();
673
            Point relativeClickPoint = e.getPoint();
674
            Point realClickLocation = new Point(tableLocation.x
675
                    + relativeClickPoint.x, tableLocation.y
676
                    + relativeClickPoint.y);
677
            return realClickLocation;
678
        }
679

    
680
    }
681

    
682
}