001package org.jdesktop.swingx.search; 002 003import java.awt.event.ActionListener; 004import java.beans.PropertyChangeEvent; 005 006import javax.swing.JPopupMenu; 007import javax.swing.JTextField; 008import javax.swing.UIManager; 009 010import org.jdesktop.swingx.plaf.AbstractUIChangeHandler; 011import org.jdesktop.swingx.util.OS; 012 013/** 014 * TODO: comment 015 * 016 * @author Peter Weishapl <petw@gmx.net> 017 */ 018public class NativeSearchFieldSupport { 019 public static final String FIND_POPUP_PROPERTY = "JTextField.Search.FindPopup"; 020 public static final String FIND_ACTION_PROPERTY = "JTextField.Search.FindAction"; 021 public static final String MAC_SEARCH_VARIANT = "search"; 022 public static final String MAC_TEXT_FIELD_VARIANT_PROPERTY = "JTextField.variant"; 023 public static final String CANCEL_ACTION_PROPERTY = "JTextField.Search.CancelAction"; 024 025 /** 026 * @return <code>true</code> if we run Leopard and the Mac Look And Feel. 027 */ 028 public static boolean isNativeSearchFieldSupported() { 029 try { 030 String versionString = System.getProperty("os.version"); 031 // Mac versions have the format 10.x or 10.x.x 032 if (versionString.length() < 4) { 033 return false; 034 } 035 // only the part 10.x is important 036 versionString = versionString.substring(0, 4); 037 038 return OS.isMacOSX() && Float.parseFloat(versionString) >= 10.5 039 && UIManager.getLookAndFeel().getName().equals("Mac OS X"); 040 } catch (Exception e) { 041 // in case the os.version cannot be parsed, we are surely not 042 // running mac os x. 043 return false; 044 } 045 } 046 047 public static void setSearchField(JTextField txt, boolean isSearchField) { 048 // Leopard Hack: ensure property change event is triggered, if nothing 049 // changes. 050 if (isSearchField == isSearchField(txt)) { 051 txt.putClientProperty(MAC_TEXT_FIELD_VARIANT_PROPERTY, "_triggerevent_"); 052 } else if (isSearchField) { 053 // if we have a search field here, register listener for ui changes 054 // (leopard hack) 055 uiChangeHandler.install(txt); 056 } else { 057 // if we don't have a search field, we don't need to listen anymore. 058 uiChangeHandler.uninstall(txt); 059 } 060 061 if (isSearchField) { 062 txt.putClientProperty(MAC_TEXT_FIELD_VARIANT_PROPERTY, MAC_SEARCH_VARIANT); 063 txt.putClientProperty("Quaqua.TextField.style", MAC_SEARCH_VARIANT); 064 065 } else { 066 txt.putClientProperty(MAC_TEXT_FIELD_VARIANT_PROPERTY, "default"); 067 txt.putClientProperty("Quaqua.TextField.style", "default"); 068 } 069 } 070 071 public static boolean isSearchField(JTextField txt) { 072 return MAC_SEARCH_VARIANT.equals(txt.getClientProperty(MAC_TEXT_FIELD_VARIANT_PROPERTY)); 073 } 074 075 public static boolean isNativeSearchField(JTextField txt) { 076 return isSearchField(txt) && isNativeSearchFieldSupported(); 077 } 078 079 public static void setFindPopupMenu(JTextField txt, JPopupMenu popupMenu) { 080 txt.putClientProperty(FIND_POPUP_PROPERTY, popupMenu); 081 } 082 083 public static JPopupMenu getFindPopupMenu(JTextField txt) { 084 return (JPopupMenu) txt.getClientProperty(FIND_POPUP_PROPERTY); 085 } 086 087 public static void setFindAction(JTextField txt, ActionListener findAction) { 088 txt.putClientProperty(FIND_ACTION_PROPERTY, findAction); 089 } 090 091 public static ActionListener getFindAction(JTextField txt) { 092 return (ActionListener) txt.getClientProperty(FIND_ACTION_PROPERTY); 093 } 094 095 public static void setCancelAction(JTextField txt, ActionListener cancelAction) { 096 txt.putClientProperty(CANCEL_ACTION_PROPERTY, cancelAction); 097 } 098 099 public static ActionListener getCancelAction(JTextField txt) { 100 return (ActionListener) txt.getClientProperty(CANCEL_ACTION_PROPERTY); 101 } 102 103 private static final SearchFieldUIChangeHandler uiChangeHandler = new SearchFieldUIChangeHandler(); 104 105 private static final class SearchFieldUIChangeHandler extends AbstractUIChangeHandler { 106 @Override 107 public void propertyChange(PropertyChangeEvent evt) { 108 JTextField txt = (JTextField) evt.getSource(); 109 // Leopard hack to make appear correctly in search variant when 110 // changing LnF. 111 setSearchField(txt, isSearchField(txt)); 112 } 113 } 114}