fea7ebd872cfaf4bdf1b2609fe02d063bf8b5f52
[debian/openrocket] / src / net / sf / openrocket / util / GUIUtil.java
1 package net.sf.openrocket.util;
2
3 import java.awt.Component;
4 import java.awt.Image;
5 import java.awt.KeyboardFocusManager;
6 import java.awt.Point;
7 import java.awt.Window;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.KeyEvent;
10 import java.awt.event.MouseAdapter;
11 import java.awt.event.MouseEvent;
12 import java.awt.event.WindowEvent;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20
21 import javax.imageio.ImageIO;
22 import javax.swing.AbstractAction;
23 import javax.swing.Action;
24 import javax.swing.JButton;
25 import javax.swing.JComponent;
26 import javax.swing.JDialog;
27 import javax.swing.JRootPane;
28 import javax.swing.JTable;
29 import javax.swing.KeyStroke;
30 import javax.swing.RootPaneContainer;
31 import javax.swing.SwingUtilities;
32 import javax.swing.table.AbstractTableModel;
33 import javax.swing.table.TableModel;
34
35 public class GUIUtil {
36
37         private static final KeyStroke ESCAPE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
38         private static final String CLOSE_ACTION_KEY =  "escape:WINDOW_CLOSING"; 
39         
40     private static final List<Image> images = new ArrayList<Image>();
41     static {
42         loadImage("pix/icon/icon-256.png");
43         loadImage("pix/icon/icon-064.png");
44         loadImage("pix/icon/icon-048.png");
45         loadImage("pix/icon/icon-032.png");
46         loadImage("pix/icon/icon-016.png");
47     }
48     
49     private static void loadImage(String file) {
50         InputStream is;
51  
52         is = ClassLoader.getSystemResourceAsStream(file);
53         if (is == null)
54                 return;
55         
56         try {
57                 Image image = ImageIO.read(is);
58                 images.add(image);
59         } catch (IOException ignore) {
60                 ignore.printStackTrace();
61         }
62     }
63     
64
65         
66         
67         /**
68          * Add the correct action to close a JDialog when the ESC key is pressed.
69          * The dialog is closed by sending is a WINDOW_CLOSING event.
70          * 
71          * @param dialog        the dialog for which to install the action.
72          */
73         public static void installEscapeCloseOperation(final JDialog dialog) { 
74             Action dispatchClosing = new AbstractAction() { 
75                 public void actionPerformed(ActionEvent event) { 
76                     dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING)); 
77                 } 
78             }; 
79             JRootPane root = dialog.getRootPane(); 
80             root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ESCAPE, CLOSE_ACTION_KEY); 
81             root.getActionMap().put(CLOSE_ACTION_KEY, dispatchClosing); 
82         }
83         
84         
85         /**
86          * Set the given button as the default button of the frame/dialog it is in.  The button
87          * must be first attached to the window component hierarchy.
88          * 
89          * @param button        the button to set as the default button.
90          */
91         public static void setDefaultButton(JButton button) {
92                 Window w = SwingUtilities.windowForComponent(button);
93                 if (w == null) {
94                         throw new IllegalArgumentException("Attach button to a window first.");
95                 }
96                 if (!(w instanceof RootPaneContainer)) {
97                         throw new IllegalArgumentException("Button not attached to RootPaneContainer, w="+w);
98                 }
99                 ((RootPaneContainer)w).getRootPane().setDefaultButton(button);
100         }
101
102         
103         
104         /**
105          * Change the behavior of a component so that TAB and Shift-TAB cycles the focus of
106          * the components.  This is necessary for e.g. <code>JTextArea</code>.
107          * 
108          * @param c             the component to modify
109          */
110     public static void setTabToFocusing(Component c) {
111         Set<KeyStroke> strokes = new HashSet<KeyStroke>(Arrays.asList(KeyStroke.getKeyStroke("pressed TAB")));
112         c.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, strokes);
113         strokes = new HashSet<KeyStroke>(Arrays.asList(KeyStroke.getKeyStroke("shift pressed TAB")));
114         c.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, strokes);
115     }
116
117     
118     public static void setWindowIcons(Window window) {
119         window.setIconImages(images);
120     }
121     
122     
123     /**
124      * A mouse listener that toggles the state of a boolean value in a table model
125      * when clicked on another column of the table.
126      * <p>
127      * NOTE:  If the table model does not extend AbstractTableModel, the model must
128      * fire a change event (which in normal table usage is not necessary).
129      * 
130      * @author Sampo Niskanen <sampo.niskanen@iki.fi>
131      */
132     public static class BooleanTableClickListener extends MouseAdapter {
133         
134         private final JTable table;
135         private final int clickColumn;
136         private final int booleanColumn;
137         
138         
139         public BooleanTableClickListener(JTable table) {
140                 this(table, 1, 0);
141         }
142
143         
144         public BooleanTableClickListener(JTable table, int clickColumn, int booleanColumn) {
145                 this.table = table;
146                 this.clickColumn = clickColumn;
147                 this.booleanColumn = booleanColumn;
148         }
149         
150                 @Override
151                 public void mouseClicked(MouseEvent e) {
152                         Point p = e.getPoint();
153                         int col = table.columnAtPoint(p);
154                         if (col < 0)
155                                 return;
156                         col = table.convertColumnIndexToModel(col);
157                         if (col != clickColumn) 
158                                 return;
159                         
160                         int row = table.rowAtPoint(p);
161                         if (row < 0)
162                                 return;
163                         row = table.convertRowIndexToModel(row);
164                         if (row < 0)
165                                 return;
166                         
167                         TableModel model = table.getModel();
168                         Object value = model.getValueAt(row, booleanColumn);
169                         
170                         if (!(value instanceof Boolean)) {
171                                 throw new IllegalStateException("Table value at row="+row+" col="+
172                                                 booleanColumn + " is not a Boolean, value=" +value);
173                         }
174                         
175                         Boolean b = (Boolean)value;
176                         b = !b;
177                         model.setValueAt(b, row, booleanColumn);
178                         if (model instanceof AbstractTableModel) {
179                                 ((AbstractTableModel)model).fireTableCellUpdated(row, booleanColumn);
180                         }
181                 }
182
183     }
184         
185 }