EMMA Coverage Report (generated Sat Oct 08 11:41:37 CEST 2011)
[all classes][net.sf.jomic.tools]

COVERAGE SUMMARY FOR SOURCE FILE [UiTools.java]

nameclass, %method, %block, %line, %
UiTools.java100% (1/1)95%  (21/22)88%  (1222/1386)94%  (282.3/301)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class UiTools100% (1/1)95%  (21/22)88%  (1222/1386)94%  (282.3/301)
getInvisibleCursor (): Cursor 0%   (0/1)0%   (0/28)0%   (0/5)
initColumnWidths (JTable): void 100% (1/1)62%  (96/156)86%  (21.5/25)
ifAnyMaskSetThenAppend (StringBuffer, int, int, int, String): void 100% (1/1)64%  (7/11)67%  (2/3)
<static initializer> 100% (1/1)68%  (17/25)70%  (1.4/2)
attemptToRemoveActionListener (AbstractButton, ActionListener): void 100% (1/1)71%  (10/14)88%  (3.5/4)
removeKeyStroke (JComponent, KeyStroke []): void 100% (1/1)72%  (44/61)71%  (10/14)
attemptToRemoveDocumentListener (JTextField, DocumentListener): void 100% (1/1)73%  (11/15)88%  (3.5/4)
addToKeyMap (int, String): void 100% (1/1)74%  (23/31)85%  (4.2/5)
addKeyStrokeAction (JComponent, String, Action): void 100% (1/1)81%  (21/26)93%  (4.6/5)
keyStrokeToString (KeyStroke): String 100% (1/1)88%  (132/150)93%  (20.5/22)
fillMnemonics (JMenuBar): void 100% (1/1)93%  (50/54)95%  (10.5/11)
fillMnemonics (JMenu): void 100% (1/1)95%  (73/77)97%  (17.5/18)
UiTools (): void 100% (1/1)100% (18/18)100% (6/6)
centerUp (Component): void 100% (1/1)100% (5/5)100% (2/2)
createDialogMainPanel (): JPanel 100% (1/1)100% (22/22)100% (6/6)
createRigidAreaBetweenButtons (): Component 100% (1/1)100% (4/4)100% (1/1)
getKeyText (int): String 100% (1/1)100% (69/69)100% (10/10)
instance (): UiTools 100% (1/1)100% (8/8)100% (3/3)
mnemonicable (JMenuItem): boolean 100% (1/1)100% (16/16)100% (6/6)
removeKeyStroke (InputMap, KeyStroke []): void 100% (1/1)100% (17/17)100% (4/4)
removeKeyStroke (InputMap, KeyStroke): void 100% (1/1)100% (21/21)100% (5/5)
setUpKeyMap (): void 100% (1/1)100% (558/558)100% (140/140)

