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 * (C) 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 */
015package com.ibm.rational.stp.client.samples;
016
017import java.awt.BorderLayout;
018import java.awt.FlowLayout;
019import java.awt.Font;
020import java.awt.event.ActionEvent;
021import java.awt.event.ActionListener;
022import java.awt.event.WindowAdapter;
023import java.awt.event.WindowEvent;
024import java.io.File;
025import java.io.FileReader;
026import java.util.Vector;
027
028import javax.swing.JButton;
029import javax.swing.JComboBox;
030import javax.swing.JFrame;
031import javax.swing.JOptionPane;
032import javax.swing.JPanel;
033import javax.swing.JScrollPane;
034import javax.swing.JTable;
035import javax.swing.JTextArea;
036import javax.swing.ListSelectionModel;
037import javax.swing.event.ListSelectionEvent;
038import javax.swing.event.ListSelectionListener;
039import javax.swing.plaf.basic.BasicBorders;
040import javax.swing.table.AbstractTableModel;
041import javax.wvcm.WvcmException;
042
043/**
044 * An all-in-one class for displaying a table of browser data
045 */
046public 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}