001    package jigcell.compare.views;
002    
003    import java.awt.BorderLayout;
004    import java.awt.Point;
005    import java.awt.event.MouseEvent;
006    import java.awt.event.MouseListener;
007    import javax.swing.JPopupMenu;
008    import javax.swing.JScrollPane;
009    import javax.swing.ListSelectionModel;
010    import javax.swing.event.ListSelectionEvent;
011    import javax.swing.event.ListSelectionListener;
012    import jigcell.compare.impl.ClipboardDataSource;
013    import jigcell.compare.impl.Compare;
014    import jigcell.compare.impl.DataManager;
015    import jigcell.compare.impl.PrinterDataSource;
016    import jigcell.compare.ui.BasicTable;
017    import jigcell.compare.ui.CompareFrontEnd;
018    import jigcell.compare.ui.DataEditorPanelTab;
019    import jigcell.compare.ui.FindAccessory;
020    import jigcell.compare.ui.IBasicTableHost;
021    import jigcell.compare.ui.IColumnSelectionTab;
022    import jigcell.compare.ui.INameFinderTab;
023    import jigcell.compare.ui.IRowSelectionTab;
024    import jigcell.compare.ui.InterfaceBuilder;
025    
026    /**
027     * A default implementation for displaying data in a table.
028     *
029     * <p>
030     * This code is licensed under the DARPA BioCOMP Open Source License.  See LICENSE for more details.
031     * </p>
032     *
033     * @author Nicholas Allen
034     */
035    
036    public abstract class BasicTableView extends DataEditorPanelTab implements IBasicTableHost, INameFinderTab, ListSelectionListener,
037       MouseListener {
038    
039       /**
040        * Resource key for last table selection
041        */
042    
043       public final static String RESOURCE_LASTTABLESELECTION = "jigcell_last_table_selection";
044    
045       /**
046        * Resource key for table selection
047        */
048    
049       public final static String RESOURCE_TABLESELECTION = "jigcell_table_selection";
050    
051       /**
052        * Name of default popup
053        */
054    
055       protected final static String POPUP_DEFAULT = "default";
056    
057       /**
058        * Display
059        */
060    
061       protected BasicTable table;
062    
063       /**
064        * Data model
065        */
066    
067       protected BasicTable.BasicTableModel model;
068    
069       /**
070        * Clipboard to use
071        */
072    
073       protected ClipboardDataSource clipboard;
074    
075       /**
076        * Context menu
077        */
078    
079       protected JPopupMenu popup;
080    
081       /**
082        * Location of last popup invocation
083        */
084    
085       protected Point popupPoint;
086    
087       /**
088        * Printer to use
089        */
090    
091       protected PrinterDataSource printer;
092    
093       /**
094        * Last name searched for
095        */
096    
097       protected String lastSearchName;
098    
099       /**
100        * Selection group to be a part of
101        */
102    
103       protected String selectionGroup;
104    
105       /**
106        * Creates a new table view with no additional functionality.
107        *
108        * @param compare Comparator backend to interface with
109        * @param configMarker Marker for retrieving configuration information from Comparator backend
110        */
111    
112       public BasicTableView (Compare compare, String configMarker) {
113          super (compare, configMarker);
114          DataManager data = compare.getDataManager ();
115          clipboard = (ClipboardDataSource) data.getPreferredSource (ClipboardDataSource.class);
116          printer = (PrinterDataSource) data.getPreferredSource (PrinterDataSource.class);
117          lastSearchName = "";
118       }
119    
120       /**
121        * @see jigcell.compare.ui.INameFinderTab#findByName()
122        */
123    
124       public void findByName () {
125          findByName (false, true);
126       }
127    
128       /**
129        * @see jigcell.compare.ui.INameFinderTab#findByName(boolean)
130        */
131    
132       public boolean findByName (boolean forward) {
133          return findByName (lastSearchName, table.getSelectedRow (), forward);
134       }
135    
136       /**
137        * @see jigcell.compare.ui.INameFinderTab#findByName(boolean,boolean)
138        */
139    
140       public void findByName (boolean resume, boolean forward) {
141          FindAccessory accessory = new FindAccessory ();
142          ((CompareFrontEnd) compare).setTabAccessory (this, accessory);
143          if (resume)
144             accessory.setFound (findByName (lastSearchName, table.getSelectedRow (), forward));
145       }
146    
147       /**
148        * @see jigcell.compare.ui.INameFinderTab#findByName(String,boolean)
149        */
150    
151       public boolean findByName (String name, boolean forward) {
152          return findByName (name, table.getSelectedRow (), forward);
153       }
154    
155       /**
156        * @see jigcell.compare.ui.IColumnEditorTab#getColumnCount()
157        */
158    
159       public int getColumnCount () {
160          return table.getColumnCount ();
161       }
162    
163       /**
164        * @see jigcell.compare.ui.IColumnEditorTab#getColumnData(int)
165        */
166    
167       public Object getColumnData (int column) {
168          throw new UnsupportedOperationException ();
169       }
170    
171       /**
172        * @see jigcell.compare.ui.INameFinderTab#getLastSearchName()
173        */
174    
175       public String getLastSearchName () {
176        return lastSearchName;
177       }
178    
179       /**
180        * @see jigcell.compare.ui.IRowEditorTab#getRowCount()
181        */
182    
183       public int getRowCount () {
184          return table.getRowCount ();
185       }
186    
187       /**
188        * @see jigcell.compare.ui.IRowEditorTab#getRowData(int)
189        */
190    
191       public Object getRowData (int row) {
192          throw new UnsupportedOperationException ();
193       }
194    
195       /**
196        * @see jigcell.compare.ui.IColumnSelectionTab#getSelectedColumns
197        */
198    
199       public int [] getSelectedColumns () {
200          return table.getSelectedColumns ();
201       }
202    
203       /**
204        * @see jigcell.compare.ui.IRowSelectionTab#getSelectedRows
205        */
206    
207       public int [] getSelectedRows () {
208          return table.getSelectedRows ();
209       }
210    
211       /**
212        * The selection group this view is part of.  Null indicates that this view is part of no group.
213        */
214    
215       public String getSelectionGroup () {
216          return selectionGroup;
217       }
218    
219       /**
220        * {@inheritDoc}
221        */
222    
223       public BasicTable getTable () {
224          return table;
225       }
226    
227       public void mouseClicked (MouseEvent e) {}
228    
229       public void mouseEntered (MouseEvent e) {}
230    
231       public void mouseExited (MouseEvent e) {}
232    
233       public void mousePressed (MouseEvent e) {
234          popupPoint = e.getPoint ();
235          if (e.isPopupTrigger () && popup != null) {
236             preparePopup (table.rowAtPoint (popupPoint), table.convertColumnIndexToModel (table.columnAtPoint (popupPoint)));
237             popup.show (e.getComponent (), e.getX (), e.getY ());
238          }
239       }
240    
241       public void mouseReleased (MouseEvent e) {
242          mousePressed (e);
243       }
244    
245       /**
246        * @see jigcell.compare.ui.IRowSelectionTab#selectAll
247        */
248    
249       public void selectAll () {
250          table.selectAll ();
251       }
252    
253       /**
254        * @see jigcell.compare.ui.IRowSelectionTab#selectInvert
255        */
256    
257       public void selectInvert () {
258          if (this instanceof IRowSelectionTab)
259             selectInvertRows ();
260          else if (this instanceof IColumnSelectionTab)
261             selectInvertColumns ();
262          else
263             throw new UnsupportedOperationException ();
264       }
265    
266       /**
267        * @see jigcell.compare.ui.IColumnSelectionTab#selectInvertColumns
268        */
269    
270       public void selectInvertColumns () {
271          if (!(this instanceof IColumnSelectionTab))
272             throw new UnsupportedOperationException ();
273          int cols [] = table.getSelectedColumns ();
274          table.selectAll ();
275          for (int i = 0, l = cols.length; i < l; i++) {
276             int col = cols [i];
277             table.removeColumnSelectionInterval (col, col);
278          }
279       }
280    
281       /**
282        * @see jigcell.compare.ui.IRowSelectionTab#selectInvertRows
283        */
284    
285       public void selectInvertRows () {
286          if (!(this instanceof IRowSelectionTab))
287             throw new UnsupportedOperationException ();
288          int rows [] = table.getSelectedRows ();
289          table.selectAll ();
290          for (int i = 0, l = rows.length; i < l; i++) {
291             int row = rows [i];
292             table.removeRowSelectionInterval (row, row);
293          }
294       }
295    
296       /**
297        * @see jigcell.compare.ui.IRowSelectionTab#selectNone
298        */
299    
300       public void selectNone () {
301          table.clearSelection ();
302       }
303    
304       /**
305        * @see jigcell.compare.ui.IColumnSelectionTab#setSelectedColumns(int [])
306        */
307    
308       public void setSelectedColumns (int columns []) {
309          if (!(this instanceof IColumnSelectionTab))
310             throw new UnsupportedOperationException ();
311          table.clearSelection ();
312          for (int i = 0, l = columns.length; i < l; i++) {
313             int col = columns [i];
314             table.addColumnSelectionInterval (col, col);
315          }
316       }
317    
318       /**
319        * @see jigcell.compare.ui.IRowSelectionTab#setSelectedRows(int [])
320        */
321    
322       public void setSelectedRows (int rows []) {
323          if (!(this instanceof IRowSelectionTab))
324             throw new UnsupportedOperationException ();
325          table.clearSelection ();
326          for (int i = 0, l = rows.length; i < l; i++) {
327             int row = rows [i];
328             table.addRowSelectionInterval (row, row);
329          }
330       }
331    
332       public void valueChanged (ListSelectionEvent e) {
333          if (selectionGroup == null)
334             return;
335          compare.updateResourceMap (RESOURCE_TABLESELECTION, this, table.getSelectedRows ());
336          compare.replaceResource (RESOURCE_LASTTABLESELECTION, this);
337          compare.firePropertyChange (RESOURCE_LASTTABLESELECTION);
338          compare.firePropertyChange (RESOURCE_TABLESELECTION);
339       }
340    
341       /**
342        * Writes data to the clipboard.
343        *
344        * @param data Data
345        * @param message Error message to use in case of error
346        */
347    
348       protected boolean clipboardWrite (Object data, String message) {
349          try {
350             clipboard.write (data);
351             return true;
352          } catch (Exception e) {
353             compare.shellHandleException (Compare.MESSAGE_ERROR, message, e);
354          }
355          return false;
356       }
357    
358       /**
359        * Creates a context menu for the view.
360        */
361    
362       protected JPopupMenu createPopup () {
363          return menuManager.createPopup (POPUP_DEFAULT);
364       }
365    
366       /**
367        * {@inheritDoc}
368        */
369    
370       protected void createUI () {
371          createUI (null);
372       }
373    
374       /**
375        * Creates an interface for the view.
376        *
377        * @param model Table model to use
378        */
379    
380       protected void createUI (BasicTable.BasicTableModel model) {
381          setLayout (new BorderLayout ());
382          this.model = model;
383          table = new BasicTable (model);
384          table.setColumnSelectionAllowed (false);
385          table.setDragEnabled (false);
386          table.setRowSelectionAllowed (true);
387          table.setSurrendersFocusOnKeystroke (true);
388          table.setSelectionMode (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
389          table.getSelectionModel ().addListSelectionListener (this);
390          JScrollPane scroll = new JScrollPane (table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
391          add (scroll, BorderLayout.CENTER);
392          scroll.setBorder (InterfaceBuilder.BORDER_NOTHING);
393          popup = createPopup ();
394          table.addMouseListener (this);
395          table.setDefaultEditor (Object.class, new BasicTable.BasicEditor (this));
396          table.setDefaultRenderer (Object.class, new BasicTable.BasicRenderer (this));
397       }
398    
399       /**
400        * Searches for a name starting from an initial row in a specified direction.  Returns whether an instance was found.
401        *
402        * @param name Name to search for
403        * @param row Starting row
404        * @param forward Whether to search forwards
405        */
406    
407       protected boolean findByName (String name, int row, boolean forward) {
408          return false;
409       }
410    
411       /**
412        * Prepares the popup for display.
413        *
414        * @param row Model row of the popup point
415        * @param column Model column of the popup point
416        */
417    
418       protected void preparePopup (int row, int column) {}
419    
420       /**
421        * Sets the selection group to be a part of.  Null indicates that this view is part of no group.
422        *
423        * @param group Selection group
424        */
425    
426       protected void setSelectionGroup (String group) {
427          selectionGroup = group;
428       }
429    }