Configurator.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:8k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: Configurator.java,v 1.3 2005/10/10 18:01:35 rbair Exp $
  3.  *
  4.  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  * 
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.swingx.autocomplete;
  22. import java.awt.event.ActionEvent;
  23. import java.awt.event.FocusAdapter;
  24. import java.awt.event.FocusEvent;
  25. import java.awt.event.KeyAdapter;
  26. import java.awt.event.KeyEvent;
  27. import java.awt.event.KeyListener;
  28. import java.beans.PropertyChangeEvent;
  29. import java.beans.PropertyChangeListener;
  30. import javax.swing.*;
  31. import javax.swing.text.*;
  32. import javax.swing.text.TextAction;
  33. /**
  34.  * This class contains only static utility methods that can be used to set up
  35.  * automatic completion for some Swing components.
  36.  * <p>Usage examples:</p>
  37.  * <p><code>
  38.  * JComboBox comboBox = [...];<br/>
  39.  * Configurator.<b>enableAutoCompletion</b>(comboBox);<br/>
  40.  * &nbsp;<br/>
  41.  * JList list = [...];<br/>
  42.  * JTextField textField = [...];<br/>
  43.  * Configurator.<b>enableAutoCompletion</b>(list, textField);
  44.  * </p></code>
  45.  *
  46.  * @author Thomas Bierhance
  47.  */
  48. public class Configurator {
  49.     
  50.     /**
  51.      * Enables automatic completion for the given JTextComponent based on the
  52.      * items contained in the given JList. The two components will be
  53.      * synchronized. The automatic completion will always be strict.
  54.      *
  55.      * @param list a list
  56.      * @param textComponent the text component that will be used for automatic
  57.      * completion.
  58.      */
  59.     public static void enableAutoCompletion(JList list, JTextComponent textComponent) {
  60.         AbstractComponentAdaptor adaptor = new ListAdaptor(list, textComponent);
  61.         Document document = new Document(adaptor, true);
  62.         configureTextComponent(textComponent, document, adaptor);
  63.     }
  64.     
  65.     /**
  66.      * Enables automatic completion for the given JComboBox. The automatic
  67.      * completion will be strict (only items from the combo box can be selected)
  68.      * if the combo box is not editable.
  69.      * @param comboBox a combobox
  70.      */
  71.     public static void enableAutoCompletion(final JComboBox comboBox) {
  72.         boolean strictMatching = !comboBox.isEditable();
  73.         // has to be editable
  74.         comboBox.setEditable(true);
  75.         
  76.         // configure the text component=editor component
  77.         JTextComponent editor = (JTextComponent) comboBox.getEditor().getEditorComponent();
  78.         final AbstractComponentAdaptor adaptor = new ComboBoxAdaptor(comboBox);
  79.         final Document document = new Document(adaptor, strictMatching);
  80.         configureTextComponent(editor, document, adaptor);
  81.         
  82.         // show the popup list when the user presses a key
  83.         final KeyListener keyListener = new KeyAdapter() {
  84.             public void keyPressed(KeyEvent keyEvent) {
  85.                 // don't popup on action keys (cursor movements, etc...)
  86.                 if (keyEvent.isActionKey()) return;
  87.                 // don't popup if the combobox isn't visible anyway
  88.                 if (comboBox.isDisplayable() && !comboBox.isPopupVisible()) {
  89.                     int keyCode = keyEvent.getKeyCode();
  90.                     // don't popup when the user hits shift,ctrl or alt
  91.                     if (keyCode==keyEvent.VK_SHIFT || keyCode==keyEvent.VK_CONTROL || keyCode==keyEvent.VK_ALT) return;
  92.                     comboBox.setPopupVisible(true);
  93.                 }
  94.             }
  95.         };
  96.         editor.addKeyListener(keyListener);
  97.         
  98.         // Changing the l&f can change the combobox' editor which in turn
  99.         // would not be autocompletion-enabled. The new editor needs to be set-up.
  100.         comboBox.addPropertyChangeListener(new PropertyChangeListener() {
  101.             public void propertyChange(PropertyChangeEvent e) {
  102.                 if (e.getPropertyName().equals("editor")) {
  103.                     ComboBoxEditor editor = comboBox.getEditor();
  104.                     if (editor!=null && editor.getEditorComponent()!=null) {
  105.                         configureTextComponent((JTextComponent) editor.getEditorComponent(), document, adaptor);
  106.                         editor.getEditorComponent().addKeyListener(keyListener);
  107.                     }
  108.                 }
  109.             }
  110.         });
  111.     }
  112.     
  113.     /**
  114.      * Configures a given text component for automatic completion using the
  115.      * given Document and AbstractComponentAdaptor.
  116.      * @param textComponent a text component that should be configured
  117.      * @param document the Document to be installed on the text component
  118.      * @param adaptor the AbstractComponentAdaptor to be used
  119.      */
  120.     public static void configureTextComponent(JTextComponent textComponent, Document document, final AbstractComponentAdaptor adaptor) {
  121.         // install the document on the text component
  122.         textComponent.setDocument(document);
  123.         
  124.         // mark entire text when the text component gains focus
  125.         // otherwise the last mark would have been retained which is quiet confusing
  126.         textComponent.addFocusListener(new FocusAdapter() {
  127.             public void focusGained(FocusEvent e) {
  128.                 JTextComponent textComponent = (JTextComponent) e.getSource();
  129.                 adaptor.markEntireText();
  130.             }
  131.         });
  132.         
  133.         // Tweak some key bindings
  134.         InputMap editorInputMap = textComponent.getInputMap();
  135.         if (document.isStrictMatching()) {
  136.             // move the selection to the left on VK_BACK_SPACE
  137.             editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0), DefaultEditorKit.selectionBackwardAction);
  138.             // ignore VK_DELETE and CTRL+VK_X and beep instead when strict matching
  139.             editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE, 0), errorFeedbackAction);
  140.             editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.event.InputEvent.CTRL_DOWN_MASK), errorFeedbackAction);
  141.         } else {
  142.             ActionMap editorActionMap = textComponent.getActionMap();
  143.             // leave VK_DELETE and CTRL+VK_X as is
  144.             // VK_BACKSPACE will move the selection to the left if the selected item is in the list
  145.             // it will delete the previous character otherwise
  146.             editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0), "nonstrict-backspace");
  147.             editorActionMap.put("nonstrict-backspace", new NonStrictBackspaceAction(
  148.                     editorActionMap.get(DefaultEditorKit.deletePrevCharAction),
  149.                     editorActionMap.get(DefaultEditorKit.selectionBackwardAction),
  150.                     adaptor));
  151.         }
  152.     }
  153.     
  154.     static class NonStrictBackspaceAction extends TextAction {
  155.         Action backspace;
  156.         Action selectionBackward;
  157.         AbstractComponentAdaptor adaptor;
  158.         
  159.         public NonStrictBackspaceAction(Action backspace, Action selectionBackward, AbstractComponentAdaptor adaptor) {
  160.             super("nonstrict-backspace");
  161.             this.backspace = backspace;
  162.             this.selectionBackward = selectionBackward;
  163.             this.adaptor = adaptor;
  164.         }
  165.         
  166.         public void actionPerformed(ActionEvent e) {
  167.             if (adaptor.listContainsSelectedItem()) {
  168.                 selectionBackward.actionPerformed(e);
  169.             } else {
  170.                 backspace.actionPerformed(e);
  171.             }
  172.         }
  173.     }
  174.     
  175.     /**
  176.      * A TextAction that provides an error feedback for the text component that invoked
  177.      * the action. The error feedback is most likely a "beep".
  178.      */
  179.     static Object errorFeedbackAction = new TextAction("provide-error-feedback") {
  180.         public void actionPerformed(ActionEvent e) {
  181.             UIManager.getLookAndFeel().provideErrorFeedback(getTextComponent(e));
  182.         }
  183.     };
  184. }