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

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: AbstractPatternPanel.java,v 1.8 2005/10/12 11:26:56 kleopatra 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;
  22. import java.awt.Dimension;
  23. import java.beans.PropertyChangeEvent;
  24. import java.beans.PropertyChangeListener;
  25. import javax.swing.Action;
  26. import javax.swing.ActionMap;
  27. import javax.swing.JCheckBox;
  28. import javax.swing.JLabel;
  29. import javax.swing.JTextField;
  30. import javax.swing.SwingUtilities;
  31. import javax.swing.UIManager;
  32. import javax.swing.event.DocumentEvent;
  33. import javax.swing.event.DocumentListener;
  34. import org.jdesktop.swingx.action.AbstractActionExt;
  35. import org.jdesktop.swingx.action.ActionContainerFactory;
  36. import org.jdesktop.swingx.action.BoundAction;
  37. import org.jdesktop.swingx.plaf.LookAndFeelAddons;
  38. /**
  39.  * Common base class of ui clients.
  40.  * 
  41.  * Implements basic synchronization between PatternModel state and
  42.  * actions bound to it.
  43.  * 
  44.  * 
  45.  * 
  46.  * PENDING: extending JXPanel is a convenience measure, should be extracted
  47.  *   into a dedicated controller.
  48.  * PENDING: should be re-visited when swingx goes binding-aware
  49.  * 
  50.  * @author Jeanette Winzenburg
  51.  */
  52. public abstract class AbstractPatternPanel extends JXPanel {
  53.     public static final String SEARCH_FIELD_LABEL = "searchFieldLabel";
  54.     public static final String SEARCH_FIELD_MNEMONIC = SEARCH_FIELD_LABEL + ".mnemonic";
  55.     public static final String SEARCH_TITLE = "searchTitle";
  56.     public static final String MATCH_ACTION_COMMAND = "match";
  57.     static {
  58.         // Hack to enforce loading of SwingX framework ResourceBundle
  59.         LookAndFeelAddons.getAddon();
  60.     }
  61.     protected JLabel searchLabel;
  62.     protected JTextField searchField;
  63.     protected JCheckBox matchCheck;
  64.     
  65.     protected PatternModel patternModel;
  66.     private ActionContainerFactory actionFactory;
  67. //------------------------ actions
  68.     /**
  69.      * Callback action bound to MATCH_ACTION_COMMAND. 
  70.      *  
  71.      */
  72.     public abstract void match();
  73.     
  74.     /** 
  75.      * convenience method for type-cast to AbstractActionExt.
  76.      * 
  77.      *  
  78.      * @param key
  79.      * @return
  80.      */
  81.     protected AbstractActionExt getAction(String key) {
  82.         // PENDING: outside clients might add different types?
  83.         return (AbstractActionExt) getActionMap().get(key);
  84.     }
  85.     /**
  86.      * creates and registers all actions with the actionMap.
  87.      *
  88.      */
  89.     protected void initActions() {
  90.         initPatternActions();
  91.         initExecutables();
  92.     }
  93.     
  94.     /**
  95.      * creates and registers all "executable" actions.
  96.      * Meaning: the actions bound to a callback method on this.
  97.      * 
  98.      * PENDING: not quite correctly factored? Name?
  99.      *
  100.      */
  101.     protected void initExecutables() {
  102.         Action execute = createBoundAction(MATCH_ACTION_COMMAND, "match");
  103.         getActionMap().put(JXDialog.EXECUTE_ACTION_COMMAND, 
  104.                 execute);
  105.         getActionMap().put(MATCH_ACTION_COMMAND, execute);
  106.         refreshEmptyFromModel();
  107.         
  108.         
  109.     }
  110.     
  111.     /**
  112.      * creates actions bound to PatternModel's state.
  113.      *
  114.      */
  115.     protected void initPatternActions() {
  116.         ActionMap map = getActionMap();
  117.         map.put(PatternModel.MATCH_CASE_ACTION_COMMAND, 
  118.                 createModelStateAction(PatternModel.MATCH_CASE_ACTION_COMMAND, 
  119.                         "setCaseSensitive", getPatternModel().isCaseSensitive()));
  120.         map.put(PatternModel.MATCH_WRAP_ACTION_COMMAND, 
  121.                 createModelStateAction(PatternModel.MATCH_WRAP_ACTION_COMMAND, 
  122.                         "setWrapping", getPatternModel().isWrapping()));
  123.         map.put(PatternModel.MATCH_BACKWARDS_ACTION_COMMAND, 
  124.                 createModelStateAction(PatternModel.MATCH_BACKWARDS_ACTION_COMMAND, 
  125.                         "setBackwards", getPatternModel().isBackwards()));
  126.         map.put(PatternModel.MATCH_INCREMENTAL_ACTION_COMMAND, 
  127.                 createModelStateAction(PatternModel.MATCH_INCREMENTAL_ACTION_COMMAND, 
  128.                         "setIncremental", getPatternModel().isIncremental()));
  129.     }
  130.     /**
  131.      * tries to find a String value from the UIManager, prefixing the
  132.      * given key with the UIPREFIX. 
  133.      * 
  134.      * TODO: move to utilities?
  135.      * 
  136.      * @param key 
  137.      * @return the String as returned by the UIManager or key if the returned
  138.      *   value was null.
  139.      */
  140.     protected String getUIString(String key) {
  141.         String text = UIManager.getString(PatternModel.SEARCH_PREFIX + key);
  142.         return text != null ? text : key;
  143.     }
  144.     /**
  145.      * creates, configures and returns a bound state action on a boolean property
  146.      * of the PatternModel.
  147.      * 
  148.      * @param command the actionCommand - same as key to find localizable resources
  149.      * @param methodName the method on the PatternModel to call on item state changed
  150.      * @param initial the initial value of the property
  151.      * @return
  152.      */
  153.     protected AbstractActionExt createModelStateAction(String command, String methodName, boolean initial) {
  154.         String actionName = getUIString(command);
  155.         BoundAction action = new BoundAction(actionName,
  156.                 command);
  157.         action.setStateAction();
  158.         action.registerCallback(getPatternModel(), methodName);
  159.         action.setSelected(initial);
  160.         return action;
  161.     }
  162.     /**
  163.      * creates, configures and returns a bound action to the given method of 
  164.      * this.
  165.      * 
  166.      * @param actionCommand the actionCommand, same as key to find localizable resources
  167.      * @param methodName the method to call an actionPerformed.
  168.      * @return
  169.      */
  170.     protected AbstractActionExt createBoundAction(String actionCommand, String methodName) {
  171.         String actionName = getUIString(actionCommand);
  172.         BoundAction action = new BoundAction(actionName,
  173.                 actionCommand);
  174.         action.registerCallback(this, methodName);
  175.         return action;
  176.     }
  177.     //---------------------- synch patternModel <--> components
  178.     /**
  179.      * called from listening to pattern property of PatternModel.
  180.      * 
  181.      * This implementation calls match() if the model is in
  182.      * incremental state.
  183.      *
  184.      */
  185.     protected void refreshPatternFromModel() {
  186.         if (getPatternModel().isIncremental()) {
  187.             match();
  188.         }
  189.     }
  190.     /**
  191.      * returns the patternModel. Lazyly creates and registers a
  192.      * propertyChangeListener if null.
  193.      * 
  194.      */
  195.     protected PatternModel getPatternModel() {
  196.         if (patternModel == null) {
  197.             patternModel = createPatternModel();
  198.             patternModel.addPropertyChangeListener(getPatternModelListener());
  199.         }
  200.         return patternModel;
  201.     }
  202.     /**
  203.      * factory method to create the PatternModel.
  204.      * Hook for subclasses to install custom models.
  205.      * @return
  206.      */
  207.     protected PatternModel createPatternModel() {
  208.         PatternModel l = new PatternModel();
  209.         return l;
  210.     }
  211.     /**
  212.      * creates and returns a PropertyChangeListener to the PatternModel.
  213.      * 
  214.      * NOTE: the patternModel is totally under control of this class - currently
  215.      * there's no need to keep a reference to the listener.
  216.      * 
  217.      * @return
  218.      */
  219.     protected PropertyChangeListener getPatternModelListener() {
  220.         PropertyChangeListener l = new PropertyChangeListener() {
  221.     
  222.             public void propertyChange(PropertyChangeEvent evt) {
  223.                 String property = evt.getPropertyName();
  224.                 if ("pattern".equals(property)) {
  225.                     refreshPatternFromModel();
  226.                 } else if ("rawText".equals(property)) {
  227.                     refreshDocumentFromModel();
  228.                 } else if ("caseSensitive".equals(property)){
  229.                     getAction(PatternModel.MATCH_CASE_ACTION_COMMAND).
  230.                         setSelected(((Boolean) evt.getNewValue()).booleanValue());
  231.                 } else if ("wrapping".equals(property)) {
  232.                     getAction(PatternModel.MATCH_WRAP_ACTION_COMMAND).
  233.                     setSelected(((Boolean) evt.getNewValue()).booleanValue());
  234.                 } else if ("backwards".equals(property)) {
  235.                     getAction(PatternModel.MATCH_BACKWARDS_ACTION_COMMAND).
  236.                     setSelected(((Boolean) evt.getNewValue()).booleanValue());
  237.                 } else if ("incremental".equals(property)) {
  238.                     getAction(PatternModel.MATCH_INCREMENTAL_ACTION_COMMAND).
  239.                     setSelected(((Boolean) evt.getNewValue()).booleanValue());
  240.                 } else if ("empty".equals(property)) {
  241.                     refreshEmptyFromModel();
  242.                 }   
  243.     
  244.             }
  245.     
  246.         };
  247.         return l;
  248.     }
  249.     /**
  250.      * called from listening to empty property of PatternModel.
  251.      * 
  252.      * this implementation synch's the enabled state of the action with
  253.      * MATCH_ACTION_COMMAND to !empty.
  254.      * 
  255.      */
  256.     protected void refreshEmptyFromModel() {
  257.         boolean enabled = !getPatternModel().isEmpty();
  258.         getAction(MATCH_ACTION_COMMAND).setEnabled(enabled);
  259.         
  260.     }
  261.     /**
  262.      * callback method from listening to searchField.
  263.      *
  264.      */
  265.     protected void refreshModelFromDocument() {
  266.         getPatternModel().setRawText(searchField.getText());
  267.     }
  268.     protected void refreshDocumentFromModel() {
  269.         if (searchField.getText().equals(getPatternModel().getRawText())) return;
  270.         SwingUtilities.invokeLater(new Runnable() {
  271.             public void run() {
  272.                 searchField.setText(getPatternModel().getRawText());
  273.             }
  274.         });
  275.     }
  276.     protected DocumentListener getSearchFieldListener() {
  277.         DocumentListener l = new DocumentListener() {
  278.             public void changedUpdate(DocumentEvent ev) {
  279.                 // JW - really?? we've a PlainDoc without Attributes
  280.                 refreshModelFromDocument();
  281.             }
  282.     
  283.             public void insertUpdate(DocumentEvent ev) {
  284.                 refreshModelFromDocument();
  285.             }
  286.     
  287.             public void removeUpdate(DocumentEvent ev) {
  288.                 refreshModelFromDocument();
  289.             }
  290.     
  291.         };
  292.         return l;
  293.     }
  294. //-------------------------- config helpers
  295.     /**
  296.      * configure and bind components to/from PatternModel
  297.      */
  298.     protected void bind() {
  299.       bindSearchLabel();
  300.         searchField.getDocument().addDocumentListener(getSearchFieldListener());
  301.         getActionContainerFactory().configureButton(matchCheck, 
  302.                 (AbstractActionExt) getActionMap().get(PatternModel.MATCH_CASE_ACTION_COMMAND),
  303.                 null);
  304.         
  305.     }
  306.     /**
  307.      * Configures the searchLabel.
  308.      * Here: sets text and mnenomic properties form ui values, 
  309.      * configures as label for searchField.
  310.      */
  311.     protected void bindSearchLabel() {
  312.         searchLabel.setText(getUIString(SEARCH_FIELD_LABEL));
  313.           String mnemonic = getUIString(SEARCH_FIELD_MNEMONIC);
  314.           if (mnemonic != SEARCH_FIELD_MNEMONIC) {
  315.               searchLabel.setDisplayedMnemonic(mnemonic.charAt(0));
  316.           }
  317.           searchLabel.setLabelFor(searchField);
  318.     }
  319.     
  320.     protected ActionContainerFactory getActionContainerFactory() {
  321.         if (actionFactory == null) {
  322.             actionFactory = new ActionContainerFactory(null);
  323.         }
  324.         return actionFactory;
  325.     }
  326.     
  327.     protected void initComponents() {
  328.         searchLabel = new JLabel();
  329.         searchField = new JTextField(getSearchFieldWidth()) {
  330.             public Dimension getMaximumSize() {
  331.                 Dimension superMax = super.getMaximumSize();
  332.                 superMax.height = getPreferredSize().height;
  333.                 return superMax;
  334.             }
  335.         };
  336.         matchCheck = new JCheckBox();
  337.         
  338.     }
  339.     /**
  340.      * @return
  341.      */
  342.     protected int getSearchFieldWidth() {
  343.         return 15;
  344.     }
  345. }