001         package com.croftsoft.apps.agoracast.c2p;
002    
003         import java.awt.*;
004         import java.awt.event.*;
005         import java.beans.*;
006         import java.io.*;
007         import javax.swing.*;
008         import javax.swing.event.*;
009         import javax.swing.table.*;
010         import java.util.*;
011    
012         import com.croftsoft.core.gui.ButtonPanel2;
013         import com.croftsoft.core.gui.LabeledFieldsPanel2;
014         import com.croftsoft.core.gui.table.AlternatingRenderer;
015         import com.croftsoft.core.gui.table.TableColumnModelAdapter;
016         import com.croftsoft.core.lang.NullArgumentException;
017         import com.croftsoft.core.util.ArrayLib;
018    
019         /*********************************************************************
020         * Displays the downloaded data in a table.
021         *
022         * <p />
023         *
024         * @version
025         *   2001-11-09
026         * @since
027         *   2001-07-31
028         * @author
029         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
030         *********************************************************************/
031    
032         public final class  AgoracastTablePanel
033           extends JPanel
034           implements ActionListener
035         //////////////////////////////////////////////////////////////////////
036         //////////////////////////////////////////////////////////////////////
037         {
038    
039         private static final String  CATEGORY_ALL   = "--- ALL ---";
040    
041         //
042    
043         private final AgoracastMediator     agoracastMediator;
044    
045         private final AgoracastBrowsePanel  agoracastBrowsePanel;
046    
047         private final JButton               columnsButton;
048    
049         private final JButton               downloadButton;
050    
051         private final JComboBox             jComboBox;
052    
053         //
054    
055         private AgoracastTableModel   agoracastTableModel;
056    
057         private JTable                jTable;
058    
059         private JScrollPane           jScrollPane;
060    
061         private String                category;
062    
063         private String [ ]            columnNames;
064    
065         //////////////////////////////////////////////////////////////////////
066         //////////////////////////////////////////////////////////////////////
067    
068         public  AgoracastTablePanel (
069           AgoracastMediator     agoracastMediator,
070           AgoracastBrowsePanel  agoracastBrowsePanel )
071         //////////////////////////////////////////////////////////////////////
072         {
073           super ( new BorderLayout ( ), true ); // isDoubleBuffered
074    
075           NullArgumentException.check (
076             this.agoracastMediator = agoracastMediator );
077    
078           NullArgumentException.check (
079             this.agoracastBrowsePanel = agoracastBrowsePanel );
080    
081           AgoracastLib.setColor ( this, agoracastMediator );
082    
083           updateTable ( null );
084    
085           columnsButton = new JButton ( "Add and Remove Columns" );
086    
087           columnsButton.addActionListener ( this );
088    
089           downloadButton = new JButton ( "Download New Data" );
090    
091           downloadButton.addActionListener ( this );
092    
093           add (
094             new ButtonPanel2 (
095               new JButton [ ] { columnsButton, downloadButton } ),
096             BorderLayout.SOUTH );
097    
098           String [ ]  categories = ( String [ ] ) ArrayLib.prepend (
099             AgoracastConstants.CHOICES_CATEGORY, CATEGORY_ALL );
100    
101           jComboBox = new JComboBox ( categories );
102    
103           jComboBox.addActionListener ( this );
104    
105           JPanel  categoryPanel = new JPanel ( new FlowLayout ( ), true );
106    
107           categoryPanel.add ( new JLabel ( "Category:  " ) );
108    
109           categoryPanel.add ( jComboBox );
110    
111           JPanel  northPanel = new JPanel ( new BorderLayout ( ), true );
112    
113           northPanel.add ( categoryPanel, BorderLayout.NORTH );
114    
115           northPanel.add (
116             new JLabel ( AgoracastConstants.TABLE_TEXT ), BorderLayout.SOUTH );
117    
118           add ( northPanel, BorderLayout.NORTH );
119         }
120    
121         //////////////////////////////////////////////////////////////////////
122         //////////////////////////////////////////////////////////////////////
123    
124         public synchronized void  actionPerformed ( ActionEvent  actionEvent )
125         //////////////////////////////////////////////////////////////////////
126         {
127           Object  source = actionEvent.getSource ( );
128    
129           if ( source == downloadButton )
130           {
131             agoracastBrowsePanel.download ( );
132           }
133           else if ( source == columnsButton )
134           {
135             agoracastBrowsePanel.showFieldsPanel ( columnNames );
136           }
137           else if ( source == jComboBox )
138           {
139             handleCategorySelection ( );
140           }
141         }
142    
143         public synchronized void  updateTable ( String [ ]  columnNames )
144         //////////////////////////////////////////////////////////////////////
145         {
146           if ( ( columnNames == null    )
147             || ( columnNames.length < 1 ) )
148           {
149             // get the default columns for the category
150    
151             AgoracastCategory  agoracastCategory
152               = agoracastMediator.getAgoracastCategory ( category );
153    
154             columnNames = agoracastCategory.getColumnNames ( );
155           }
156    
157           this.columnNames = columnNames;
158    
159           if ( jScrollPane != null )
160           {
161             remove ( jScrollPane );
162           }
163    
164           agoracastTableModel = new AgoracastTableModel (
165             agoracastMediator, category, columnNames );
166    
167           jTable = new JTable ( agoracastTableModel );
168    
169    // The following hack attempts to size the column widths proportional
170    // to their max String lengths.  Should be replaced by a better
171    // algorithm or a method that allows the user to persistently set the
172    // width.
173    
174           TableColumnModel  tableColumnModel = jTable.getColumnModel ( );
175    
176           int  columnCount = tableColumnModel.getColumnCount ( );
177    
178           int  rowCount = agoracastTableModel.getRowCount ( );
179    
180           for ( int  i = 0; i < columnCount; i++ )
181           {
182             TableColumn  tableColumn = tableColumnModel.getColumn ( i );
183    
184             int  maxCharacterWidth
185               = agoracastTableModel.getColumnName ( i ).length ( );
186    
187             for ( int  j = 0; j < rowCount; j++ )
188             {
189               String  value = ( String )
190                 ( agoracastTableModel.getValueAt ( j, i ) );
191    
192               if ( value != null )
193               {
194                 int  length = value.length ( );
195    
196                 if ( length > maxCharacterWidth )
197                 {
198                   maxCharacterWidth = length;
199                 }        
200               }
201             }
202    
203             tableColumn.setPreferredWidth ( maxCharacterWidth * 15 );
204           }
205    
206           jTable.getSelectionModel ( ).setSelectionMode (
207             ListSelectionModel.SINGLE_SELECTION );
208    
209           JTableHeader  jTableHeader = jTable.getTableHeader ( );
210    
211           jTableHeader.setUpdateTableInRealTime ( false );
212    
213           jTableHeader.addMouseListener (
214             new MouseAdapter ( )
215             {
216               public void  mouseClicked ( MouseEvent  mouseEvent )
217               {
218                 handleSortColumn ( mouseEvent );
219               }
220             } );
221    
222           jTable.addMouseListener (
223             new MouseAdapter ( )
224             {
225               public void  mouseClicked ( MouseEvent  mouseEvent )
226               {
227                 handleRowSelection ( mouseEvent );
228               }
229             } );
230    
231           jTable.setDefaultRenderer (
232             Object.class,
233             new AlternatingRenderer (
234               AgoracastConstants.SELECTED_FOREGROUND_COLOR,
235               AgoracastConstants.SELECTED_BACKGROUND_COLOR,
236               AgoracastConstants.ODD_FOREGROUND_COLOR,
237               AgoracastConstants.ODD_BACKGROUND_COLOR,
238               AgoracastConstants.EVEN_FOREGROUND_COLOR,
239               AgoracastConstants.EVEN_BACKGROUND_COLOR ) );
240    
241           jTable.setRequestFocusEnabled ( false );
242    
243           // Runs faster if unregistered.
244           // p717, Zukowski, "Definitive Guide to Swing for Java 2, 2nd Ed."
245    
246           ToolTipManager.sharedInstance ( ).unregisterComponent ( jTable );
247    
248           jScrollPane = new JScrollPane ( jTable );
249    
250           add ( jScrollPane, BorderLayout.CENTER );
251    
252           revalidate ( );
253         }
254    
255         //////////////////////////////////////////////////////////////////////
256         // private methods
257         //////////////////////////////////////////////////////////////////////
258    
259         private synchronized void  handleRowSelection ( MouseEvent  e )
260         //////////////////////////////////////////////////////////////////////
261         {
262           if ( e.getClickCount ( ) == 2 )
263           {
264             agoracastBrowsePanel.viewSource (
265               agoracastTableModel.getAgoracastData (
266               jTable.getSelectedRow ( ) ) );
267           }
268         }
269    
270         /*********************************************************************
271         * See Robinson & Vorobiev, "Swing", 2000, p602.
272         *********************************************************************/
273         private synchronized void  handleSortColumn ( MouseEvent  e )
274         //////////////////////////////////////////////////////////////////////
275         {
276           TableColumnModel  tableColumnModel = jTable.getColumnModel ( );
277    
278           int  columnModelIndex
279             = tableColumnModel.getColumnIndexAtX ( e.getX ( ) );
280    
281           int  modelIndex = tableColumnModel.getColumn (
282             columnModelIndex ).getModelIndex ( );
283    
284           agoracastTableModel.sort ( modelIndex );
285         }
286    
287         private synchronized void  handleCategorySelection ( )
288         //////////////////////////////////////////////////////////////////////
289         {
290           category = ( String ) jComboBox.getSelectedItem ( );
291    
292           if ( CATEGORY_ALL.equals ( category ) )
293           {
294             category = null;
295           }
296    
297           AgoracastCategory  agoracastCategory
298             = agoracastMediator.getAgoracastCategory ( category );
299    
300           updateTable ( agoracastCategory.getColumnNames ( ) ); 
301         }
302    
303         //////////////////////////////////////////////////////////////////////
304         //////////////////////////////////////////////////////////////////////
305         }