001    /*
002     * file BrowserDataModel.java
003     *
004     * Licensed Materials - Property of IBM
005     * Restricted Materials of IBM - you are allowed to copy, modify and 
006     * redistribute this file as part of any program that interfaces with 
007     * IBM Rational CM API.
008     *
009     * com.ibm.rational.stp.client.samples.BrowserDataModel
010     *
011     * © Copyright IBM Corporation 2004, 2008.  All Rights Reserved.
012     * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
013     * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp.
014     */
015    package com.ibm.rational.stp.client.samples;
016    
017    import java.awt.BorderLayout;
018    import java.awt.FlowLayout;
019    import java.awt.Font;
020    import java.awt.event.ActionEvent;
021    import java.awt.event.ActionListener;
022    import java.awt.event.WindowAdapter;
023    import java.awt.event.WindowEvent;
024    import java.io.File;
025    import java.io.FileReader;
026    import java.util.Vector;
027    
028    import javax.swing.JButton;
029    import javax.swing.JComboBox;
030    import javax.swing.JFrame;
031    import javax.swing.JOptionPane;
032    import javax.swing.JPanel;
033    import javax.swing.JScrollPane;
034    import javax.swing.JTable;
035    import javax.swing.JTextArea;
036    import javax.swing.ListSelectionModel;
037    import javax.swing.event.ListSelectionEvent;
038    import javax.swing.event.ListSelectionListener;
039    import javax.swing.plaf.basic.BasicBorders;
040    import javax.swing.table.AbstractTableModel;
041    import javax.wvcm.WvcmException;
042    
043    /**
044     * An all-in-one class for displaying a table of browser data
045     */
046    public abstract class BrowserDataModel
047        extends AbstractTableModel
048    {
049        /**
050         * Returns the object that is viewable at a given index in the table model
051         *
052         * @param  index  The index into the table model of the item to show
053         *
054         * @return  null if the item is not viewable; otherwise an object that
055         * is viewable.
056         */
057        abstract Object getViewable(int index);
058    
059        /**
060         * Displays an object returned by getViewable
061         *
062         * @param  viewable  The object to display.
063         */
064        abstract void show(Object viewable) throws WvcmException;
065    
066        /**
067         * Displays the content of the object whose properties are displayed in 
068         * this table.
069         * @throws Throwable If the content cannot be displayed.
070         */
071        void showContent() throws Throwable {} 
072        
073        /**
074         * Returns the label to place on the Hide/Show Errors button
075         * @return If null or empty, the Hide/Show button is not displayed; 
076         * otherwise the button will be displayed with the given label.
077         */
078        String toggleErrorsLabel() { return ""; }
079        
080        /**
081         * Rereads the data from the resource and redisplays it
082         * 
083         * @throws WvcmException If problems arise during the process. 
084         */
085        void redisplay() throws WvcmException {}
086    
087        /**
088         * Processes the Show/Hide Errors button when clicked.
089         * @throws WvcmException if the action cannot be carried out.
090         */
091        void toggleErrors() throws WvcmException {}
092        
093        /**
094         * A specification for the interface between the BrowserDataModel and a
095         * provider of operations to be applied to the object displayed in the
096         * model.
097         */
098        interface Operations {
099                /**
100                 * Returns a list of operations that can be applied to the object displayed
101                 * by this data model.
102                 * If not null, the list is placed in a combo-box from which the user
103                 * may select and execute an operation.
104                 * @return A list of possible operations for the resource. If null, no
105                 * operations combo-box will be displayed.
106                 */
107                Vector getList();
108                
109                /**
110                 * Performs the operation identified by the argument to the object displayed
111                 * by this data model.
112                 * @param op One of the operations supplied in the list returned by
113                 * resourceOperations.
114                 */
115                void execute(Object op, BrowserDataModel model);
116        }
117        
118        Operations getOperationsObject() { return null; }
119        
120        /**
121         * Generates a display of this table.
122         * @param  title  The window title
123         * @param  hasContent true if the ShowContent button should be displayed
124         */
125        JFrame showModel(
126            String       title,
127            boolean      hasContent)
128        {
129            final JFrame frame = new JFrame(title);
130            // Comment this line when using Sun's TableSorter class
131            final JTable table = new JTable(this);
132            // Uncomment these lines when using Sun's TableSorter class
133            // final TableSorter sorter = (m_sorter = new TableSorter(this));
134            // final JTable      table = new JTable(sorter);
135            //         
136            // sorter.setTableHeader(table.getTableHeader());
137            // sorter.setSortingStatus(0, TableSorter.ASCENDING);
138            //
139            final JPanel  panel = new JPanel(new BorderLayout());
140            final JPanel  subpanel = new JPanel(new FlowLayout());
141            final JButton button = new JButton("View");
142    
143            subpanel.add(button, BorderLayout.SOUTH);
144            button.setEnabled(false);
145            button.addActionListener(new ActionListener() {
146                    public void actionPerformed(ActionEvent arg0)
147                    {
148                        int[] selected = selectedRows(table);
149    
150                        for (int i = 0; i < selected.length; ++i) {
151                            try {
152                                show(getViewable(selected[i]));
153                            } catch (WvcmException ex) {
154                                JOptionPane.showMessageDialog(null, ex.getLocalizedMessage());
155                            }
156                        }
157                    }
158                });
159    
160            if (hasContent) {
161                JButton show = new JButton("Show Content");
162                subpanel.add(show);
163                show.addActionListener(new ActionListener() {
164                    public void actionPerformed(ActionEvent arg0)
165                    {
166                        try {
167                            showContent();
168                        } catch (Throwable ex) {
169                            JOptionPane.showMessageDialog(null, ex.getLocalizedMessage());
170                        }
171                    }
172                });
173            }
174            
175            String label = toggleErrorsLabel();
176            
177            if (label.length() > 0) {
178                JButton show = new JButton(label);
179                subpanel.add(show);
180                show.addActionListener(new ActionListener() {
181                    public void actionPerformed(ActionEvent arg0)
182                    {
183                        try {
184                            toggleErrors();
185                        } catch (Throwable ex) {
186                            JOptionPane.showMessageDialog(null, ex.getLocalizedMessage());
187                        }
188                    }
189                });
190            }
191            
192            final Operations ops = getOperationsObject();
193            
194            if (ops != null) {
195                    Vector list = ops.getList();
196                    
197                    if (list != null && !list.isEmpty()) {
198                            final JComboBox box = new JComboBox(list);
199                        JButton exec = new JButton("<<GO!");
200                        subpanel.add(box);
201                        subpanel.add(exec);
202                        exec.addActionListener(new ActionListener() {
203                            public void actionPerformed(ActionEvent arg0)
204                            {
205                                ops.execute(box.getSelectedItem(), BrowserDataModel.this);
206                            }
207                        });
208                    }
209            }
210            
211            JButton exit = new JButton("Exit");
212            subpanel.add(exit);
213            exit.addActionListener(new ActionListener() {
214                public void actionPerformed(ActionEvent arg0)
215                {
216                    System.exit(0);
217                }
218            });
219            
220            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
221    
222            // Ask to be notified of selection changes.
223            ListSelectionModel rowSM = table.getSelectionModel();
224            rowSM.addListSelectionListener(new ListSelectionListener() {
225                    public void valueChanged(ListSelectionEvent e)
226                    {
227                        if (!e.getValueIsAdjusting()) {
228                            int[] selected = selectedRows(table);
229                            button.setEnabled(false);
230    
231                            for (int i = 0; i < selected.length; ++i) {
232                                if (getViewable(selected[i]) != null) {
233                                    button.setEnabled(true);
234    
235                                    break;
236                                }
237                            }
238                        }
239                    }
240                });
241    
242            panel.add(new JScrollPane(table), BorderLayout.CENTER);
243            panel.add(subpanel, BorderLayout.SOUTH);
244            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
245            frame.setContentPane(panel);
246            frame.setBounds(lastX += 3, lastY += 3, 
247                                            600, 17*(5 + table.getRowCount()));
248            frame.addWindowFocusListener(new WindowAdapter(){
249                public void windowGainedFocus(
250                    WindowEvent arg0)
251                {
252                    super.windowGainedFocus(arg0);
253                    lastX = arg0.getWindow().getX();
254                    lastY = arg0.getWindow().getY();
255                }
256            });
257    
258            frame.setVisible(true);
259            
260            return m_frame = frame;
261        }
262        
263        /**
264         * Returns the rows of the table currently selected in the display
265         * @param table The table
266         * @return An int[] containing the index of each row that is highlighted
267         */
268        int[] selectedRows(JTable table)
269        {
270            int[] selected = table.getSelectedRows();
271    
272            // Uncomment these lines when using Sun's TableSorter class
273            // for (int I = 0; I < selected.length; ++I)
274            //      selected[I] = m_sorter.modelIndex(selected[I]);
275            //
276            
277            return selected;
278        }
279        
280        /**
281         * Displays the content of file in a window.
282         * @param title The title string to appear in the window banner
283         * @param file A File identifying the file whose content is to be displayed
284         * @return A JFrame for the displayed window.
285         * @throws Throwable If the content of the file cannot be displayed.
286         */
287        static JFrame showFile(
288            String title, 
289            File file) throws Throwable
290        {
291            JTextArea text = new JTextArea(680, 400);
292            FileReader reader = new FileReader(file);
293            char[] buf = new char[1000];
294            int n;
295        
296            while ((n=reader.read(buf)) > 0) {
297                text.append(new String(buf,0,n));
298            }
299            
300            reader.close();
301            file.delete();
302            
303            text.setBorder(BasicBorders.getTextFieldBorder());
304            text.setCaretPosition(0);
305            text.setFont(new Font("Monospaced", Font.PLAIN, 12));
306            
307            JFrame frame = new JFrame(title);
308            frame.setContentPane(new JScrollPane(text));
309            frame.setBounds(lastX += 20, lastY += 40, 600, 300);
310            frame.setVisible(true);
311            
312            return frame;
313        }
314        
315        // Uncomment this line when using a TableSorter
316        // private TableSorter m_sorter;
317        //
318        
319        /** The frame containing this data model */
320        protected JFrame m_frame;
321        
322        /** The X offset for the next window displayed */
323        static int lastX = 180;
324    
325        /** The Y offset for the next window displayed */
326        static int lastY = 360;
327    }