From a4752915054bc9b456d4583e1a596e6f83dbaa6e Mon Sep 17 00:00:00 2001 From: Purvesh Sahoo Date: Sun, 28 Aug 2011 03:55:43 +0000 Subject: [PATCH] Adds support to uninstall dictionary and persist enable state across reboots. --- resources/languages/resources.properties | 5 +- .../spellcheck/CheckerToggleButton.java | 89 ++++++++ .../spellcheck/LanguageSelectionField.java | 212 ++++++++++++++++-- .../plugin/spellcheck/SpellChecker.java | 31 +++ 4 files changed, 312 insertions(+), 25 deletions(-) create mode 100644 src/net/java/sip/communicator/plugin/spellcheck/CheckerToggleButton.java diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index db871794d..b8a856c1d 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1312,6 +1312,9 @@ plugin.spellcheck.DICT_ERROR_TITLE=Error Switching Dictionary plugin.spellcheck.DICT_ERROR=Cannot switch dictionary plugin.spellcheck.DICT_RETRIEVE_ERROR=Dictionary cannot be fetched from plugin.spellcheck.DICT_PROCESS_ERROR=Locale not recognized +plugin.spellcheck.UNINSTALL_DICTIONARY=Uninstall +plugin.spellcheck.DICT_ERROR_DELETE_TITLE=Error uninstalling dictionary +plugin.spellcheck.DICT_ERROR_DELETE=Cannot uninstall dictionary plugin.contactsourceconfig.CONTACT_SOURCE_TITLE=Contact sources @@ -1333,4 +1336,4 @@ plugin.certconfig.KEYSTORE_EXCEPTION=Unable to load the keystore ({0}). plugin.certconfig.FILE_TYPE_DESCRIPTION=Certificate stores (PKCS#11 Module, PKCS#12 files, Java ks Keystore) plugin.certconfig.ALIAS_LOAD_EXCEPTION=Unable to obtain aliases from keystore ({0}). plugin.certconfig.INVALID_KEYSTORE_TYPE=The selected Keystore type seems to be invalid ({0}). -plugin.certconfig.BROWSE_KEYSTORE=Open KeyStore \ No newline at end of file +plugin.certconfig.BROWSE_KEYSTORE=Open KeyStore diff --git a/src/net/java/sip/communicator/plugin/spellcheck/CheckerToggleButton.java b/src/net/java/sip/communicator/plugin/spellcheck/CheckerToggleButton.java new file mode 100644 index 000000000..0d7840ce4 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/spellcheck/CheckerToggleButton.java @@ -0,0 +1,89 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.spellcheck; + +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.Contact; + +/** + * Toggle-able button that sets the spell checker to be either enabled or + * disabled. + * + * @author Damian Johnson + */ +public class CheckerToggleButton + implements PluginComponent +{ + private final JToggleButton toggleButton; + + CheckerToggleButton(final SpellChecker checker) + { + this.toggleButton = + new JToggleButton(Resources.getImage("plugin.spellcheck.DISABLE")); + this.toggleButton.setSelectedIcon(Resources + .getImage("plugin.spellcheck.ENABLE")); + this.toggleButton.setSelected(checker.isEnabled()); + this.toggleButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent event) + { + checker.setEnabled(toggleButton.isSelected()); + } + }); + } + + public Object getComponent() + { + return this.toggleButton; + } + + public String getConstraints() + { + return Container.RIGHT; + } + + public Container getContainer() + { + return Container.CONTAINER_CHAT_TOOL_BAR; + } + + public String getName() + { + return "Spell Checker Toggle"; + } + + public int getPositionIndex() + { + return -1; + } + + public boolean isNativeComponent() + { + return false; + } + + public void setCurrentContact(MetaContact metaContact) + { + + } + + public void setCurrentContactGroup(MetaContactGroup metaGroup) + { + + } + + @Override + public void setCurrentContact(Contact contact) + { + // TODO Auto-generated method stub + + } +} diff --git a/src/net/java/sip/communicator/plugin/spellcheck/LanguageSelectionField.java b/src/net/java/sip/communicator/plugin/spellcheck/LanguageSelectionField.java index 2986ed2af..96ecb4606 100644 --- a/src/net/java/sip/communicator/plugin/spellcheck/LanguageSelectionField.java +++ b/src/net/java/sip/communicator/plugin/spellcheck/LanguageSelectionField.java @@ -7,6 +7,7 @@ import java.awt.*; import java.awt.image.*; +import java.awt.event.*; import java.io.*; import java.util.*; @@ -15,6 +16,7 @@ import javax.swing.event.*; import net.java.sip.communicator.plugin.spellcheck.Parameters.Default; +import net.java.sip.communicator.plugin.spellcheck.Parameters.Locale; import net.java.sip.communicator.service.contactlist.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.gui.Container; @@ -64,6 +66,9 @@ public class LanguageSelectionField private final ArrayList localeList = new ArrayList(); + + private final SIPCommTextButton removeItem = new SIPCommTextButton( + Resources.getString("plugin.spellcheck.UNINSTALL_DICTIONARY")); /** * Provides instance of this class associated with a spell checker. If ones @@ -108,7 +113,7 @@ private LanguageSelectionField(SpellChecker checker) this.menu.setOpaque(false); this.setOpaque(false); - DefaultListModel model = new DefaultListModel(); + final DefaultListModel model = new DefaultListModel(); final JList list = new JList(model); this.languageSelectionRenderer = new LanguageListRenderer(); @@ -122,10 +127,11 @@ private LanguageSelectionField(SpellChecker checker) spellChecker.isLocaleAvailable(locale)); } - model.addElement(locale); localeList.add(locale); } - + + setModelElements(model); + JScrollPane scroll = new JScrollPane(list); scroll.setBorder(null); @@ -136,38 +142,123 @@ private LanguageSelectionField(SpellChecker checker) list.setSelectedIndex(localeList.indexOf(loc) + 1); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + removeItem.setPreferredSize(new Dimension(30, 28)); + + list.addListSelectionListener(new LanguageListSelectionListener()); + + menu.add(scroll); + + ImageIcon flagIcon = + getLocaleIcon(checker.getLocale(), + localeAvailabilityCache.get(checker.getLocale())); + SelectedObject selectedObject = + new SelectedObject(flagIcon, checker.getLocale()); + menu.setSelected(selectedObject); + + this.menu.addSeparator(); + + menu.add(removeItem); - list.addListSelectionListener(new ListSelectionListener() + list.addKeyListener(new KeyListener() { + long time = 0; - public void valueChanged(ListSelectionEvent e) + String key = ""; + + @Override + public void keyTyped(KeyEvent e) { + char ch = e.getKeyChar(); - if (!e.getValueIsAdjusting()) - { - final JList source = (JList) e.getSource(); - final Parameters.Locale locale = - (Parameters.Locale) source.getSelectedValue(); + if (!Character.isLetter(ch)) + return; + + if (time + 1000 < System.currentTimeMillis()) + key = ""; - source.setEnabled(false); + time = System.currentTimeMillis(); - // Indicate to the user that the language is currently - // loading. - locale.setLoading(true); + key += ch; - new SetSpellChecker(locale, source).start(); + for (int i = 0; i < model.getSize(); i++) + { + String label = + ((Parameters.Locale) model.getElementAt(i)).getLabel() + .toLowerCase(); + if (label.startsWith(key.toLowerCase())) + { + list.setSelectedIndex(i); + list.ensureIndexIsVisible(i); + break; + } } + + list.requestFocusInWindow(); + + } + + @Override + public void keyReleased(KeyEvent e) + { + + } + + @Override + public void keyPressed(KeyEvent e) + { + } }); + + removeItem.setEnabled(!spellChecker.getLocale().getIsoCode() + .equals(Parameters.getDefault(Parameters.Default.LOCALE))); + + removeItem.addActionListener(new ActionListener() + { - menu.add(scroll); + @Override + public void actionPerformed(ActionEvent e) + { + try + { + list.setEnabled(false); + Locale locale = (Locale) menu.getSelectedObject(); - ImageIcon flagIcon = - getLocaleIcon(checker.getLocale(), - localeAvailabilityCache.get(checker.getLocale())); - SelectedObject selectedObject = - new SelectedObject(flagIcon, checker.getLocale()); - menu.setSelected(selectedObject); + localeAvailabilityCache.put(locale, false); + + spellChecker.removeLocale(locale); + + list.setEnabled(true); + + ImageIcon flagIcon = + getLocaleIcon(spellChecker.getLocale(), + localeAvailabilityCache.get(spellChecker + .getLocale())); + SelectedObject selectedObject = + new SelectedObject(flagIcon, spellChecker.getLocale()); + menu.setSelected(selectedObject); + + } + catch (Exception ex) + { + PopupDialog dialog = + SpellCheckActivator.getUIService().getPopupDialog(); + + String message = + Resources + .getString("plugin.spellcheck.DICT_ERROR_DELETE") + + ex.getMessage(); + + dialog.showMessagePopupDialog( + message, + Resources + .getString("plugin.spellcheck.DICT_ERROR_DELETE_TITLE"), + PopupDialog.WARNING_MESSAGE); + ex.printStackTrace(); + } + } + }); } /** @@ -354,11 +445,49 @@ private JCheckBox createEnableCheckBox() public void stateChanged(ChangeEvent evt) { spellChecker.setEnabled(checkBox.isSelected()); + SpellCheckActivator.getConfigService().setProperty( + "plugin.spellcheck.ENABLE", checkBox.isSelected()); } }); return checkBox; } + + /** + * Set the elements for list model + * + * @param model the model whose elements are to be set + */ + private void setModelElements(DefaultListModel model) + { + synchronized (model) + { + + + model.clear(); + + Collections.sort(localeList, new Comparator() + { + + @Override + public int compare(Locale o1, Locale o2) + { + boolean b1 = spellChecker.isLocaleAvailable(o1); + boolean b2 = spellChecker.isLocaleAvailable(o2); + + if (b1 == b2) + return 0; + + return (b1 ? -1 : 1); + } + + }); + + for (Parameters.Locale loc : localeList) + model.addElement(loc); + + } + } private class SetSpellChecker extends SwingWorker { @@ -418,6 +547,16 @@ public void finished() // Indicate to the user that the language is currently // loading. locale.setLoading(false); + + sourceList.removeListSelectionListener(sourceList + .getListSelectionListeners()[0]); + setModelElements((DefaultListModel) sourceList.getModel()); + sourceList.setSelectedValue(locale, true); + removeItem.setEnabled(!spellChecker.getLocale().getIsoCode() + .equals(Parameters.getDefault(Parameters.Default.LOCALE))); + sourceList + .addListSelectionListener(new LanguageListSelectionListener()); + } /** @@ -499,10 +638,35 @@ public Component getListCellRendererComponent(JList list, + " loading..."); else setText(localeLabel); - + setIcon(flagIcon); - + return this; } } + + private class LanguageListSelectionListener + implements ListSelectionListener + { + public void valueChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) + { + final JList source = (JList) e.getSource(); + final Parameters.Locale locale = + (Parameters.Locale) source.getSelectedValue(); + + source.setEnabled(false); + + // Indicate to the user that the language is currently + // loading. + locale.setLoading(true); + + new SetSpellChecker(locale, source).start(); + source.requestFocusInWindow(); + removeItem.setEnabled(false); + + } + } + } } diff --git a/src/net/java/sip/communicator/plugin/spellcheck/SpellChecker.java b/src/net/java/sip/communicator/plugin/spellcheck/SpellChecker.java index 24f253e66..ee7460cf6 100644 --- a/src/net/java/sip/communicator/plugin/spellcheck/SpellChecker.java +++ b/src/net/java/sip/communicator/plugin/spellcheck/SpellChecker.java @@ -70,6 +70,9 @@ class SpellChecker */ synchronized void start(BundleContext bc) throws Exception { + isEnabled = SpellCheckActivator.getConfigService() + .getBoolean("plugin.spellcheck.ENABLE", true); + FileAccessService faService = SpellCheckActivator.getFileAccessService(); @@ -327,6 +330,34 @@ void setLocale(Parameters.Locale locale) throws Exception } } + /** + * Removes the dictionary from the system, and sets the default locale + * dictionary as the current dictionary + * + * @param locale locale to be removed + */ + void removeLocale(Parameters.Locale locale) throws Exception + { + synchronized (this.locale) + { + String path = locale.getDictUrl().getFile(); + + int filenameStart = path.lastIndexOf('/') + 1; + String filename = path.substring(filenameStart); + + File dictLocation = + SpellCheckActivator.getFileAccessService() + .getPrivatePersistentFile(DICT_DIR + filename); + + if (dictLocation.exists()) + dictLocation.delete(); + + String localeIso = Parameters.getDefault(Parameters.Default.LOCALE); + Parameters.Locale loc = Parameters.getLocale(localeIso); + setLocale(loc); + } + } + /** * Determines if locale's dictionary is locally available or not. *