1// Jomic - a viewer for comic book archives.
2// Copyright (C) 2004-2011 Thomas Aglassinger
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16package net.sf.jomic.tools;
17 
18import java.awt.BorderLayout;
19import java.awt.Component;
20import java.awt.Cursor;
21import java.awt.Dimension;
22import java.awt.Image;
23import java.awt.LayoutManager;
24import java.awt.Point;
25import java.awt.Toolkit;
26import java.awt.event.ActionListener;
27import java.awt.event.InputEvent;
28import java.awt.event.KeyEvent;
29import java.awt.image.MemoryImageSource;
30import java.util.HashMap;
31import java.util.LinkedList;
32import java.util.List;
33import java.util.Map;
34 
35import javax.swing.AbstractButton;
36import javax.swing.Action;
37import javax.swing.BorderFactory;
38import javax.swing.Box;
39import javax.swing.DefaultCellEditor;
40import javax.swing.InputMap;
41import javax.swing.JComponent;
42import javax.swing.JMenu;
43import javax.swing.JMenuBar;
44import javax.swing.JMenuItem;
45import javax.swing.JPanel;
46import javax.swing.JTable;
47import javax.swing.JTextField;
48import javax.swing.KeyStroke;
49import javax.swing.border.Border;
50import javax.swing.event.DocumentListener;
51import javax.swing.table.TableCellRenderer;
52import javax.swing.table.TableColumn;
53import javax.swing.table.TableModel;
54 
55import net.sf.jomic.common.PropertyConstants;
56 
57import org.apache.commons.logging.Log;
58import org.apache.commons.logging.LogFactory;
59 
60/**
61 *  User interface tools.
62 *
63 * @author    Thomas Aglassinger
64 */
65public final class UiTools
66{
67 
68    /**
69     *  Inset to use at the border of a JFrame or JDialog.
70     */
71    public static final int FRAME_INSET = 16;
72    private static final int CURSOR_SIZE = 16;
73    private static final int EMPTY_PIXELS_BETWEEN_BUTTONS = 6;
74    private static final int KEY_STROKE_HEX_DIGIT_COUNT = 8;
75    private static final int KEY_STROKE_TEXT_BUFFER_SIZE = 48;
76 
77    private static UiTools instance;
78    private static Cursor invisibleCursor;
79    private static Log logger = LogFactory.getLog(UiTools.class);
80 
81    private ErrorTools errorTools;
82    private Map keyMap;
83    private Dimension rigidAreaBetweenButtonsSize;
84    private StringTools stringTools;
85 
86    private UiTools() {
87        errorTools = ErrorTools.instance();
88        stringTools = StringTools.instance();
89        rigidAreaBetweenButtonsSize =
90                new Dimension(EMPTY_PIXELS_BETWEEN_BUTTONS, EMPTY_PIXELS_BETWEEN_BUTTONS);
91        setUpKeyMap();
92    }
93 
94    private void setUpKeyMap() {
95        keyMap = new HashMap();
96        addToKeyMap(KeyEvent.VK_COMMA, "COMMA");
97        addToKeyMap(KeyEvent.VK_PERIOD, "PERIOD");
98        addToKeyMap(KeyEvent.VK_SLASH, "SLASH");
99        addToKeyMap(KeyEvent.VK_SEMICOLON, "SEMICOLON");
100        addToKeyMap(KeyEvent.VK_EQUALS, "EQUALS");
101        addToKeyMap(KeyEvent.VK_OPEN_BRACKET, "OPEN_BRACKET");
102        addToKeyMap(KeyEvent.VK_BACK_SLASH, "BACK_SLASH");
103        addToKeyMap(KeyEvent.VK_CLOSE_BRACKET, "CLOSE_BRACKET");
104        addToKeyMap(KeyEvent.VK_ENTER, "ENTER");
105        addToKeyMap(KeyEvent.VK_BACK_SPACE, "BACK_SPACE");
106        addToKeyMap(KeyEvent.VK_TAB, "TAB");
107        addToKeyMap(KeyEvent.VK_CANCEL, "CANCEL");
108        addToKeyMap(KeyEvent.VK_CLEAR, "CLEAR");
109        addToKeyMap(KeyEvent.VK_SHIFT, "SHIFT");
110        addToKeyMap(KeyEvent.VK_CONTROL, "CONTROL");
111        addToKeyMap(KeyEvent.VK_ALT, "ALT");
112        addToKeyMap(KeyEvent.VK_PAUSE, "PAUSE");
113        addToKeyMap(KeyEvent.VK_CAPS_LOCK, "CAPS_LOCK");
114        addToKeyMap(KeyEvent.VK_ESCAPE, "ESCAPE");
115        addToKeyMap(KeyEvent.VK_SPACE, "SPACE");
116        addToKeyMap(KeyEvent.VK_PAGE_UP, "PAGE_UP");
117        addToKeyMap(KeyEvent.VK_PAGE_DOWN, "PAGE_DOWN");
118        addToKeyMap(KeyEvent.VK_END, "END");
119        addToKeyMap(KeyEvent.VK_HOME, "HOME");
120        addToKeyMap(KeyEvent.VK_LEFT, "LEFT");
121        addToKeyMap(KeyEvent.VK_UP, "UP");
122        addToKeyMap(KeyEvent.VK_RIGHT, "RIGHT");
123        addToKeyMap(KeyEvent.VK_DOWN, "DOWN");
124        addToKeyMap(KeyEvent.VK_MULTIPLY, "MULTIPLY");
125        addToKeyMap(KeyEvent.VK_ADD, "ADD");
126        addToKeyMap(KeyEvent.VK_SEPARATOR, "SEPARATOR");
127        addToKeyMap(KeyEvent.VK_SUBTRACT, "SUBTRACT");
128        addToKeyMap(KeyEvent.VK_DECIMAL, "DECIMAL");
129        addToKeyMap(KeyEvent.VK_DIVIDE, "DIVIDE");
130        addToKeyMap(KeyEvent.VK_DELETE, "DELETE");
131        addToKeyMap(KeyEvent.VK_NUM_LOCK, "NUM_LOCK");
132        addToKeyMap(KeyEvent.VK_SCROLL_LOCK, "SCROLL_LOCK");
133        addToKeyMap(KeyEvent.VK_F1, "F1");
134        addToKeyMap(KeyEvent.VK_F2, "F2");
135        addToKeyMap(KeyEvent.VK_F3, "F3");
136        addToKeyMap(KeyEvent.VK_F4, "F4");
137        addToKeyMap(KeyEvent.VK_F5, "F5");
138        addToKeyMap(KeyEvent.VK_F6, "F6");
139        addToKeyMap(KeyEvent.VK_F7, "F7");
140        addToKeyMap(KeyEvent.VK_F8, "F8");
141        addToKeyMap(KeyEvent.VK_F9, "F9");
142        addToKeyMap(KeyEvent.VK_F10, "F10");
143        addToKeyMap(KeyEvent.VK_F11, "F11");
144        addToKeyMap(KeyEvent.VK_F12, "F12");
145        addToKeyMap(KeyEvent.VK_F13, "F13");
146        addToKeyMap(KeyEvent.VK_F14, "F14");
147        addToKeyMap(KeyEvent.VK_F15, "F15");
148        addToKeyMap(KeyEvent.VK_F16, "F16");
149        addToKeyMap(KeyEvent.VK_F17, "F17");
150        addToKeyMap(KeyEvent.VK_F18, "F18");
151        addToKeyMap(KeyEvent.VK_F19, "F19");
152        addToKeyMap(KeyEvent.VK_F20, "F20");
153        addToKeyMap(KeyEvent.VK_F21, "F21");
154        addToKeyMap(KeyEvent.VK_F22, "F22");
155        addToKeyMap(KeyEvent.VK_F23, "F23");
156        addToKeyMap(KeyEvent.VK_F24, "F24");
157        addToKeyMap(KeyEvent.VK_PRINTSCREEN, "PRINTSCREEN");
158        addToKeyMap(KeyEvent.VK_INSERT, "INSERT");
159        addToKeyMap(KeyEvent.VK_HELP, "HELP");
160        addToKeyMap(KeyEvent.VK_META, "META");
161        addToKeyMap(KeyEvent.VK_BACK_QUOTE, "BACK_QUOTE");
162        addToKeyMap(KeyEvent.VK_QUOTE, "QUOTE");
163        addToKeyMap(KeyEvent.VK_KP_UP, "KP_UP");
164        addToKeyMap(KeyEvent.VK_KP_DOWN, "KP_DOWN");
165        addToKeyMap(KeyEvent.VK_KP_LEFT, "KP_LEFT");
166        addToKeyMap(KeyEvent.VK_KP_RIGHT, "KP_RIGHT");
167        addToKeyMap(KeyEvent.VK_DEAD_GRAVE, "DEAD_GRAVE");
168        addToKeyMap(KeyEvent.VK_DEAD_ACUTE, "DEAD_ACUTE");
169        addToKeyMap(KeyEvent.VK_DEAD_CIRCUMFLEX, "DEAD_CIRCUMFLEX");
170        addToKeyMap(KeyEvent.VK_DEAD_TILDE, "DEAD_TILDE");
171        addToKeyMap(KeyEvent.VK_DEAD_MACRON, "DEAD_MACRON");
172        addToKeyMap(KeyEvent.VK_DEAD_BREVE, "DEAD_BREVE");
173        addToKeyMap(KeyEvent.VK_DEAD_ABOVEDOT, "DEAD_ABOVEDOT");
174        addToKeyMap(KeyEvent.VK_DEAD_DIAERESIS, "DEAD_DIAERESIS");
175        addToKeyMap(KeyEvent.VK_DEAD_ABOVERING, "DEAD_ABOVERING");
176        addToKeyMap(KeyEvent.VK_DEAD_DOUBLEACUTE, "DEAD_DOUBLEACUTE");
177        addToKeyMap(KeyEvent.VK_DEAD_CARON, "DEAD_CARON");
178        addToKeyMap(KeyEvent.VK_DEAD_CEDILLA, "DEAD_CEDILLA");
179        addToKeyMap(KeyEvent.VK_DEAD_OGONEK, "DEAD_OGONEK");
180        addToKeyMap(KeyEvent.VK_DEAD_IOTA, "DEAD_IOTA");
181        addToKeyMap(KeyEvent.VK_DEAD_VOICED_SOUND, "DEAD_VOICED_SOUND");
182        addToKeyMap(KeyEvent.VK_DEAD_SEMIVOICED_SOUND, "DEAD_SEMIVOICED_SOUND");
183        addToKeyMap(KeyEvent.VK_AMPERSAND, "AMPERSAND");
184        addToKeyMap(KeyEvent.VK_ASTERISK, "ASTERISK");
185        addToKeyMap(KeyEvent.VK_QUOTEDBL, "QUOTEDBL");
186        addToKeyMap(KeyEvent.VK_LESS, "LESS");
187        addToKeyMap(KeyEvent.VK_GREATER, "GREATER");
188        addToKeyMap(KeyEvent.VK_BRACELEFT, "BRACELEFT");
189        addToKeyMap(KeyEvent.VK_BRACERIGHT, "BRACERIGHT");
190        addToKeyMap(KeyEvent.VK_AT, "AT");
191        addToKeyMap(KeyEvent.VK_COLON, "COLON");
192        addToKeyMap(KeyEvent.VK_CIRCUMFLEX, "CIRCUMFLEX");
193        addToKeyMap(KeyEvent.VK_DOLLAR, "DOLLAR");
194        addToKeyMap(KeyEvent.VK_EURO_SIGN, "EURO_SIGN");
195        addToKeyMap(KeyEvent.VK_EXCLAMATION_MARK, "EXCLAMATION_MARK");
196        addToKeyMap(KeyEvent.VK_INVERTED_EXCLAMATION_MARK, "INVERTED_EXCLAMATION_MARK");
197        addToKeyMap(KeyEvent.VK_LEFT_PARENTHESIS, "LEFT_PARENTHESIS");
198        addToKeyMap(KeyEvent.VK_NUMBER_SIGN, "NUMBER_SIGN");
199        addToKeyMap(KeyEvent.VK_MINUS, "MINUS");
200        addToKeyMap(KeyEvent.VK_PLUS, "PLUS");
201        addToKeyMap(KeyEvent.VK_RIGHT_PARENTHESIS, "RIGHT_PARENTHESIS");
202        addToKeyMap(KeyEvent.VK_UNDERSCORE, "UNDERSCORE");
203        addToKeyMap(KeyEvent.VK_FINAL, "FINAL");
204        addToKeyMap(KeyEvent.VK_CONVERT, "CONVERT");
205        addToKeyMap(KeyEvent.VK_NONCONVERT, "NONCONVERT");
206        addToKeyMap(KeyEvent.VK_ACCEPT, "ACCEPT");
207        addToKeyMap(KeyEvent.VK_MODECHANGE, "MODECHANGE");
208        addToKeyMap(KeyEvent.VK_KANA, "KANA");
209        addToKeyMap(KeyEvent.VK_KANJI, "KANJI");
210        addToKeyMap(KeyEvent.VK_ALPHANUMERIC, "ALPHANUMERIC");
211        addToKeyMap(KeyEvent.VK_KATAKANA, "KATAKANA");
212        addToKeyMap(KeyEvent.VK_HIRAGANA, "HIRAGANA");
213        addToKeyMap(KeyEvent.VK_FULL_WIDTH, "FULL_WIDTH");
214        addToKeyMap(KeyEvent.VK_HALF_WIDTH, "HALF_WIDTH");
215        addToKeyMap(KeyEvent.VK_ROMAN_CHARACTERS, "ROMAN_CHARACTERS");
216        addToKeyMap(KeyEvent.VK_ALL_CANDIDATES, "ALL_CANDIDATES");
217        addToKeyMap(KeyEvent.VK_PREVIOUS_CANDIDATE, "PREVIOUS_CANDIDATE");
218        addToKeyMap(KeyEvent.VK_CODE_INPUT, "CODE_INPUT");
219        addToKeyMap(KeyEvent.VK_JAPANESE_KATAKANA, "JAPANESE_KATAKANA");
220        addToKeyMap(KeyEvent.VK_JAPANESE_HIRAGANA, "JAPANESE_HIRAGANA");
221        addToKeyMap(KeyEvent.VK_JAPANESE_ROMAN, "JAPANESE_ROMAN");
222        addToKeyMap(KeyEvent.VK_KANA_LOCK, "KANA_LOCK");
223        addToKeyMap(KeyEvent.VK_INPUT_METHOD_ON_OFF, "INPUT_METHOD_ON_OFF");
224        addToKeyMap(KeyEvent.VK_AGAIN, "AGAIN");
225        addToKeyMap(KeyEvent.VK_UNDO, "UNDO");
226        addToKeyMap(KeyEvent.VK_COPY, "COPY");
227        addToKeyMap(KeyEvent.VK_PASTE, "PASTE");
228        addToKeyMap(KeyEvent.VK_CUT, "CUT");
229        addToKeyMap(KeyEvent.VK_FIND, "FIND");
230        addToKeyMap(KeyEvent.VK_PROPS, "PROPS");
231        addToKeyMap(KeyEvent.VK_STOP, "STOP");
232        addToKeyMap(KeyEvent.VK_COMPOSE, "COMPOSE");
233        addToKeyMap(KeyEvent.VK_ALT_GRAPH, "ALT_GRAPH");
234    }
235 
236    /**
237     *  Get an invisible Cursor. (Based on code by R?al Gagnon, see <a
238     *  href="http://www.rgagnon.com/javadetails/java-0440.html">
239     *  http://www.rgagnon.com/javadetails/java-0440.html</a> for details.
240     */
241    public synchronized Cursor getInvisibleCursor() {
242        if (invisibleCursor == null) {
243            int[] pixels = new int[CURSOR_SIZE * CURSOR_SIZE];
244            Image image = Toolkit.getDefaultToolkit().createImage(
245                    new MemoryImageSource(CURSOR_SIZE, CURSOR_SIZE, pixels, 0, CURSOR_SIZE));
246 
247            invisibleCursor = Toolkit.getDefaultToolkit().createCustomCursor(image,
248                    new Point(0, 0), "invisiblecursor");
249        }
250        return invisibleCursor;
251    }
252 
253    /**
254     *  Get (English) text for keyboard code.
255     */
256    public String getKeyText(int keyCode) {
257        String result;
258 
259        if ((keyCode >= KeyEvent.VK_0) && (keyCode <= KeyEvent.VK_9)
260                || (keyCode >= KeyEvent.VK_A) && (keyCode <= KeyEvent.VK_Z)) {
261            result = String.valueOf((char) keyCode);
262        } else {
263            result = (String) keyMap.get(new Integer(keyCode));
264            if (result == null) {
265                if (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9) {
266                    char c = (char) (keyCode - KeyEvent.VK_NUMPAD0 + '0');
267 
268                    result = "NUMPAD" + c;
269                } else {
270                    result = "unknown(" + stringTools.hexString(keyCode, KEY_STROKE_HEX_DIGIT_COUNT) + ")";
271                }
272            }
273        }
274 
275        return result;
276    }
277 
278    public static synchronized UiTools instance() {
279        if (instance == null) {
280            instance = new UiTools();
281        }
282        return instance;
283    }
284 
285    public void addKeyStrokeAction(JComponent component, String keyStrokeName, Action action) {
286        String command = (String) action.getValue(Action.NAME);
287 
288        assert command != null : "action must have a name";
289        component.getInputMap().put(KeyStroke.getKeyStroke(keyStrokeName), command);
290        component.getActionMap().put(command, action);
291    }
292 
293    /**
294     *  Provided that <code>button</code> is not null, remove <code>listener</code> from it.
295     */
296    public void attemptToRemoveActionListener(AbstractButton button, ActionListener listener) {
297        assert listener != null;
298 
299        if (button != null) {
300            button.removeActionListener(listener);
301        }
302    }
303 
304    /**
305     *  Provided that <code>field</code> is not null, remove <code>listener</code> from its <code>Document</code>
306     *  .
307     */
308    public void attemptToRemoveDocumentListener(JTextField field, DocumentListener listener) {
309        assert listener != null;
310 
311        if (field != null) {
312            field.getDocument().removeDocumentListener(listener);
313        }
314    }
315 
316    /**
317     *  Center frame in upper half of the screen.
318     */
319    public void centerUp(Component frame) {
320        errorTools.centerUp(frame);
321    }
322 
323    public JPanel createDialogMainPanel() {
324        JPanel result = new JPanel();
325        Border border = BorderFactory.createEmptyBorder(FRAME_INSET, FRAME_INSET, FRAME_INSET, FRAME_INSET);
326        LayoutManager layout = new BorderLayout();
327 
328        result.setBorder(border);
329        result.setLayout(layout);
330        return result;
331    }
332 
333    /**
334     *  Create ridig area to put "some" space between two buttons in a BoxLayout.
335     *
336     * @see    Box#createRigidArea(java.awt.Dimension)
337     */
338    public Component createRigidAreaBetweenButtons() {
339        return Box.createRigidArea(rigidAreaBetweenButtonsSize);
340    }
341 
342    /**
343     *  Set mnemonics in <code>menu</code> depending on the labels of the MenuItems.
344     */
345    public void fillMnemonics(JMenu menu) {
346        assert menu != null;
347        int itemCount = menu.getItemCount();
348        List labelList = new LinkedList();
349 
350        for (int i = 0; i < itemCount; i += 1) {
351            JMenuItem item = menu.getItem(i);
352 
353            if (mnemonicable(item)) {
354                String label = item.getText();
355 
356                labelList.add(label);
357            }
358        }
359 
360        String[] labels = (String[]) labelList.toArray(new String[0]);
361        char[] mnemonics = stringTools.getMnemonics(labels, null);
362        int j = 0;
363 
364        for (int i = 0; i < itemCount; i += 1) {
365            JMenuItem item = menu.getItem(i);
366 
367            if (mnemonicable(item)) {
368                if (!Boolean.getBoolean(
369                        PropertyConstants.SYSTEM_PROPERTY_PREFIX + PropertyConstants.HIDE_MNEMONICS)) {
370                    item.setMnemonic(mnemonics[j]);
371                }
372                j += 1;
373            }
374        }
375    }
376 
377    /**
378     *  Set mnemonics in <code>bar</code> depending on the labels of the Menus and MenuItems.
379     */
380    public void fillMnemonics(JMenuBar bar) {
381        assert bar != null;
382        int menuCount = bar.getMenuCount();
383        String[] labels = new String[menuCount];
384 
385        for (int i = 0; i < menuCount; i += 1) {
386            labels[i] = bar.getMenu(i).getText();
387        }
388 
389        char[] mnemonics = stringTools.getMnemonics(labels, null);
390 
391        for (int i = 0; i < menuCount; i += 1) {
392            JMenu menu = bar.getMenu(i);
393 
394            menu.setMnemonic(mnemonics[i]);
395            fillMnemonics(menu);
396        }
397    }
398 
399    /**
400     *  This method picks good column sizes. If all column heads are wider than the column's cells'
401     *  contents, then you can just use column.sizeWidthToFit().
402     */
403    public void initColumnWidths(JTable table) {
404        assert table != null;
405        TableModel tableModel = table.getModel();
406        TableColumn columnModel = null;
407        Component componet = null;
408        int headerWidth = 0;
409        int cellWidth = 0;
410        TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
411 
412        if (logger.isDebugEnabled()) {
413            logger.debug("init widths of " + table.getColumnCount() + "x" + table.getRowCount() + " table");
414        }
415 
416        for (int column = 0; column < table.getColumnCount(); column += 1) {
417            columnModel = table.getColumnModel().getColumn(column);
418 
419            componet = headerRenderer.getTableCellRendererComponent(
420                    null, columnModel.getHeaderValue(), false, false, 0, 0);
421            headerWidth = componet.getPreferredSize().width;
422 
423            int maxCellWidth = 0;
424 
425            for (int row = 0; row < table.getRowCount(); row += 1) {
426                componet =
427                        table.getDefaultRenderer(tableModel.getColumnClass(column)).getTableCellRendererComponent(
428                        table,
429                        table.getValueAt(row, column),
430                        false,
431                        false,
432                        0,
433                        column);
434                cellWidth = componet.getPreferredSize().width;
435                if (logger.isDebugEnabled()) {
436                    logger.debug("cellwidth(" + column + "," + row + ")=" + cellWidth);
437                }
438                if (cellWidth > maxCellWidth) {
439                    maxCellWidth = cellWidth;
440                }
441            }
442 
443            if (logger.isDebugEnabled()) {
444                logger.debug(
445                        "initializing width of column "
446                        + column
447                        + ". "
448                        + "headerWidth = "
449                        + headerWidth
450                        + "; maxCellWidth = "
451                        + maxCellWidth);
452            }
453            columnModel.setPreferredWidth(Math.max(headerWidth, maxCellWidth));
454        }
455    }
456 
457    /**
458     *  <p>
459     *
460     *  Get a string that is parseably by <code>KeyStroke.getKeyStroke()</code>. (<code>KeyStroke.toString()</code>
461     *  does not return such a string.)</p> <p>
462     *
463     *  However, there is one keystroke that cannot be represented as a string that can be parsed
464     *  back to a keystroke - a typed space character. In order to bind an action to a typed space
465     *  character, <code>KeyStroke.getKeyStroke(new Character(' '), 0)</code> needs to be called.
466     *  </p> Source: <a href="http://javaalmanac.com/egs/javax.swing/Key2Str.html">The Java
467     *  Developers Almanac 1.4</a> .
468     *
469     * @see    KeyStroke#getKeyStroke(java.lang.String)
470     */
471    public String keyStrokeToString(KeyStroke keyStroke) {
472        assert keyStroke != null;
473 
474        StringBuffer result = new StringBuffer(KEY_STROKE_TEXT_BUFFER_SIZE);
475        int modifiers = keyStroke.getModifiers();
476 
477        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_MASK, "shift ");
478        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_MASK, "ctrl ");
479        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.META_DOWN_MASK, InputEvent.META_MASK, "meta ");
480        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_MASK, "alt ");
481        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON1_MASK, "button1 ");
482        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.BUTTON2_DOWN_MASK, InputEvent.BUTTON2_MASK, "button2 ");
483        ifAnyMaskSetThenAppend(result, modifiers, InputEvent.BUTTON3_DOWN_MASK, InputEvent.BUTTON3_MASK, "button3 ");
484 
485        int type = keyStroke.getKeyEventType();
486 
487        if (type == KeyEvent.KEY_TYPED) {
488            result.append("typed ");
489            result.append(keyStroke.getKeyChar() + " ");
490        } else if (type == KeyEvent.KEY_PRESSED) {
491            result.append("pressed ");
492            result.append(getKeyText(keyStroke.getKeyCode()) + " ");
493        } else if (type == KeyEvent.KEY_RELEASED) {
494            result.append("released ");
495            result.append(getKeyText(keyStroke.getKeyCode()) + " ");
496        } else {
497            assert false : "keyEventType=" + type;
498        }
499 
500        return result.toString().trim();
501    }
502 
503    /**
504     *  Remove for a JComponent all keyStrokes. Based on a suggestion in a <a
505     *  href="http://forum.java.sun.com/thread.jsp?thread=462430&forum=57&message=2121002">thread
506     *  </a> in Sun's developer forum.
507     */
508    public void removeKeyStroke(JComponent component, KeyStroke[] keyStrokes) {
509        removeKeyStroke(component.getInputMap(JComponent.WHEN_FOCUSED), keyStrokes);
510        removeKeyStroke(component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT), keyStrokes);
511        removeKeyStroke(component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW), keyStrokes);
512        if (component instanceof JTable) {
513            // HACK: Stop VK_LEFT/RIGHT from working on the cell editor.
514            JTable table = (JTable) component;
515            DefaultCellEditor editor = (DefaultCellEditor) table.getCellEditor(0, 0);
516            JComponent editorComponent = (JComponent) editor.getComponent();
517 
518            removeKeyStroke(editorComponent, keyStrokes);
519        }
520        int ub = component.getComponentCount();
521 
522        for (int i = 0; i < ub; i += 1) {
523            Component child = component.getComponent(i);
524 
525            if (child instanceof JComponent) {
526                removeKeyStroke((JComponent) child, keyStrokes);
527            }
528        }
529    }
530 
531    private void addToKeyMap(int keyCode, String text) {
532        assert text != null;
533        Integer integerKeyCode = new Integer(keyCode);
534 
535        assert !keyMap.containsKey(integerKeyCode);
536        keyMap.put(integerKeyCode, text);
537    }
538 
539    /**
540     *  If in <code>value</code> any of the bit masks <code>mask1</code> or <code>mask2</code> is
541     *  enabled, append to the buffer <code>target</code> the text <code>textToAppend</code>.
542     *
543     * @see    #keyStrokeToString(KeyStroke)
544     */
545    private void ifAnyMaskSetThenAppend(StringBuffer target, int value, int mask1, int mask2, String textToAppend) {
546        if ((value & (mask1 | mask2)) != 0) {
547            target.append(textToAppend);
548        }
549    }
550 
551    /**
552     *  Is there any point in giving a mnemonic to a JMenuItem? Possible reasons for not setting a
553     *  mnemonic:
554     *  <ol>
555     *    <li> item is a separator
556     *    <li> item has no label (but only an icon)
557     *  </ol>
558     *
559     */
560    private boolean mnemonicable(JMenuItem item) {
561        boolean result = false;
562 
563        if (item != null) {
564            String label = item.getText();
565 
566            if ((label != null) && (label.length() > 0)) {
567                result = true;
568            }
569        }
570        return result;
571    }
572 
573    private void removeKeyStroke(InputMap im, KeyStroke[] keyStrokes) {
574        for (int i = 0; i < keyStrokes.length; i += 1) {
575            KeyStroke k = keyStrokes[i];
576 
577            removeKeyStroke(im, k);
578        }
579    }
580 
581    private void removeKeyStroke(InputMap inputMap, KeyStroke keyStroke) {
582        Object key = inputMap.get(keyStroke);
583 
584        if (key != null) {
585            logger.debug("remove KeyStroke for key " + key);
586            inputMap.put(keyStroke, "none");
587        }
588    }
589}

[all classes][net.sf.jomic.tools]
EMMA 2.0.4217 (C) Vladimir Roubtsov