KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > ui > ClipboardHistoryFrame


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.ui;
35
36 import javax.swing.*;
37 import javax.swing.event.*;
38 import javax.swing.text.JTextComponent JavaDoc;
39 import javax.swing.text.Keymap JavaDoc;
40 import java.awt.*;
41 import java.awt.event.*;
42 import java.util.List JavaDoc;
43 import java.util.ArrayList JavaDoc;
44 import java.util.StringTokenizer JavaDoc;
45 import java.util.NoSuchElementException JavaDoc;
46
47 import edu.rice.cs.drjava.DrJava;
48 import edu.rice.cs.drjava.config.OptionConstants;
49 import edu.rice.cs.drjava.model.ClipboardHistoryModel;
50 import edu.rice.cs.util.Lambda;
51
52 /** Frame with history of clipboard. */
53 public class ClipboardHistoryFrame extends JFrame {
54   /** Interface for an action to be performed when the user closes the frame,
55    * either by using "OK" or "Cancel".
56    */

57   public static interface CloseAction extends Lambda<Object JavaDoc, String JavaDoc> {
58     public Object JavaDoc apply(String JavaDoc selected);
59   }
60   
61   /** Class to save the frame state, i.e. location and dimensions.*/
62   public static class FrameState {
63     private Dimension _dim;
64     private Point _loc;
65     public FrameState(Dimension d, Point l) {
66       _dim = d;
67       _loc = l;
68     }
69     public FrameState(String JavaDoc s) {
70       StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(s);
71       try {
72         int x = Integer.valueOf(tok.nextToken());
73         int y = Integer.valueOf(tok.nextToken());
74         _dim = new Dimension(x, y);
75         x = Integer.valueOf(tok.nextToken());
76         y = Integer.valueOf(tok.nextToken());
77         _loc = new Point(x, y);
78       }
79       catch(NoSuchElementException JavaDoc nsee) {
80         throw new IllegalArgumentException JavaDoc("Wrong FrameState string: " + nsee);
81       }
82       catch(NumberFormatException JavaDoc nfe) {
83         throw new IllegalArgumentException JavaDoc("Wrong FrameState string: " + nfe);
84       }
85     }
86     public FrameState(ClipboardHistoryFrame comp) {
87       _dim = comp.getSize();
88       _loc = comp.getLocation();
89     }
90     public String JavaDoc toString() {
91       final StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
92       sb.append((int)_dim.getWidth());
93       sb.append(' ');
94       sb.append((int)_dim.getHeight());
95       sb.append(' ');
96       sb.append(_loc.x);
97       sb.append(' ');
98       sb.append(_loc.y);
99       return sb.toString();
100     }
101     public Dimension getDimension() { return _dim; }
102     public Point getLocation() { return _loc; }
103   }
104
105   /** Clipboard history model */
106   private ClipboardHistoryModel _chm;
107
108   /** Code for the last button that was pressed.*/
109   private int _buttonPressed;
110
111   /** Ok button.*/
112   private JButton _okButton;
113   
114   /** Cancel button. */
115   private JButton _cancelButton;
116
117   /** List with history. */
118   private JList _historyList;
119
120   /** Text area for that previews the history content. */
121   private JTextArea _previewArea;
122   
123   /** Last frame state. It can be stored and restored. */
124   private FrameState _lastState = null;
125   
126   /** Owner frame. */
127   private MainFrame _mainFrame;
128   
129   /** Close actions for ok and cancel button. */
130   private CloseAction _okAction, _cancelAction;
131   
132   /** Create a new clipboard history frame.
133    * @param owner owner frame
134    * @param title dialog title
135    * @param chm the clipboard history model
136    * @param okAction the action to perform when OK is clicked
137    * @param cancelAction the action to perform when Cancel is clicked
138    */

139   public ClipboardHistoryFrame(MainFrame owner, String JavaDoc title, ClipboardHistoryModel chm,
140                                CloseAction okAction, CloseAction cancelAction) {
141     super(title);
142     _chm = chm;
143     _mainFrame = owner;
144     _okAction = okAction;
145     _cancelAction = cancelAction;
146     init();
147   }
148   
149   /** Returns the last state of the frame, i.e. the location and dimension.
150    * @return frame state
151    */

152   public FrameState getFrameState() { return _lastState; }
153   
154   /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
155    * @param ds State to update to, or {@code null} to reset
156    */

157   public void setFrameState(FrameState ds) {
158     _lastState = ds;
159     if (_lastState!=null) {
160       setSize(_lastState.getDimension());
161       setLocation(_lastState.getLocation());
162       validate();
163     }
164   }
165   
166   /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
167    * @param s State to update to, or {@code null} to reset
168    */

169   public void setFrameState(String JavaDoc s) {
170     try { _lastState = new FrameState(s); }
171     catch(IllegalArgumentException JavaDoc e) { _lastState = null; }
172     if (_lastState!=null) {
173       setSize(_lastState.getDimension());
174       setLocation(_lastState.getLocation());
175       validate();
176     }
177     else {
178       Dimension parentDim = (_mainFrame!=null)?(_mainFrame.getSize()):getToolkit().getScreenSize();
179       int xs = (int)parentDim.getWidth()/3;
180       int ys = (int)parentDim.getHeight()/4;
181       setSize(Math.max(xs,400), Math.max(ys, 400));
182       MainFrame.setPopupLoc(this, _mainFrame);
183     }
184   }
185
186   /** Return the code for the last button that was pressed. This will be either JOptionPane.OK_OPTION or
187    * JOptionPane.CANCEL_OPTION.
188    * @return button code
189    */

190   public int getButtonPressed() {
191     return _buttonPressed;
192   }
193
194   /** Initialize the frame.
195    */

196   private void init() {
197     addWindowListener(new java.awt.event.WindowAdapter JavaDoc() {
198       public void windowClosing(WindowEvent winEvt) {
199         cancelButtonPressed();
200       }
201     });
202     addComponentListener(new java.awt.event.ComponentAdapter JavaDoc() {
203       public void componentResized(ComponentEvent e) {
204         validate();
205         _historyList.ensureIndexIsVisible(_historyList.getSelectedIndex());
206       }
207     });
208     
209     JRootPane rootPane = this.getRootPane();
210     InputMap iMap = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
211     iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
212     
213     ActionMap aMap = rootPane.getActionMap();
214     aMap.put("escape", new AbstractAction() {
215       public void actionPerformed(ActionEvent e) {
216         cancelButtonPressed();
217       }
218     });
219
220     _historyList = new JList();
221     _historyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
222     _historyList.addListSelectionListener(new ListSelectionListener() {
223       public void valueChanged(ListSelectionEvent e) {
224         updatePreview();
225       }
226     });
227     _historyList.setFont(DrJava.getConfig().getSetting(OptionConstants.FONT_MAIN));
228     _historyList.setCellRenderer(new DefaultListCellRenderer() {
229       public Component JavaDoc getListCellRendererComponent(JList list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus) {
230         Component JavaDoc c = super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
231         c.setForeground(DrJava.getConfig().getSetting(OptionConstants.DEFINITIONS_NORMAL_COLOR));
232         return c;
233       }
234     });
235     _historyList.addFocusListener(new FocusListener() {
236       public void focusGained(FocusEvent e) {
237       }
238
239       public void focusLost(FocusEvent e) {
240         if ((e.getOppositeComponent()!=_previewArea) &&
241             (e.getOppositeComponent()!=_okButton) &&
242             (e.getOppositeComponent()!=_cancelButton)) {
243           _historyList.requestFocus();
244         }
245       }
246     });
247
248     // buttons
249
_okButton = new JButton("OK");
250     _okButton.addActionListener(new ActionListener() {
251       public void actionPerformed(ActionEvent e) {
252         okButtonPressed();
253       }
254     });
255
256     _cancelButton = new JButton("Cancel");
257     _cancelButton.addActionListener(new ActionListener() {
258       public void actionPerformed(ActionEvent e) {
259         cancelButtonPressed();
260       }
261     });
262         
263     // put everything together
264
Container contentPane = getContentPane();
265     
266     GridBagLayout layout = new GridBagLayout();
267     contentPane.setLayout(layout);
268     
269     GridBagConstraints c = new GridBagConstraints();
270     c.anchor = GridBagConstraints.NORTHWEST;
271     c.weightx = 1.0;
272     c.weighty = 0.0;
273     c.gridwidth = GridBagConstraints.REMAINDER; // end row
274
c.insets.top = 2;
275     c.insets.left = 2;
276     c.insets.bottom = 2;
277     c.insets.right = 2;
278
279     c.fill = GridBagConstraints.BOTH;
280     c.weighty = 1.0;
281     contentPane.add(new JScrollPane(_historyList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
282                                     JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
283                     c);
284     
285     _previewArea = new JTextArea("");
286     _previewArea.setEditable(false);
287     _previewArea.setDragEnabled(false);
288     _previewArea.setEnabled(false);
289     _previewArea.setFont(DrJava.getConfig().getSetting(OptionConstants.FONT_MAIN));
290     _previewArea.setDisabledTextColor(DrJava.getConfig().getSetting(OptionConstants.DEFINITIONS_NORMAL_COLOR));
291     c.weighty = 2.0;
292     contentPane.add(new JScrollPane(_previewArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
293                                     JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
294                     c);
295     
296     c.anchor = GridBagConstraints.SOUTH;
297     
298     JPanel buttonPanel = new JPanel(new GridBagLayout());
299     GridBagConstraints bc = new GridBagConstraints();
300     bc.insets.left = 2;
301     bc.insets.right = 2;
302     buttonPanel.add(_okButton, bc);
303     buttonPanel.add(_cancelButton, bc);
304     
305     c.weighty = 0.0;
306     contentPane.add(buttonPanel, c);
307
308     Dimension parentDim = (_mainFrame!=null)?(_mainFrame.getSize()):getToolkit().getScreenSize();
309     int xs = (int)parentDim.getWidth()/3;
310     int ys = (int)parentDim.getHeight()/4;
311     setSize(Math.max(xs,400), Math.max(ys, 300));
312     MainFrame.setPopupLoc(this, _mainFrame);
313
314     updateView();
315   }
316   
317   /** Validates before changing visibility. Only runs in the event thread.
318     * @param b true if frame should be shown, false if it should be hidden.
319     */

320   public void setVisible(boolean b) {
321     assert EventQueue.isDispatchThread();
322     validate();
323     super.setVisible(b);
324     if (b) {
325       _mainFrame.hourglassOn();
326       updateView();
327       _historyList.requestFocus();
328     }
329     else {
330       _mainFrame.hourglassOff();
331       _mainFrame.toFront();
332     }
333   }
334
335   /** Update the displays based on the model. */
336   private void updateView() {
337     List JavaDoc<String JavaDoc> strs = _chm.getStrings();
338     ListItem[] arr = new ListItem[strs.size()];
339     for(int i=0; i<strs.size(); ++i) arr[strs.size()-i-1] = new ListItem(strs.get(i));
340     _historyList.setListData(arr);
341     if (_historyList.getModel().getSize()>0) {
342       _historyList.setSelectedIndex(0);
343       getRootPane().setDefaultButton(_okButton);
344       _okButton.setEnabled(true);
345     }
346     else {
347       getRootPane().setDefaultButton(_cancelButton);
348       _okButton.setEnabled(false);
349     }
350     updatePreview();
351   }
352
353   /** Update the preview area based on the model. */
354   private void updatePreview() {
355     String JavaDoc text = "";
356     if (_historyList.getModel().getSize()>0) {
357       int index = _historyList.getSelectedIndex();
358       if (index!=-1) {
359         text = ((ListItem)_historyList.getModel().getElementAt(_historyList.getSelectedIndex())).getFull();
360       }
361     }
362
363     _previewArea.setText(text);
364     _previewArea.setCaretPosition(0);
365   }
366   
367   /** Handle OK button. */
368   private void okButtonPressed() {
369     _lastState = new FrameState(ClipboardHistoryFrame.this);
370     setVisible(false);
371     if (_historyList.getModel().getSize()>0) {
372       _buttonPressed = JOptionPane.OK_OPTION;
373       String JavaDoc s = ((ListItem)_historyList.getModel().getElementAt(_historyList.getSelectedIndex())).getFull();
374       _chm.put(s);
375       _okAction.apply(s);
376     }
377     else {
378       _buttonPressed = JOptionPane.CANCEL_OPTION;
379       Toolkit.getDefaultToolkit().beep();
380       _cancelAction.apply(null);
381     }
382   }
383   
384   /** Handle cancel button. */
385   private void cancelButtonPressed() {
386     _buttonPressed = JOptionPane.CANCEL_OPTION;
387     _lastState = new FrameState(ClipboardHistoryFrame.this);
388     setVisible(false);
389     _cancelAction.apply(null);
390   }
391   
392   /** Keeps a full string, but toString is only the first line. */
393   private static class ListItem {
394     private String JavaDoc full, display;
395     public ListItem(String JavaDoc s) {
396       full = s;
397       int index1 = s.indexOf('\n');
398       if (index1==-1) index1 = s.length();
399       int index2 = s.indexOf(System.getProperty("line.separator"));
400       if (index2==-1) index2 = s.length();
401       display = s.substring(0, Math.min(index1, index2));
402     }
403     public String JavaDoc getFull() { return full; }
404     public String JavaDoc toString() { return display; }
405     public boolean equals(Object JavaDoc o) {
406       if ((o==null) || !(o instanceof ListItem)) return false;
407       return full.equals(((ListItem)o).full);
408     }
409   }
410 }
411
Popular Tags