View Javadoc

1   package org.devaki.nextobjects.ui.workspace.models;
2   /*
3   
4   nextobjects Copyright (C) 2001-2005 Emmanuel Florent
5   
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2 of the License, or (at your
9   option) any later version.
10  
11  This program is distributed in the hope that it will
12  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the GNU General Public License for more details.
15  
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc., 59
18  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  
20  */
21  import java.util.Vector;
22  import java.awt.GridBagConstraints;
23  import java.awt.GridBagLayout;
24  import java.awt.Insets;
25  import java.awt.event.ActionEvent;
26  import java.awt.event.ActionListener;
27  import java.awt.event.KeyAdapter;
28  import java.awt.event.KeyEvent;
29  import java.awt.event.MouseAdapter;
30  import java.awt.event.MouseEvent;
31  import javax.swing.BorderFactory;
32  import javax.swing.JPanel;
33  import javax.swing.JScrollPane;
34  import javax.swing.table.AbstractTableModel;
35  import javax.swing.DefaultListSelectionModel;
36  import javax.swing.table.JTableHeader;
37  import javax.swing.table.TableColumnModel;
38  import org.devaki.nextobjects.constants.CstImages;
39  import org.devaki.nextobjects.ui.components.CustomButton;
40  import org.devaki.nextobjects.ui.components.CustomTable;
41  import org.devaki.nextobjects.workspace.models.Property;
42  /***
43   * This class provide a jtable representing columns a set of property
44   *
45   * @author <a href="mailto:eflorent@devaki.org">Emmanuel Florent</a>
46   */
47  public class PropertyEdit extends JPanel
48  {
49      /***
50       * Selected row in the jTable
51       */
52      private int selectedRow = -1;
53      /***
54       * The previous (UP) button
55       */
56      private CustomButton jButtonPrevious =
57          new CustomButton(CstImages.ICN_UP, "Move the selected field up", true);
58      /***
59       * The next (DOWN) button
60       */
61      private CustomButton jButtonNext =
62          new CustomButton(
63              CstImages.ICN_DOWN,
64              "Move the selected field down",
65              true);
66      /***
67       * The remove button
68       */
69      private CustomButton jButtonRemove =
70          new CustomButton("Remove", "Remove the selected field", true, false);
71      /***
72       * The new button
73       */
74      private CustomButton jButtonNew =
75          new CustomButton("New", "Create a new field", true, false);
76      /***
77       * The table for columns
78       */
79      private CustomTable jTableProperties =
80          new CustomTable(
81              false,
82              DefaultListSelectionModel.SINGLE_SELECTION,
83              false,
84              false);
85      /***
86       * The table model
87       */
88      private ObjectPropertyTableModel model = new ObjectPropertyTableModel();
89      /***
90       * Constructor
91       *
92       */
93      public PropertyEdit()
94      {
95          super(new GridBagLayout());
96          // Define table model
97          this.jTableProperties.setModel(this.model);
98          // Set tool tips for the table header
99          this.jTableProperties.setTableHeader(
100             new ToolTipHeader(this.jTableProperties.getColumnModel()));
101         // Fix columns width
102         this.setColumnsWidth();
103         // 'jPanelGeneralFields'
104         this.add(
105             new JScrollPane(this.jTableProperties),
106             new GridBagConstraints(
107                 0,
108                 0,
109                 5,
110                 1,
111                 1.0,
112                 1.0,
113                 GridBagConstraints.CENTER,
114                 GridBagConstraints.BOTH,
115                 new Insets(5, 5, 0, 5),
116                 0,
117                 0));
118         this.add(
119             this.jButtonNew,
120             new GridBagConstraints(
121                 0,
122                 1,
123                 1,
124                 1,
125                 0.0,
126                 0.0,
127                 GridBagConstraints.CENTER,
128                 GridBagConstraints.NONE,
129                 new Insets(5, 5, 5, 5),
130                 0,
131                 0));
132         this.add(
133             this.jButtonRemove,
134             new GridBagConstraints(
135                 1,
136                 1,
137                 1,
138                 1,
139                 0.0,
140                 0.0,
141                 GridBagConstraints.CENTER,
142                 GridBagConstraints.NONE,
143                 new Insets(5, 0, 5, 5),
144                 0,
145                 0));
146         this.add(
147             this.jButtonPrevious,
148             new GridBagConstraints(
149                 2,
150                 1,
151                 1,
152                 1,
153                 1.0,
154                 0.0,
155                 GridBagConstraints.EAST,
156                 GridBagConstraints.NONE,
157                 new Insets(5, 0, 5, 5),
158                 0,
159                 0));
160         this.add(
161             this.jButtonNext,
162             new GridBagConstraints(
163                 3,
164                 1,
165                 1,
166                 1,
167                 0.0,
168                 0.0,
169                 GridBagConstraints.CENTER,
170                 GridBagConstraints.NONE,
171                 new Insets(5, 0, 5, 5),
172                 0,
173                 0));
174         // Define table model
175         this.jTableProperties.setModel(this.model);
176         // Set tool tips for the table header
177         this.jTableProperties.setTableHeader(
178             new ToolTipHeader(this.jTableProperties.getColumnModel()));
179         // Fix columns width
180         //this.setColumnsWidth();
181         this.jButtonPrevious.addActionListener(new ActionListener()
182         {
183             // When calling 'jButtonPrevious', invert the current field with the
184             // previous field in 'jTableField'
185             public final void actionPerformed(final ActionEvent e)
186             {
187                 // It can be done, only if the current field is not the first in
188                 // 'jTableField'
189                 if (selectedRow > 0)
190                 {
191                     model.insertProperty(
192                         (Property) model.getProperties().elementAt(
193                             selectedRow - 1),
194                         selectedRow + 1);
195                     model.removeField(selectedRow - 1);
196                     jTableProperties.setSelectedRow(--selectedRow);
197                 }
198             }
199         });
200         this.jButtonNext.addActionListener(new ActionListener()
201         {
202             // When calling 'jButtonNext', invert the current field with
203             // the next field in 'jTableField'
204             public final void actionPerformed(final ActionEvent e)
205             {
206                 // It can be done, only if the current field is not the last in
207                 // 'jTableField' and that it is different from -1
208                 if ((selectedRow > -1)
209                     && (selectedRow < (jTableProperties.getRowCount() - 1)))
210                 {
211                     model.insertProperty(
212                         (Property) model.getProperties().elementAt(selectedRow),
213                         selectedRow + 2);
214                     model.removeField(selectedRow);
215                     jTableProperties.setSelectedRow(++selectedRow);
216                 }
217             }
218         });
219         this.jButtonRemove.addActionListener(new ActionListener()
220         {
221             // When calling 'jButtonRemove', remove the current field
222             public final void actionPerformed(final ActionEvent e)
223             {
224                 model.removeField(selectedRow);
225                 // If the removed field was in first position and that there is
226                 //  always fields, set 'selectedRow' to zero
227                 if ((jTableProperties.getRowCount() > 0) && (selectedRow == 0))
228                 {
229                     jTableProperties.setSelectedRow(0);
230                 }
231                 // Else decrement 'selectedRow' and apply it to 'jTableField'
232                 else
233                 {
234                     jTableProperties.setSelectedRow(--selectedRow);
235                 }
236                 // FIX : Reset the columns width due to an unknow resize call
237                 //setColumnsWidth();
238                 // Disable 'jButtonRemove' if there is no selected row
239                 if (selectedRow == -1)
240                 {
241                     jButtonRemove.setEnabled(false);
242                 }
243             }
244         });
245         this.jButtonNew.addActionListener(new ActionListener()
246         {
247             // When calling 'jButtonNew', add a field
248             public final void actionPerformed(final ActionEvent e)
249             {
250                 // Create a new 'Property' object
251                 Property dep = new Property("", "");
252                 // Add it to 'jTableField'
253                 model.addProperty(dep);
254                 // Update 'selectedRow'
255                 selectedRow = jTableProperties.getRowCount() - 1;
256                 // Set the selected field in 'jTableField'
257                 jTableProperties.setSelectedRow(selectedRow);
258                 // Enable 'jButtonRemove'
259                 jButtonRemove.setEnabled(true);
260             }
261         });
262         // MOUSE
263         this.jTableProperties.addMouseListener(new MouseAdapter()
264         {
265             // When clicking on 'jTableField'...
266             public final void mouseClicked(final MouseEvent e)
267             {
268                 // Set 'selectedRow'
269                 selectedRow = jTableProperties.getSelectedRow();
270                 // Enable 'jButtonRemove'
271                 jButtonRemove.setEnabled(true);
272             }
273         });
274         // KEY
275         this.jTableProperties.addKeyListener(new KeyAdapter()
276         {
277             // When selecting a row of 'jTableField' using the keyboard...
278             public final void keyReleased(final KeyEvent e)
279             {
280                 // Set 'selectedRow'
281                 selectedRow = jTableProperties.getSelectedRow();
282                 // Enable 'jButtonRemove'
283                 jButtonRemove.setEnabled(true);
284             }
285         });
286         this.setBorder(BorderFactory.createTitledBorder("Properties"));
287         // Fix columns width
288         this.setColumnsWidth();
289     }
290     /***
291      * Unused: Cancel edition if 'DataDictionaryEdit' was
292      * edited in its previous call
293      */
294     public final void cancelCellEditing()
295     {
296         if (this.jTableProperties.isEditing())
297         {
298             int tmpInt1 = this.jTableProperties.getEditingRow();
299             int tmpInt2 = this.jTableProperties.getEditingColumn();
300             this
301                 .jTableProperties
302                 .getCellEditor(tmpInt1, tmpInt2)
303                 .cancelCellEditing();
304         }
305     }
306     /***
307      * Reset 'jTableField' columns width
308      */
309     private void setColumnsWidth()
310     {
311         for (int i = 0; i < this.model.getColumnCount(); i++)
312         {
313             this.jTableProperties.getColumnModel().getColumn(
314                 i).setPreferredWidth(
315                 this.model.getColumnSize(i));
316         }
317     }
318     /***
319      * Sorts entire array
320      * @param array the array
321      */
322     public static final void sort(final Vector array)
323     {
324         sort(array, 0, array.size() - 1);
325     }
326     /***
327      * Sorts partial array
328      * @param array the array
329      * @param start start
330      * @param end end
331      */
332     public static final void sort(
333         final Vector array,
334         final int start,
335         final int end)
336     {
337         int p;
338         if (end > start)
339         {
340             p = partition(array, start, end);
341             sort(array, start, p - 1);
342             sort(array, p + 1, end);
343         }
344     }
345     /***
346      * conpare
347      * @param a string
348      * @param b second string
349      * @return compare
350      */
351     protected static int compare(final String a, final String b)
352     {
353         return a.compareTo(b);
354     }
355     /***
356      * oartition
357      * @param array array
358      * @param start start
359      * @param end end
360      * @return partion
361      */
362     protected static int partition(
363         final Vector array,
364         final int start,
365         final int end)
366     {
367         int left, right;
368         String partitionElement;
369         // Arbitrary partition start...there are better ways...
370         partitionElement = ((Property) array.elementAt(end)).getName();
371         left = start - 1;
372         right = end;
373         for (;;)
374         {
375             while (compare(partitionElement,
376                 ((Property) array.elementAt(++left)).getName())
377                 == 1)
378             {
379                 if (left == end)
380                 {
381                     break;
382                 }
383             }
384             while (compare(partitionElement,
385                 ((Property) array.elementAt(--right)).getName())
386                 == -1)
387             {
388                 if (right == start)
389                 {
390                     break;
391                 }
392             }
393             if (left >= right)
394             {
395                 break;
396             }
397             swap(array, left, right);
398         }
399         swap(array, left, end);
400         return left;
401     }
402     /***
403      * swap elements
404      * @param array array
405      * @param i from
406      * @param j to
407      */
408     protected static void swap(final Vector array, final int i, final int j)
409     {
410         Object temp;
411         temp = array.elementAt(i);
412         array.setElementAt(array.elementAt(j), i);
413         array.setElementAt(temp, j);
414     }
415     /***
416      * set the object table model
417      * @param pModel the object table model
418      */
419     public final void setModel(final ObjectPropertyTableModel pModel)
420     {
421         this.model = pModel;
422     }
423     /***
424      * get the object table model
425      * @return object table model
426      */
427     public final ObjectPropertyTableModel getModel()
428     {
429         return model;
430     }
431     /***
432      * Define a cell editor for the Code column
433      * This class define a model to edit the object columns
434      */
435     public final class ObjectPropertyTableModel extends AbstractTableModel
436     {
437         /*** The data stored to be restored with cancel button */
438         private Vector oldData = new Vector();
439         /***
440          * The column name
441          */
442         private final String[] columnNames = { "name", "value" };
443         /***
444          * The column class/types
445          */
446         private final Class[] columnClasses = { String.class, String.class };
447         /***
448          * The column size
449          */
450         private final int[] columnSizes = { 245, 248 };
451         /***
452          * The columns
453          */
454         private Vector properties = new Vector(1);
455         /***
456          * Return the data contained in the JTable
457          * @return colums
458          */
459         public final Vector getProperties()
460         {
461             return properties;
462         }
463         /***
464          * Reset the TableModel to its old values
465          */
466         public final void resetProperties()
467         {
468             cancelCellEditing();
469             this.properties = new Vector(oldData);
470         }
471         /***
472          * Set data in the JTable
473          * @param pData the columns
474          */
475         public final void setProperties(final Vector pData)
476         {
477             // store the old data
478             oldData.removeAllElements();
479             for (int i = 0; i < pData.size(); i++)
480             {
481                 oldData.addElement(new Property("", ""));
482             }
483             //fix the new data.
484             this.properties = new Vector(pData);
485             sort(properties);
486         }
487         /***
488          * Add a field
489          * @param pProperty the column
490          */
491         public final void addProperty(final Property pProperty)
492         {
493             this.properties.addElement(pProperty);
494             this.fireTableRowsInserted(
495                 this.properties.size() - 1,
496                 this.properties.size() - 1);
497         }
498         /***
499          * Add a field at a particular index
500          * @param pProperty the column
501          * @param i index
502          */
503         public final void insertProperty(final Property pProperty, final int i)
504         {
505             this.properties.insertElementAt(pProperty, i);
506             this.fireTableRowsInserted(
507                 this.properties.size() - 1,
508                 this.properties.size() - 1);
509         }
510         /***
511          * Remove a field at a particular index
512          * @param i index
513          */
514         public final void removeField(final int i)
515         {
516             if (i >= 0 && i < properties.size())
517             {
518                 this.properties.removeElementAt(i);
519                 this.fireTableRowsDeleted(
520                     this.properties.size() - 1,
521                     this.properties.size() - 1);
522             }
523         }
524         /***
525          * Return the number of columns
526          * @return count
527          */
528         public final int getColumnCount()
529         {
530             return this.columnNames.length;
531         }
532         /***
533          * Return the number of lines
534          * @return the count of row, number of columns.
535          */
536         public final int getRowCount()
537         {
538             return this.properties.size();
539         }
540         /***
541          * Return the name of the column at the specified index
542          * @param i index
543          * @return column
544          */
545         public final String getColumnName(final int i)
546         {
547             return this.columnNames[i];
548         }
549         /***
550          * Return the class of the column at the specified index
551          * @param i index
552          * @return class
553          */
554         public final Class getColumnClass(final int i)
555         {
556             return this.columnClasses[i];
557         }
558         /***
559          * Return the size of the column at the specified index
560          * @param i index
561          * @return the size
562          */
563         public final int getColumnSize(final int i)
564         {
565             return this.columnSizes[i];
566         }
567         /***
568          * Return the value at the specified row and column
569          * @param row row index
570          * @param col column index
571          * @return the value
572          */
573         public final Object getValueAt(final int row, final int col)
574         {
575             Property newProperty = (Property) properties.elementAt(row);
576             switch (col)
577             {
578                 case 0 :
579                     return newProperty.getName();
580                 case 1 :
581                     return newProperty.getValue();
582                 default :
583                     return null;
584             }
585         }
586         /***
587          * Set the specified value at the specified row and column
588          * @param value value
589          * @param row row index
590          * @param col column index
591          */
592         public final void setValueAt(
593             final Object value,
594             final int row,
595             final int col)
596         {
597             Property newProperty = (Property) properties.elementAt(row);
598             switch (col)
599             {
600                 case 0 :
601                     if (value.toString().length() != 0)
602                     {
603                         newProperty.setName(value.toString());
604                     }
605                     break;
606                 case 1 :
607                     newProperty.setValue(value.toString());
608                     break;
609             }
610             // Replace the previous element
611             this.properties.setElementAt(newProperty, row);
612             this.fireTableDataChanged();
613             // Set the selected row for the jTableField
614             jTableProperties.setSelectedRow(row);
615         }
616         /***
617          * Return that every cell is editable
618          * @param row row index
619          * @param col column index
620          * @return is editable
621          */
622         public final boolean isCellEditable(final int row, final int col)
623         {
624             return true;
625         }
626     } // End of class 'EntityFieldTableModel'
627     /***
628      * Define the tooltips of the 'jTableField' header
629      */
630     private class ToolTipHeader extends JTableHeader
631     {
632         /***
633          * The tooltips
634          */
635         private String[] toolTips =
636             { "Name of the app-property", "Value of the app-property." };
637         /***
638         * Construct a new 'ToolTipHeader' object
639         * @param pModel the TableColumnModel
640         */
641         public ToolTipHeader(final TableColumnModel pModel)
642         {
643             super(pModel);
644         }
645         /***
646          * Return the tool tip depending on the mouse cursor position
647          * @param e the event
648          * @return the tooltip
649          */
650         public final String getToolTipText(final MouseEvent e)
651         {
652             int col = this.columnAtPoint(e.getPoint());
653             int modelCol = this.getTable().convertColumnIndexToModel(col);
654             return toolTips[modelCol];
655         }
656     }
657 }