Source code: jpl2/common/gui/SwingToolkit.java
1 /***********************************************************************
2 * JavaPsionLink 2.0, a java implementation of the psion link protocol
3 * Copyright (C) 2002, 2003 John S Montgomery (john.montgomery@lineone.net)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2.1 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ************************************************************************/
19 package jpl2.common.gui;
20
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import javax.swing.*;
26 import javax.swing.border.*;
27 import javax.swing.text.*;
28 import javax.swing.event.*;
29
30 import java.io.File;
31
32 public class SwingToolkit extends JPLToolkit implements SwingConstants {
33 private JFileChooser chooseFolder = null;
34 private JFileChooser saveFile = null;
35 private JFileChooser openFile = null;
36 private int windowCount = 0;
37
38 public SwingToolkit() throws ClassNotFoundException {
39 // attempt to load a swing class to see if swing
40 // is installed
41 Class clazz = Class.forName( "javax.swing.JFrame" );
42
43 // if we are on a mac make it have the menu at the top of the screen
44 if ( System.getProperty("mrj.version") != null ) {
45 try {
46 // just in case this messes up it's in a try block
47 System.setProperty("com.apple.macos.useScreenMenuBar","true");
48 }
49 catch( Throwable t ) {}
50 try {
51 // just in case this messes up it's in a try block
52 System.setProperty("apple.laf.useScreenMenuBar","true");
53 }
54 catch( Throwable t ) {}
55 }
56 }
57
58 /** Returns either a java.awt.Frame or a javax.swing.JFrame
59 **/
60 protected Frame makeFrameImp() {
61 JFrame frame = new JFrame();
62 frame.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
63 frame.addWindowListener(
64 new WindowAdapter() {
65
66 public void windowClosing( WindowEvent we ) {
67 we.getWindow().dispose();
68 synchronized( getToolkit() ) {
69 windowCount--;
70 }
71 }
72
73 public void windowClosed( WindowEvent we ) {
74 synchronized( getToolkit() ) {
75 if ( windowCount <= 0 )
76 System.exit( 0 );
77 }
78 }
79
80
81 } );
82
83 synchronized( getToolkit() ) {
84 windowCount++;
85 }
86 return frame;
87 }
88
89
90 /** Returns either a java.awt.Dialog or a javax.swing.JDialog
91 **/
92 protected Dialog makeDialogImp( Frame parent, boolean modal ) {
93 return new JDialog( parent, "", modal );
94 }
95
96 /** Adds a component to a window. In the case of swing getContentPane() must be used.
97 **/
98 public void add( Window w, Component c ) {
99 if ( w instanceof JFrame )
100 ((JFrame)w).getContentPane().add( c );
101 else
102 ((JDialog)w).getContentPane().add( c );
103 }
104
105 /** Adds a component to a window. In the case of swing getContentPane() must be used.
106 **/
107 public void add( Window w, Component c, Object constraints ) {
108 if ( w instanceof JFrame )
109 ((JFrame)w).getContentPane().add( c, constraints );
110 else
111 ((JDialog)w).getContentPane().add( c, constraints );
112 }
113
114 /** Sets a layout for a window. In the case of swing getContentPane() must be used.
115 **/
116 public void setLayout( Window w, LayoutManager l ) {
117 if ( w instanceof JFrame )
118 ((JFrame)w).getContentPane().setLayout( l );
119 else
120 ((JDialog)w).getContentPane().setLayout( l );
121 }
122
123 /** Returns either a java.awt.Panel or a javax.swing.JPanel.
124 **/
125 public Container makePanel() {
126 return new JPanel();
127 }
128
129 /** Returns either a java.awt.Panel or a javax.swing.JPanel.
130 **/
131 protected Container makeGroupPanelImp( String title ) {
132 JPanel panel = new JPanel();
133 Border border = BorderFactory.createTitledBorder( title );
134 panel.setBorder( border );
135 return panel;
136 }
137
138 /** Returns either a java.awt.Button or a javax.swing.JButton.
139 **/
140 protected Component makeButtonImp( String text, String action, ActionListener listener ) {
141 JButton button = new JButton( text );
142 button.setActionCommand( action );
143 button.addActionListener( listener );
144 return button;
145 }
146
147 // add a keylistener to everythnig in the component
148 private void addKeyListener( Component c, KeyListener kl ) {
149 c.addKeyListener( kl );
150 if ( c instanceof Container ) {
151 Component[] cs = ((Container)c).getComponents();
152 for ( int i = 0; i < cs.length; i++ )
153 addKeyListener( cs[ i ], kl );
154 }
155 }
156
157 /** Make the button the default on a dialog.
158 **/
159 public void setDefaultButton( Dialog dialog, Component button ) {
160 ((JDialog)dialog).getRootPane().setDefaultButton( (JButton)button );
161 }
162
163 /** Make the button the "cancel" button on a dialog. ie the button
164 * which dismisses the dialog without takign any action.
165 **/
166 public void setCancelButton( Dialog dialog, Component button ) {
167 setButtonKey( dialog, button, KeyEvent.VK_ESCAPE );
168 }
169
170 /** Associate a key press with the button. ie so a key can be pressed instead of
171 * using the mouse to press the button.
172 **/
173 public void setButtonKey( Dialog dialog, Component button, int keyCode ) {
174 ((JButton)button).setMnemonic( keyCode );
175 ButtonKeyAdapter adapter = new ButtonKeyAdapter( button, keyCode );
176 addKeyListener( dialog, adapter );
177 }
178
179 /** Make the button the default on a frame.
180 **/
181 public void setDefaultButton( Frame frame, Component button ) {
182 ((JFrame)frame).getRootPane().setDefaultButton( (JButton)button );
183 }
184
185 /** Make the button the "cancel" button on a frame. ie the button
186 * which dismisses the frame without taking any action.
187 **/
188 public void setCancelButton( Frame frame, Component button ){
189 setButtonKey( frame, button, KeyEvent.VK_ESCAPE );
190 }
191
192 /** Associate a key press with the button. ie so a key can be pressed instead of
193 * using the mouse to press the button.
194 **/
195 public void setButtonKey( Frame frame, Component button, int keyCode ) {
196 ((JButton)button).setMnemonic( keyCode );
197 ButtonKeyAdapter adapter = new ButtonKeyAdapter( button, keyCode );
198 addKeyListener( frame, adapter );
199 }
200
201 /** Returns either a java.awt.Label or a javax.swing.JLabel.
202 **/
203 protected Component makeLabelImp( String text, int horizontalAlignment ) {
204 switch( horizontalAlignment ) {
205 case Label.LEFT:
206 horizontalAlignment = LEFT;
207 break;
208 case Label.RIGHT:
209 horizontalAlignment = RIGHT;
210 break;
211 case Label.CENTER:
212 horizontalAlignment = CENTER;
213 break;
214 }
215 return new JLabel( text, horizontalAlignment );
216 }
217
218 /** Sets the text on what may be a button or a label.
219 **/
220 protected void setTextImp( Component c, String text ) {
221 if ( c instanceof AbstractButton ) {
222 ((AbstractButton)c).setText( text );
223 }
224 else if ( c instanceof JLabel ) {
225 ((JLabel)c).setText( text );
226 }
227 else {
228 ((JTextComponent)c).setText( text );
229 }
230 }
231
232 /** Returns either a java.awt.MenuBar or a javax.swing.JMenuBar.
233 **/
234 public Object makeMenuBar() {
235 return new JMenuBar();
236 }
237
238 /** Sets a frames menu bar.
239 **/
240 public void setMenuBar( Frame frame, Object menuBar ) {
241 ((JFrame)frame).setJMenuBar( (JMenuBar)menuBar );
242 }
243
244 /** Returns either a java.awt.Menu or a javax.swing.JMenu.
245 **/
246 protected Object makeMenuImp( String label ) {
247 return new JMenu( label );
248 }
249
250 /** Insert a seperator/divider into the menu.
251 **/
252 public void addSeparator( Object menu ) {
253 ((JMenu)menu).addSeparator();
254 }
255
256 /** Remove all items from a menu.
257 **/
258 public void removeAll( Object menu ) {
259 ((JMenu)menu).removeAll();
260 }
261
262 /** Add a menu to a menu bar.
263 **/
264 public void addMenu( Object menuBar, Object menu ) {
265 ((JMenuBar)menuBar).add( (JMenu)menu );
266 }
267
268 /** Set the help menu on a menu bar.
269 **/
270 public void setHelpMenu( Object menuBar, Object menu ) {
271 // older swing does not always have this
272 // implemented and may throw an error
273 try {
274 ((JMenuBar)menuBar).setHelpMenu( (JMenu)menu );
275 }
276 catch( Throwable t ) {
277 addMenu( menuBar, menu );
278 }
279 }
280
281 /** Returns either a java.awt.MenuItem or a javax.swing.JMenuItem.
282 **/
283 protected Object makeMenuItemImp( String label, MenuShortcut s, String action, ActionListener listener ) {
284
285 JMenuItem item = new JMenuItem( label );
286 item.addActionListener( listener );
287 item.setActionCommand( action );
288
289 if ( s != null ) {
290 Toolkit tk = Toolkit.getDefaultToolkit();
291 int modifiers = tk.getMenuShortcutKeyMask();
292 if ( s.usesShiftModifier() )
293 modifiers |= KeyEvent.SHIFT_MASK;
294 item.setAccelerator( KeyStroke.getKeyStroke( s.getKey(), modifiers ) );
295 }
296
297 return item;
298 }
299
300 /** Add a menu item to a menu.
301 **/
302 public void addMenuItem( Object menu, Object menuItem ) {
303 ((JMenu)menu).add( (JMenuItem)menuItem );
304 }
305
306 /** Enable disable a menu/menuitem.
307 **/
308 public void setEnabled( Object menuItem, boolean enabled ) {
309 ((JMenuItem)menuItem).setEnabled( enabled );
310 }
311
312 /** Returns either a java.awt.ScrollPane of a javax.swing.JScrollPane.
313 **/
314 public Container makeScrollPane( Component contents ) {
315 return new JScrollPane( contents );
316 }
317
318 /** Returns the viewport size of a scrollpane.
319 **/
320 public Dimension getViewportSize( Container scrollpane ) {
321 JViewport viewPort = ((JScrollPane)scrollpane).getViewport();
322 return viewPort.getExtentSize();
323 }
324
325 /** Returns the scroll position of a scrollpane.
326 **/
327 public Point getScrollPosition( Container scrollpane ) {
328 JViewport viewPort = ((JScrollPane)scrollpane).getViewport();
329 return viewPort.getViewPosition();
330 }
331
332 /** Sets the scroll position of a scrollpane.
333 **/
334 public void setScrollPosition( Container scrollpane, int x, int y ) {
335 JViewport viewPort = ((JScrollPane)scrollpane).getViewport();
336 viewPort.setViewPosition( new Point( x, y ) );
337 }
338
339 /** Returns either a java.awt.Choice or a javax.swing.JComboBox.
340 **/
341 public Component makeChoice( String[] items, ItemListener itemListener ) {
342 JComboBox choice = new JComboBox( items );
343 if ( itemListener != null )
344 choice.addItemListener( itemListener );
345 return choice;
346 }
347
348 /** Set the items on a choice.
349 **/
350 public void setChoiceItems( Component choice, String[] items ) {
351 JComboBox jchoice = (JComboBox)choice;
352 jchoice.removeAllItems();
353 for ( int i = 0; i < items.length; i++ ) {
354 jchoice.addItem( items[ i ] );
355 }
356 }
357
358 /** Returns either a java.awt.List or a javax.swing.JList.
359 **/
360 public Component makeList( String[] items, ItemListener itemListener ) {
361 JPLList list = new JPLList( items );
362 list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
363
364 if ( itemListener != null )
365 list.addItemListener( itemListener );
366 return new JScrollPane( list );
367 }
368
369 private JList getJList( Component list ) {
370 return (JList)((JScrollPane)list).getViewport().getComponent( 0 );
371 }
372
373 /** Set the items on a list.
374 **/
375 public void setListItems( Component list, String[] items ) {
376 JList jlist = getJList( list );
377 jlist.setListData( items );
378 }
379
380 /** Set the currently selected item on a choice.
381 **/
382 public void setSelected( Component choice, String item ) {
383 if ( choice instanceof JComboBox ) {
384 JComboBox jchoice = (JComboBox)choice;
385 for ( int i = 0; i < jchoice.getItemCount(); i++ ) {
386 Object itemi = jchoice.getItemAt( i );
387 if ( itemi.equals( item ) ) {
388 jchoice.setSelectedIndex( i );
389 break;
390 }
391 }
392 }
393 else {
394 try {
395 JList jlist = getJList( choice );
396 jlist.setSelectedValue( item, true );
397 }
398 catch( Exception e ){} // if item is not in list
399 }
400 }
401
402 /** Get the currently selected item on a choice.
403 **/
404 public String getSelected( Component choice ) {
405
406 if ( choice instanceof JComboBox )
407 return (String)((JComboBox)choice).getSelectedItem();
408 else
409 return (String)getJList(choice).getSelectedValue();
410
411 }
412
413 /** Get the currently selected item on a choice.
414 **/
415 public int getSelectedIndex( Component choice ) {
416 if ( choice instanceof JComboBox )
417 return ((JComboBox)choice).getSelectedIndex();
418 else
419 return getJList( choice).getSelectedIndex();
420 }
421
422 /** Returns either a ProgressBar or a javax.swing.JProgressBar.
423 **/
424 public Component makeProgressBar() {
425 return new JProgressBar( HORIZONTAL, 0, 100 );
426 }
427
428 /** Set the max value on a progress bar.
429 **/
430 public void setProgressBarMax( Component progressBar, int max ) {
431 ((JProgressBar)progressBar).setMaximum( max );
432 }
433
434 /** Set the current value of a progress bar.
435 **/
436 public void setProgressBarValue( Component progressBar, int value ) {
437 ((JProgressBar)progressBar).setValue( value );
438 }
439
440
441 /** Returns either a java.awt.TextField or a javax.swing.JTextField.
442 **/
443 public Component makeTextField( String text, int columns, TextListener listener ) {
444 JTextField textField = new JTextField( text, columns );
445 if ( listener != null ) {
446 Document doc = textField.getDocument();
447 doc.addDocumentListener( new TextDocListener( textField, listener ) );
448 }
449
450 return textField;
451 }
452
453 public void setEditable( Component textField, boolean editable ) {
454 ((JTextField)textField).setEditable( editable );
455 }
456
457 /** Get the text from a text field.
458 **/
459 public String getText( Component textField ) {
460 return ((JTextField)textField).getText();
461 }
462
463 /** Returns either a java.awt.Checkbox or a javax.swing.JCheckBox
464 **/
465 protected Component makeCheckBoxImpl( String label, ItemListener listener ) {
466 JCheckBox checkBox = new JCheckBox( label );
467 if ( listener != null )
468 checkBox.addItemListener( listener );
469 return checkBox;
470 }
471
472 /** Get the current state of a CheckBox
473 **/
474 public boolean getCheckBoxState( Component checkBox ) {
475 return ((JCheckBox)checkBox).isSelected();
476 }
477
478 /** Set the state of a CheckBox.
479 **/
480 public void setCheckBoxState( Component checkBox, boolean state ) {
481 ((JCheckBox)checkBox).setSelected( state );
482 }
483
484
485 /** Under this setup can we create a folder/directory
486 * chooser?
487 **/
488 public boolean canChooseFolders() {
489 return true;
490 }
491
492 /** Display a dialog to allow the user to choose a folder (eg for
493 * where to download files to.
494 **/
495 protected File chooseFolderImp( Frame parent, String title ) {
496 if ( canChooseFolders() ) {
497 if ( chooseFolder == null ) {
498 chooseFolder = new JFileChooser();
499 chooseFolder.setApproveButtonText( getResourceString( "@res:selectButton" ) );
500 chooseFolder.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
501 }
502 chooseFolder.setDialogTitle( title );
503 chooseFolder.rescanCurrentDirectory();
504 if ( chooseFolder.showDialog( parent, getResourceString( "@res:selectButton" ) ) == JFileChooser.APPROVE_OPTION) {
505 File folder = chooseFolder.getSelectedFile();
506 chooseFolder.setCurrentDirectory( chooseFolder.getCurrentDirectory() );
507 return folder;
508 }
509 }
510 return null;
511 }
512
513
514 /** Display a dialog to allow the user to save a file.
515 **/
516 protected File chooseSaveFileImp( Frame parent, String title ) {
517 if ( saveFile == null ) {
518 saveFile = new JFileChooser();
519 }
520 saveFile.setDialogTitle( title );
521 saveFile.rescanCurrentDirectory();
522 if ( saveFile.showSaveDialog( parent ) == JFileChooser.APPROVE_OPTION) {
523 File save = saveFile.getSelectedFile();
524 saveFile.setCurrentDirectory( saveFile.getCurrentDirectory() );
525 return save;
526 }
527 return null;
528 }
529
530 /** Display a dialog to allow the user to open a file.
531 **/
532 protected File chooseOpenFileImp( Frame parent, String title ) {
533 if ( openFile == null ) {
534 openFile = new JFileChooser();
535 }
536 openFile.setDialogTitle( title );
537 openFile.rescanCurrentDirectory();
538 if ( openFile.showOpenDialog( parent ) == JFileChooser.APPROVE_OPTION) {
539 File open = openFile.getSelectedFile();
540 openFile.setCurrentDirectory( openFile.getCurrentDirectory() );
541 return open;
542 }
543 return null;
544 }
545
546 public static class TextDocListener implements DocumentListener {
547 private JTextComponent textComponent = null;
548 private TextListener textListener = null;
549
550 public TextDocListener( JTextComponent textComponent, TextListener textListener ) {
551 this.textComponent = textComponent;
552 this.textListener = textListener;
553 }
554
555 public void changedUpdate( DocumentEvent de ) {
556 textListener.textValueChanged( new TextEvent( textComponent, TextEvent.TEXT_VALUE_CHANGED ) );
557 }
558
559 public void insertUpdate( DocumentEvent de ) {
560 textListener.textValueChanged( new TextEvent( textComponent, TextEvent.TEXT_VALUE_CHANGED ) );
561 }
562
563 public void removeUpdate( DocumentEvent de ) {
564 textListener.textValueChanged( new TextEvent( textComponent, TextEvent.TEXT_VALUE_CHANGED ) );
565 }
566
567 }
568
569 public static class JPLList extends JList implements ItemSelectable, ListSelectionListener {
570 private ItemListener listener = null;
571
572 public JPLList( String[] data ) {
573 super( data );
574 addListSelectionListener( this );
575 }
576
577
578
579 /* (non-Javadoc)
580 * @see java.awt.ItemSelectable#addItemListener(java.awt.event.ItemListener)
581 */
582 public void addItemListener(ItemListener listener) {
583 if ( this.listener == null )
584 this.listener = listener;
585 else
586 this.listener = AWTEventMulticaster.add( this.listener, listener );
587 }
588
589 /* (non-Javadoc)
590 * @see java.awt.ItemSelectable#getSelectedObjects()
591 */
592 public Object[] getSelectedObjects() {
593 return getSelectedValues();
594 }
595
596 /* (non-Javadoc)
597 * @see java.awt.ItemSelectable#removeItemListener(java.awt.event.ItemListener)
598 */
599 public void removeItemListener(ItemListener listener) {
600 if ( this.listener == listener )
601 this.listener = null;
602 else
603 this.listener = AWTEventMulticaster.remove( this.listener, listener );
604
605 }
606
607 /* (non-Javadoc)
608 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
609 */
610 public void valueChanged( ListSelectionEvent lse ) {
611 if ( listener != null )
612 listener.itemStateChanged( new ItemEvent( this, ItemEvent.ITEM_STATE_CHANGED, getSelectedValue(), ItemEvent.SELECTED ) );
613 }
614
615 }
616
617 }
618