summaryrefslogtreecommitdiffstats
path: root/JLanguageTool/src/java/de/danielnaber/languagetool/gui
diff options
context:
space:
mode:
Diffstat (limited to 'JLanguageTool/src/java/de/danielnaber/languagetool/gui')
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/AboutDialog.java58
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/Configuration.java233
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/ConfigurationDialog.java497
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/LanguageManagerDialog.java184
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/Main.java738
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/MainMenuBar.java170
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/MissingJdicException.java38
-rw-r--r--JLanguageTool/src/java/de/danielnaber/languagetool/gui/Tools.java192
8 files changed, 2110 insertions, 0 deletions
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/AboutDialog.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/AboutDialog.java
new file mode 100644
index 0000000..26df4a1
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/AboutDialog.java
@@ -0,0 +1,58 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2007 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.util.ResourceBundle;
+
+import javax.swing.JOptionPane;
+
+import de.danielnaber.languagetool.JLanguageTool;
+import de.danielnaber.languagetool.Language;
+import de.danielnaber.languagetool.tools.StringTools;
+
+/**
+ * A dialog with version and copyright information.
+ *
+ * @author Daniel Naber
+ */
+public class AboutDialog {
+
+ protected final ResourceBundle messages;
+
+ public AboutDialog(final ResourceBundle messages) {
+ this.messages = messages;
+ }
+
+ public void show() {
+ final String aboutText =
+ StringTools.getLabel(messages.getString("guiMenuAbout"));
+ JOptionPane.showMessageDialog(null, getAboutText(),
+ aboutText, JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ protected String getAboutText() {
+ return "LanguageTool " + JLanguageTool.VERSION + "\n"
+ + "Copyright (C) 2005-2010 Daniel Naber\n"
+ + "This software is licensed under the GNU Lesser General Public License.\n"
+ + "LanguageTool Homepage: http://www.languagetool.org\n\n"
+ + "Maintainers of the language modules:\n\n"
+ + Language.getAllMaintainers(messages);
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Configuration.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Configuration.java
new file mode 100644
index 0000000..932e1fe
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Configuration.java
@@ -0,0 +1,233 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.*;
+
+import de.danielnaber.languagetool.Language;
+import de.danielnaber.languagetool.server.HTTPServer;
+
+/**
+ * Configuration -- currently this is just a list of disabled rule IDs.
+ * Configuration is loaded from and stored to a properties file.
+ *
+ * @author Daniel Naber
+ */
+public class Configuration {
+
+ private static final String CONFIG_FILE = "languagetool.properties";
+ private static final String DISABLED_RULES_CONFIG_KEY = "disabledRules";
+ private static final String ENABLED_RULES_CONFIG_KEY = "enabledRules";
+ private static final String DISABLED_CATEGORIES_CONFIG_KEY = "disabledCategories";
+ private static final String MOTHER_TONGUE_CONFIG_KEY = "motherTongue";
+ private static final String SERVER_RUN_CONFIG_KEY = "serverMode";
+ private static final String SERVER_PORT_CONFIG_KEY = "serverPort";
+
+ private File configFile;
+
+ private Set<String> disabledRuleIds = new HashSet<String>();
+ private Set<String> enabledRuleIds = new HashSet<String>();
+ private Set<String> disabledCategoryNames = new HashSet<String>();
+ private Language motherTongue;
+ private boolean runServer;
+ private int serverPort = HTTPServer.DEFAULT_PORT;
+
+ public Configuration(final File baseDir, final String filename)
+ throws IOException {
+ if (!baseDir.isDirectory()) {
+ throw new IllegalArgumentException("Not a directory: " + baseDir);
+ }
+ configFile = new File(baseDir, filename);
+ loadConfiguration();
+ }
+
+ public Configuration(final File baseDir) throws IOException {
+ this(baseDir, CONFIG_FILE);
+ }
+
+ public Set<String> getDisabledRuleIds() {
+ return disabledRuleIds;
+ }
+
+ public Set<String> getEnabledRuleIds() {
+ return enabledRuleIds;
+ }
+
+ public Set<String> getDisabledCategoryNames() {
+ return disabledCategoryNames;
+ }
+
+ public void setDisabledRuleIds(final Set<String> ruleIDs) {
+ disabledRuleIds = ruleIDs;
+ }
+
+ public void setEnabledRuleIds(final Set<String> ruleIDs) {
+ enabledRuleIds = ruleIDs;
+ }
+
+ public void setDisabledCategoryNames(final Set<String> categoryNames) {
+ disabledCategoryNames = categoryNames;
+ }
+
+ public Language getMotherTongue() {
+ return motherTongue;
+ }
+
+ public void setMotherTongue(final Language motherTongue) {
+ this.motherTongue = motherTongue;
+ }
+
+ public boolean getRunServer() {
+ return runServer;
+ }
+
+ public void setRunServer(final boolean runServer) {
+ this.runServer = runServer;
+ }
+
+ public int getServerPort() {
+ return serverPort;
+ }
+
+ public void setServerPort(final int serverPort) {
+ this.serverPort = serverPort;
+ }
+
+ private void loadConfiguration() throws IOException {
+
+ // FIXME: disabling a rule X in language Y should not disable it in all
+ // languages - need to add a language parameter
+
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(configFile);
+ final Properties props = new Properties();
+ props.load(fis);
+ final String val = (String) props.get(DISABLED_RULES_CONFIG_KEY);
+ if (val != null) {
+ final String[] ids = val.split(",");
+ disabledRuleIds.addAll(Arrays.asList(ids));
+ }
+
+ final String enRul = (String) props.get(ENABLED_RULES_CONFIG_KEY);
+ if (enRul != null) {
+ final String[] ids = enRul.split(",");
+ enabledRuleIds.addAll(Arrays.asList(ids));
+ }
+
+ final String cat = (String) props.get(DISABLED_CATEGORIES_CONFIG_KEY);
+ if (cat != null) {
+ final String[] names = cat.split(",");
+ disabledCategoryNames.addAll(Arrays.asList(names));
+ }
+
+ final String motherTongueStr = (String) props
+ .get(MOTHER_TONGUE_CONFIG_KEY);
+ if (motherTongueStr != null) {
+ motherTongue = Language.getLanguageForShortName(motherTongueStr);
+ }
+ final String runServerString = (String) props.get(SERVER_RUN_CONFIG_KEY);
+ if (runServerString != null) {
+ runServer = runServerString.equals("true");
+ }
+ final String serverPortString = (String) props
+ .get(SERVER_PORT_CONFIG_KEY);
+ if (serverPortString != null) {
+ serverPort = Integer.parseInt(serverPortString);
+ }
+ } catch (final FileNotFoundException e) {
+ // file not found: okay, leave disabledRuleIds empty
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ }
+
+ public void saveConfiguration() throws IOException {
+ final Properties props = new Properties();
+
+ if (disabledRuleIds == null) {
+ props.setProperty(DISABLED_RULES_CONFIG_KEY, "");
+ } else {
+ final StringBuilder sb = new StringBuilder();
+ for (final Iterator<String> iter = disabledRuleIds.iterator(); iter
+ .hasNext();) {
+ final String id = iter.next();
+ sb.append(id);
+ if (iter.hasNext()) {
+ sb.append(',');
+ }
+ }
+ props.setProperty(DISABLED_RULES_CONFIG_KEY, sb.toString());
+ }
+
+ if (enabledRuleIds == null) {
+ props.setProperty(ENABLED_RULES_CONFIG_KEY, "");
+ } else {
+ final StringBuilder sb = new StringBuilder();
+ for (final Iterator<String> iter = enabledRuleIds.iterator(); iter.hasNext();) {
+ final String id = iter.next();
+ sb.append(id);
+ if (iter.hasNext()) {
+ sb.append(',');
+ }
+ }
+ props.setProperty(ENABLED_RULES_CONFIG_KEY, sb.toString());
+ }
+
+ if (disabledCategoryNames == null) {
+ props.setProperty(DISABLED_CATEGORIES_CONFIG_KEY, "");
+ } else {
+ final StringBuilder sb = new StringBuilder();
+ for (final Iterator<String> iter = disabledCategoryNames.iterator(); iter
+ .hasNext();) {
+ final String name = iter.next();
+ sb.append(name);
+ if (iter.hasNext()) {
+ sb.append(',');
+ }
+ }
+ props.setProperty(DISABLED_CATEGORIES_CONFIG_KEY, sb.toString());
+ }
+
+ if (motherTongue != null) {
+ props.setProperty(MOTHER_TONGUE_CONFIG_KEY, motherTongue.getShortName());
+ }
+ props.setProperty(SERVER_RUN_CONFIG_KEY, Boolean.valueOf(runServer)
+ .toString());
+ props.setProperty(SERVER_PORT_CONFIG_KEY, Integer.valueOf(serverPort)
+ .toString());
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(configFile);
+ props.store(fos, "LanguageTool configuration");
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/ConfigurationDialog.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/ConfigurationDialog.java
new file mode 100644
index 0000000..d78ea08
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/ConfigurationDialog.java
@@ -0,0 +1,497 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+
+import de.danielnaber.languagetool.JLanguageTool;
+import de.danielnaber.languagetool.Language;
+import de.danielnaber.languagetool.rules.Rule;
+import de.danielnaber.languagetool.server.HTTPServer;
+import de.danielnaber.languagetool.tools.StringTools;
+
+/**
+ * Dialog that offers the available rules so they can be turned on/off
+ * individually.
+ *
+ * @author Daniel Naber
+ */
+public class ConfigurationDialog implements ActionListener {
+
+ private static final String NO_MOTHER_TONGUE = "---";
+
+ private JButton okButton;
+ private JButton cancelButton;
+
+ private final ResourceBundle messages;
+ private JDialog dialog;
+
+ private JComboBox motherTongueBox;
+
+ private JCheckBox serverCheckbox;
+ private JTextField serverPortField;
+
+ private final List<JCheckBox> checkBoxes = new ArrayList<JCheckBox>();
+ private final List<String> checkBoxesRuleIds = new ArrayList<String>();
+ private final List<String> checkBoxesCategories = new ArrayList<String>();
+
+ private final List<String> defaultOffRules = new ArrayList<String>();
+
+ private Set<String> inactiveRuleIds = new HashSet<String>();
+ private Set<String> enabledRuleIds = new HashSet<String>();
+ private Set<String> inactiveCategoryNames = new HashSet<String>();
+ private final List<JCheckBox> categoryCheckBoxes = new ArrayList<JCheckBox>();
+ private final List<String> checkBoxesCategoryNames = new ArrayList<String>();
+ private Language motherTongue;
+ private boolean serverMode;
+ private int serverPort;
+
+ private final Frame owner;
+ private final boolean insideOOo;
+
+ public ConfigurationDialog(Frame owner, boolean insideOOo) {
+ this.owner = owner;
+ this.insideOOo = insideOOo;
+ messages = JLanguageTool.getMessageBundle();
+ }
+
+ public void show(List<Rule> rules) {
+ dialog = new JDialog(owner, true);
+ dialog.setTitle(messages.getString("guiConfigWindowTitle"));
+ checkBoxes.clear();
+ checkBoxesRuleIds.clear();
+ categoryCheckBoxes.clear();
+ checkBoxesCategoryNames.clear();
+
+ Collections.sort(rules, new CategoryComparator());
+
+ // close dialog when user presses Escape key:
+ final KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ final ActionListener actionListener = new ActionListener() {
+ public void actionPerformed(@SuppressWarnings("unused") ActionEvent actionEvent) {
+ dialog.setVisible(false);
+ }
+ };
+ final JRootPane rootPane = dialog.getRootPane();
+ rootPane.registerKeyboardAction(actionListener, stroke,
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ // JPanel
+ final JPanel checkBoxPanel = new JPanel();
+ checkBoxPanel.setLayout(new GridBagLayout());
+ GridBagConstraints cons = new GridBagConstraints();
+ cons.anchor = GridBagConstraints.NORTHWEST;
+ cons.gridx = 0;
+ int row = 0;
+ String prevID = null;
+ String prevCategory = null;
+ for (final Rule rule : rules) {
+ // avoid displaying rules from rule groups more than once:
+ if (prevID == null || !rule.getId().equals(prevID)) {
+ cons.gridy = row;
+ final JCheckBox checkBox = new JCheckBox(rule.getDescription());
+ if (inactiveRuleIds != null
+ && (inactiveRuleIds.contains(rule.getId()) || inactiveCategoryNames
+ .contains(rule.getCategory().getName()))) {
+ checkBox.setSelected(false);
+ } else {
+ checkBox.setSelected(true);
+ }
+
+ if (rule.isDefaultOff() && !enabledRuleIds.contains(rule.getId())) {
+ checkBox.setSelected(false);
+ }
+
+ if (rule.isDefaultOff()) {
+ defaultOffRules.add(rule.getId());
+ if (rule.getCategory().isDefaultOff()) {
+ inactiveCategoryNames.add(rule.getCategory().getName());
+ }
+ } else {
+ if (rule.getCategory().isDefaultOff()) {
+ inactiveCategoryNames.remove(rule.getCategory().getName());
+ }
+ }
+
+ final ActionListener ruleCheckBoxListener = new ActionListener() {
+ public void actionPerformed(final ActionEvent actionEvent) {
+ final JCheckBox cBox = (JCheckBox) actionEvent.getSource();
+ final boolean selected = cBox.getModel().isSelected();
+ int i = 0;
+ for (final JCheckBox chBox : checkBoxes) {
+ if (chBox.equals(cBox)) {
+ final int catNo = checkBoxesCategoryNames
+ .indexOf(checkBoxesCategories.get(i));
+ if (selected && !categoryCheckBoxes.get(catNo).isSelected()) {
+ categoryCheckBoxes.get(catNo).setSelected(true);
+ }
+ }
+ i++;
+ }
+ }
+ };
+ checkBox.addActionListener(ruleCheckBoxListener);
+ checkBoxes.add(checkBox);
+ checkBoxesRuleIds.add(rule.getId());
+ checkBoxesCategories.add(rule.getCategory().getName());
+ final boolean showHeadline = rule.getCategory() != null
+ && !rule.getCategory().getName().equals(prevCategory);
+ if ((showHeadline || prevCategory == null)
+ && rule.getCategory() != null) {
+
+ // TODO: maybe use a Tree of Checkboxes here, like in:
+ // http://www.javaworld.com/javaworld/jw-09-2007/jw-09-checkboxtree.html
+ final JCheckBox categoryCheckBox = new JCheckBox(rule.getCategory()
+ .getName());
+ if (inactiveCategoryNames != null
+ && inactiveCategoryNames.contains(rule.getCategory().getName())) {
+ categoryCheckBox.setSelected(false);
+ } else {
+ categoryCheckBox.setSelected(true);
+ }
+
+ final ActionListener categoryCheckBoxListener = new ActionListener() {
+ public void actionPerformed(final ActionEvent actionEvent) {
+ final JCheckBox cBox = (JCheckBox) actionEvent.getSource();
+ final boolean selected = cBox.getModel().isSelected();
+ int i = 0;
+ for (final JCheckBox ruleBox : checkBoxes) {
+ if (ruleBox.isSelected() != selected) {
+ if (checkBoxesCategories.get(i).equals(cBox.getText())) {
+ ruleBox.setSelected(selected);
+ }
+ }
+ i++;
+ }
+ }
+ };
+
+ categoryCheckBox.addActionListener(categoryCheckBoxListener);
+ categoryCheckBoxes.add(categoryCheckBox);
+ checkBoxesCategoryNames.add(rule.getCategory().getName());
+ checkBoxPanel.add(categoryCheckBox, cons);
+ prevCategory = rule.getCategory().getName();
+ cons.gridy++;
+ row++;
+ }
+ checkBox.setMargin(new Insets(0, 20, 0, 0)); // indent
+ checkBoxPanel.add(checkBox, cons);
+ row++;
+ }
+ prevID = rule.getId();
+ }
+
+ final JPanel motherTonguePanel = new JPanel();
+ motherTonguePanel.add(new JLabel(messages.getString("guiMotherTongue")),
+ cons);
+ motherTongueBox = new JComboBox(getPossibleMotherTongues());
+ if (motherTongue != null) {
+ if (motherTongue == Language.DEMO) {
+ motherTongueBox.setSelectedItem(NO_MOTHER_TONGUE);
+ } else {
+ motherTongueBox.setSelectedItem(messages.getString(motherTongue
+ .getShortName()));
+ }
+ }
+ motherTonguePanel.add(motherTongueBox, cons);
+
+ final JPanel portPanel = new JPanel();
+ portPanel.setLayout(new GridBagLayout());
+ // TODO: why is this now left-aligned?!?!
+ cons = new GridBagConstraints();
+ cons.insets = new Insets(0, 4, 0, 0);
+ cons.gridx = 0;
+ cons.gridy = 0;
+ cons.anchor = GridBagConstraints.WEST;
+ cons.fill = GridBagConstraints.NONE;
+ cons.weightx = 0.0f;
+ if (!insideOOo) {
+ serverCheckbox = new JCheckBox(StringTools.getLabel(messages
+ .getString("guiRunOnPort")));
+ serverCheckbox.setMnemonic(StringTools.getMnemonic(messages
+ .getString("guiRunOnPort")));
+ serverCheckbox.setSelected(serverMode);
+ portPanel.add(serverCheckbox, cons);
+ serverPortField = new JTextField(Integer.toString(serverPort));
+ serverPortField.setEnabled(serverCheckbox.isSelected());
+ // TODO: without this the box is just a few pixels small, but why??:
+ serverPortField.setMinimumSize(new Dimension(100, 25));
+ cons.gridx = 1;
+ serverCheckbox.addActionListener(new ActionListener() {
+ public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) {
+ serverPortField.setEnabled(serverCheckbox.isSelected());
+ }
+ });
+ portPanel.add(serverPortField, cons);
+ }
+
+ final JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new GridBagLayout());
+ okButton = new JButton(StringTools.getLabel(messages
+ .getString("guiOKButton")));
+ okButton.setMnemonic(StringTools.getMnemonic(messages
+ .getString("guiOKButton")));
+ okButton.addActionListener(this);
+ cancelButton = new JButton(StringTools.getLabel(messages
+ .getString("guiCancelButton")));
+ cancelButton.setMnemonic(StringTools.getMnemonic(messages
+ .getString("guiCancelButton")));
+ cancelButton.addActionListener(this);
+ cons = new GridBagConstraints();
+ cons.insets = new Insets(0, 4, 0, 0);
+ buttonPanel.add(okButton, cons);
+ buttonPanel.add(cancelButton, cons);
+
+ final Container contentPane = dialog.getContentPane();
+ contentPane.setLayout(new GridBagLayout());
+ cons = new GridBagConstraints();
+ cons.insets = new Insets(4, 4, 4, 4);
+ cons.gridx = 0;
+ cons.gridy = 0;
+ cons.weightx = 10.0f;
+ cons.weighty = 10.0f;
+ cons.fill = GridBagConstraints.BOTH;
+ contentPane.add(new JScrollPane(checkBoxPanel), cons);
+
+ cons.gridx = 0;
+ cons.gridy = 1;
+ cons.weightx = 0.0f;
+ cons.weighty = 0.0f;
+ cons.fill = GridBagConstraints.NONE;
+ cons.anchor = GridBagConstraints.WEST;
+ contentPane.add(motherTonguePanel, cons);
+
+ cons.gridx = 0;
+ cons.gridy = 2;
+ cons.weightx = 0.0f;
+ cons.weighty = 0.0f;
+ cons.fill = GridBagConstraints.NONE;
+ cons.anchor = GridBagConstraints.WEST;
+ contentPane.add(portPanel, cons);
+
+ cons.gridx = 0;
+ cons.gridy = 3;
+ cons.weightx = 0.0f;
+ cons.weighty = 0.0f;
+ cons.fill = GridBagConstraints.NONE;
+ cons.anchor = GridBagConstraints.EAST;
+ contentPane.add(buttonPanel, cons);
+
+ dialog.pack();
+ dialog.setSize(500, 500);
+ // center on screen:
+ final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ final Dimension frameSize = dialog.getSize();
+ dialog.setLocation(screenSize.width / 2 - frameSize.width / 2,
+ screenSize.height / 2 - frameSize.height / 2);
+ dialog.setVisible(true);
+ }
+
+ private Object[] getPossibleMotherTongues() {
+ final List<Object> motherTongues = new ArrayList<Object>();
+ motherTongues.add(NO_MOTHER_TONGUE);
+ for (final Language lang : Language.LANGUAGES) {
+ if (lang != Language.DEMO) {
+ motherTongues.add(messages.getString(lang.getShortName()));
+ }
+ }
+ return motherTongues.toArray();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == okButton) {
+ int i = 0;
+ inactiveCategoryNames.clear();
+ for (final JCheckBox checkBox : categoryCheckBoxes) {
+ if (!checkBox.isSelected()) {
+ final String categoryName = checkBoxesCategoryNames.get(i);
+ inactiveCategoryNames.add(categoryName);
+ }
+ i++;
+ }
+ i = 0;
+ inactiveRuleIds.clear();
+ enabledRuleIds.clear();
+ for (final JCheckBox checkBox : checkBoxes) {
+ if (!checkBox.isSelected()) {
+ final String ruleId = checkBoxesRuleIds.get(i);
+ if (!defaultOffRules.contains(ruleId)) {
+ inactiveRuleIds.add(ruleId);
+ }
+ }
+
+ if (checkBox.isSelected()) {
+ final String ruleId = checkBoxesRuleIds.get(i);
+ if (defaultOffRules.contains(ruleId)) {
+ enabledRuleIds.add(ruleId);
+ }
+ }
+
+ i++;
+ }
+
+ if (motherTongueBox.getSelectedItem() instanceof String) {
+ motherTongue = getLanguageForLocalizedName(motherTongueBox
+ .getSelectedItem().toString());
+ } else {
+ motherTongue = (Language) motherTongueBox.getSelectedItem();
+ }
+ if (serverCheckbox != null) {
+ serverMode = serverCheckbox.isSelected();
+ serverPort = Integer.parseInt(serverPortField.getText());
+ }
+ dialog.setVisible(false);
+ } else if (e.getSource() == cancelButton) {
+ dialog.setVisible(false);
+ }
+ }
+
+ public void setDisabledRules(Set<String> ruleIDs) {
+ inactiveRuleIds = ruleIDs;
+ }
+
+ public Set<String> getDisabledRuleIds() {
+ return inactiveRuleIds;
+ }
+
+ public void setEnabledRules(Set<String> ruleIDs) {
+ enabledRuleIds = ruleIDs;
+ }
+
+ public Set<String> getEnabledRuleIds() {
+ return enabledRuleIds;
+ }
+
+ public void setDisabledCategories(Set<String> categoryNames) {
+ inactiveCategoryNames = categoryNames;
+ }
+
+ public Set<String> getDisabledCategoryNames() {
+ return inactiveCategoryNames;
+ }
+
+ public void setMotherTongue(Language motherTongue) {
+ this.motherTongue = motherTongue;
+ }
+
+ public Language getMotherTongue() {
+ return motherTongue;
+ }
+
+ /**
+ * Get the Language object for the given localized language name.
+ *
+ * @param languageName
+ * e.g. <code>English</code> or <code>German</code> (case is
+ * significant)
+ * @return a Language object or <code>null</code>
+ */
+ private Language getLanguageForLocalizedName(final String languageName) {
+ for (final Language element : Language.LANGUAGES) {
+ if (NO_MOTHER_TONGUE.equals(languageName)) {
+ return Language.DEMO;
+ }
+ if (languageName.equals(messages.getString(element.getShortName()))) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ public void setRunServer(boolean serverMode) {
+ this.serverMode = serverMode;
+ }
+
+ public boolean getRunServer() {
+ if (serverCheckbox == null) {
+ return false;
+ }
+ return serverCheckbox.isSelected();
+ }
+
+ public void setServerPort(int serverPort) {
+ this.serverPort = serverPort;
+ }
+
+ public int getServerPort() {
+ if (serverPortField == null) {
+ return HTTPServer.DEFAULT_PORT;
+ }
+ return Integer.parseInt(serverPortField.getText());
+ }
+
+ /**
+ * Opens the dialog - for internal testing only.
+ */
+ public static void main(String[] args) throws IOException {
+ final ConfigurationDialog dlg = new ConfigurationDialog(null, false);
+ final List<Rule> rules = new ArrayList<Rule>();
+ final JLanguageTool lt = new JLanguageTool(Language.ENGLISH);
+ lt.activateDefaultPatternRules();
+ rules.addAll(lt.getAllRules());
+ dlg.show(rules);
+ }
+
+}
+
+class CategoryComparator implements Comparator<Rule> {
+
+ public int compare(final Rule r1, final Rule r2) {
+ final boolean hasCat = r1.getCategory() != null && r2.getCategory() != null;
+ if (hasCat) {
+ final int res = r1.getCategory().getName().compareTo(
+ r2.getCategory().getName());
+ if (res == 0) {
+ return r1.getDescription().compareToIgnoreCase(r2.getDescription());
+ }
+ return res;
+ }
+ return r1.getDescription().compareToIgnoreCase(r2.getDescription());
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/LanguageManagerDialog.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/LanguageManagerDialog.java
new file mode 100644
index 0000000..18c5b26
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/LanguageManagerDialog.java
@@ -0,0 +1,184 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2007 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.KeyStroke;
+import javax.swing.filechooser.FileFilter;
+
+import de.danielnaber.languagetool.Language;
+import de.danielnaber.languagetool.language.LanguageBuilder;
+
+/**
+ * Dialog for managing externally loaded rules.
+ *
+ * @author Daniel Naber
+ */
+public class LanguageManagerDialog implements ActionListener {
+
+ private JDialog dialog;
+
+ private JList list;
+ private JButton addButton;
+ private JButton removeButton;
+ private JButton closeButton;
+ private final List<File> ruleFiles = new ArrayList<File>();
+
+ private final Frame owner;
+ //private ResourceBundle messages = null;
+
+ public LanguageManagerDialog(Frame owner, List<Language> languages) {
+ this.owner = owner;
+ for (Language lang : languages) {
+ ruleFiles.add(new File(lang.getRuleFileName()));
+ }
+ //messages = JLanguageTool.getMessageBundle();
+ }
+
+ public void show() {
+ dialog = new JDialog(owner, true);
+ dialog.setTitle("Language Module Manager"); // FIXME: i18n
+
+ // close dialog when user presses Escape key:
+ // TODO: taken from ConfigurationDialog, avoid duplication:
+ final KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ final ActionListener actionListener = new ActionListener() {
+ @SuppressWarnings("unused")
+ public void actionPerformed(ActionEvent actionEvent) {
+ dialog.setVisible(false);
+ }
+ };
+ final JRootPane rootPane = dialog.getRootPane();
+ rootPane.registerKeyboardAction(actionListener, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ final Container contentPane = dialog.getContentPane();
+ contentPane.setLayout(new GridBagLayout());
+
+ list = new JList(ruleFiles.toArray(new File[]{}));
+ GridBagConstraints cons = new GridBagConstraints();
+ cons.insets = new Insets(4, 4, 4, 4);
+ cons.gridx = 0;
+ cons.gridy = 0;
+ cons.fill = GridBagConstraints.BOTH;
+ cons.weightx = 2.0f;
+ cons.weighty = 2.0f;
+ contentPane.add(new JScrollPane(list), cons);
+
+ cons = new GridBagConstraints();
+ cons.insets = new Insets(4, 4, 4, 4);
+ cons.fill = GridBagConstraints.HORIZONTAL;
+
+ final JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new GridBagLayout());
+ addButton = new JButton("Add..."); // FIXME: i18n
+ addButton.addActionListener(this);
+ cons.gridx = 1;
+ cons.gridy = 0;
+ buttonPanel.add(addButton, cons);
+
+ removeButton = new JButton("Remove"); // FIXME: i18n
+ removeButton.addActionListener(this);
+ cons.gridx = 1;
+ cons.gridy = 1;
+ buttonPanel.add(removeButton, cons);
+
+ closeButton = new JButton("Close"); // FIXME: i18n
+ closeButton.addActionListener(this);
+ cons.gridx = 1;
+ cons.gridy = 2;
+ buttonPanel.add(closeButton, cons);
+
+ cons.gridx = 1;
+ cons.gridy = 0;
+ cons = new GridBagConstraints();
+ cons.anchor = GridBagConstraints.NORTH;
+ contentPane.add(buttonPanel, cons);
+
+ dialog.pack();
+ dialog.setSize(300, 200);
+ // center on screen:
+ final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ final Dimension frameSize = dialog.getSize();
+ dialog.setLocation(screenSize.width/2 - (frameSize.width/2), screenSize.height/2 - (frameSize.height/2));
+ dialog.setVisible(true);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == addButton) {
+ final File ruleFile = Tools.openFileDialog(null, new XMLFileFilter());
+ // TODO: avoid duplicate files!
+ ruleFiles.add(ruleFile);
+ list.setListData(ruleFiles.toArray(new File[]{}));
+ } else if (e.getSource() == removeButton) {
+ if (list.getSelectedIndex() != -1) {
+ ruleFiles.remove(list.getSelectedIndex());
+ list.setListData(ruleFiles.toArray(new File[]{}));
+ }
+ } else if (e.getSource() == closeButton) {
+ dialog.setVisible(false);
+ } else {
+ throw new IllegalArgumentException("Don't know how to handle " + e);
+ }
+ }
+
+ /**
+ * Return all external Languages.
+ */
+ List<Language> getLanguages() {
+ final List<Language> languages = new ArrayList<Language>();
+ for (File ruleFile : ruleFiles) {
+ final Language newLanguage = LanguageBuilder.makeLanguage(ruleFile);
+ languages.add(newLanguage);
+ }
+ return languages;
+ }
+
+ static class XMLFileFilter extends FileFilter {
+ public boolean accept(final File f) {
+ if (f.getName().toLowerCase().endsWith(".xml") || f.isDirectory()) {
+ return true;
+ }
+ return false;
+ }
+ public String getDescription() {
+ return "*.xml";
+ }
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Main.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Main.java
new file mode 100644
index 0000000..eb73813
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Main.java
@@ -0,0 +1,738 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.awt.AWTException;
+import java.awt.Container;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextPane;
+import javax.swing.UIManager;
+import javax.swing.WindowConstants;
+import javax.swing.filechooser.FileFilter;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.jdesktop.jdic.tray.SystemTray;
+import org.jdesktop.jdic.tray.TrayIcon;
+import org.xml.sax.SAXException;
+
+import de.danielnaber.languagetool.JLanguageTool;
+import de.danielnaber.languagetool.Language;
+import de.danielnaber.languagetool.language.RuleFilenameException;
+import de.danielnaber.languagetool.rules.Rule;
+import de.danielnaber.languagetool.rules.RuleMatch;
+import de.danielnaber.languagetool.server.HTTPServer;
+import de.danielnaber.languagetool.server.PortBindingException;
+import de.danielnaber.languagetool.tools.StringTools;
+
+/**
+ * A simple GUI to check texts with.
+ *
+ * @author Daniel Naber
+ */
+public final class Main implements ActionListener {
+
+ private final ResourceBundle messages;
+
+ private static final String HTML_FONT_START = "<font face='Arial,Helvetica'>";
+ private static final String HTML_FONT_END = "</font>";
+
+ private final static String SYSTEM_TRAY_ICON_NAME = "/TrayIcon.png";
+ private static final String SYSTEM_TRAY_TOOLTIP = "LanguageTool";
+ private static final String CONFIG_FILE = ".languagetool.cfg";
+
+ private final Configuration config;
+
+ private JFrame frame;
+ private JTextArea textArea;
+ private JTextPane resultArea;
+ private JComboBox langBox;
+
+ private HTTPServer httpServer;
+
+ private final Map<Language, ConfigurationDialog> configDialogs = new HashMap<Language, ConfigurationDialog>();
+
+ // whether clicking on the window close button hides to system tray:
+ private boolean trayMode;
+
+ private boolean isInTray;
+
+ private Main() throws IOException {
+ config = new Configuration(new File(System.getProperty("user.home")),
+ CONFIG_FILE);
+ messages = JLanguageTool.getMessageBundle();
+ maybeStartServer();
+ }
+
+ private void createGUI() {
+ frame = new JFrame("LanguageTool " + JLanguageTool.VERSION);
+
+ try {
+ for (UIManager.LookAndFeelInfo info : UIManager
+ .getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ // Well, what can we do...
+ }
+
+ frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ frame.addWindowListener(new CloseListener());
+ frame.setIconImage(new ImageIcon(JLanguageTool.getDataBroker().getFromResourceDirAsUrl(
+ Main.SYSTEM_TRAY_ICON_NAME)).getImage());
+ frame.setJMenuBar(new MainMenuBar(this, messages));
+
+ textArea = new JTextArea(messages.getString("guiDemoText"));
+ // TODO: wrong line number is displayed for lines that are wrapped
+ // automatically:
+ textArea.setLineWrap(true);
+ textArea.setWrapStyleWord(true);
+ resultArea = new JTextPane();
+ resultArea.setContentType("text/html");
+ resultArea.setText(HTML_FONT_START + messages.getString("resultAreaText")
+ + HTML_FONT_END);
+ resultArea.setEditable(false);
+ final JLabel label = new JLabel(messages.getString("enterText"));
+ final JButton button = new JButton(StringTools.getLabel(messages
+ .getString("checkText")));
+ button
+ .setMnemonic(StringTools.getMnemonic(messages.getString("checkText")));
+ button.addActionListener(this);
+
+ final JPanel panel = new JPanel();
+ panel.setLayout(new GridBagLayout());
+ final GridBagConstraints buttonCons = new GridBagConstraints();
+ buttonCons.gridx = 0;
+ buttonCons.gridy = 0;
+ panel.add(button, buttonCons);
+ buttonCons.gridx = 1;
+ buttonCons.gridy = 0;
+ panel.add(new JLabel(" " + messages.getString("textLanguage") + " "),
+ buttonCons);
+ buttonCons.gridx = 2;
+ buttonCons.gridy = 0;
+ langBox = new JComboBox();
+ populateLanguageBox();
+ // use the system default language to preselect the language from the combo
+ // box:
+ try {
+ final Locale defaultLocale = Locale.getDefault();
+ langBox.setSelectedItem(messages.getString(defaultLocale.getLanguage()));
+ } catch (final MissingResourceException e) {
+ // language not supported, so don't select a default
+ }
+ panel.add(langBox, buttonCons);
+
+ final Container contentPane = frame.getContentPane();
+ final GridBagLayout gridLayout = new GridBagLayout();
+ contentPane.setLayout(gridLayout);
+ final GridBagConstraints cons = new GridBagConstraints();
+ cons.insets = new Insets(5, 5, 5, 5);
+ cons.fill = GridBagConstraints.BOTH;
+ cons.weightx = 10.0f;
+ cons.weighty = 10.0f;
+ cons.gridx = 0;
+ cons.gridy = 1;
+ cons.weighty = 5.0f;
+ final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ new JScrollPane(textArea), new JScrollPane(resultArea));
+ splitPane.setDividerLocation(200);
+ contentPane.add(splitPane, cons);
+
+ cons.fill = GridBagConstraints.NONE;
+ cons.gridx = 0;
+ cons.gridy = 2;
+ cons.weighty = 0.0f;
+ cons.insets = new Insets(3, 3, 3, 3);
+ // cons.fill = GridBagConstraints.NONE;
+ contentPane.add(label, cons);
+ cons.gridy = 3;
+ contentPane.add(panel, cons);
+
+ frame.pack();
+ frame.setSize(600, 550);
+ }
+
+ private void populateLanguageBox() {
+ final List<String> toSort = new ArrayList<String>();
+ langBox.removeAllItems();
+ for (final Language lang : Language.LANGUAGES) {
+ if (lang != Language.DEMO) {
+ try {
+ toSort.add(messages.getString(lang.getShortName()));
+ } catch (final MissingResourceException e) {
+ // can happen with external rules:
+ toSort.add(lang.getName());
+ }
+ }
+ }
+ Collections.sort(toSort);
+ for (final String lng : toSort) {
+ langBox.addItem(lng);
+ }
+ }
+
+ private void showGUI() {
+ frame.setVisible(true);
+ }
+
+ public void actionPerformed(final ActionEvent e) {
+ try {
+ if (e.getActionCommand().equals(
+ StringTools.getLabel(messages.getString("checkText")))) {
+ final JLanguageTool langTool = getCurrentLanguageTool();
+ checkTextAndDisplayResults(langTool, getCurrentLanguage());
+ } else {
+ throw new IllegalArgumentException("Unknown action " + e);
+ }
+ } catch (final Exception exc) {
+ Tools.showError(exc);
+ }
+ }
+
+ void loadFile() {
+ final File file = Tools.openFileDialog(frame, new PlainTextFilter());
+ if (file == null) {
+ return;
+ }
+ try {
+ final String fileContents = StringTools.readFile(new FileInputStream(file
+ .getAbsolutePath()));
+ textArea.setText(fileContents);
+ final JLanguageTool langTool = getCurrentLanguageTool();
+ checkTextAndDisplayResults(langTool, getCurrentLanguage());
+ } catch (final IOException e) {
+ Tools.showError(e);
+ }
+ }
+
+ void hideToTray() {
+ final String version = System.getProperty("java.version");
+ if (!isInTray && version.startsWith("1.5")) { // we don't run under <= 1.4,
+ // so we don't check for that
+ TrayIcon trayIcon = null;
+ try {
+ final Icon sysTrayIcon = new ImageIcon(JLanguageTool.getDataBroker().getFromResourceDirAsUrl(Main.SYSTEM_TRAY_ICON_NAME));
+ trayIcon = new TrayIcon(sysTrayIcon);
+ } catch (final NoClassDefFoundError e) {
+ throw new MissingJdicException(e);
+ }
+ final SystemTray tray = SystemTray.getDefaultSystemTray();
+ trayIcon.addActionListener(new TrayActionListener());
+ trayIcon.setToolTip(SYSTEM_TRAY_TOOLTIP);
+ tray.addTrayIcon(trayIcon);
+ } else if (!isInTray) {
+ // Java 1.6 or later
+ final java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray();
+ final Image img = Toolkit.getDefaultToolkit().getImage(
+ JLanguageTool.getDataBroker().getFromResourceDirAsUrl(Main.SYSTEM_TRAY_ICON_NAME));
+ final PopupMenu popup = makePopupMenu();
+ try {
+ final java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(img,
+ "tooltip", popup);
+ trayIcon.addMouseListener(new TrayActionListener());
+ trayIcon.setToolTip(SYSTEM_TRAY_TOOLTIP);
+ tray.add(trayIcon);
+ } catch (final AWTException e1) {
+ // thrown if there's no system tray
+ Tools.showError(e1);
+ }
+ }
+ isInTray = true;
+ frame.setVisible(false);
+ }
+
+ private PopupMenu makePopupMenu() {
+ final PopupMenu popup = new PopupMenu();
+ final ActionListener rmbListener = new TrayActionRMBListener();
+ // Check clipboard text:
+ final MenuItem checkClipboardItem = new MenuItem(StringTools
+ .getLabel(messages.getString("guiMenuCheckClipboard")));
+ checkClipboardItem.addActionListener(rmbListener);
+ popup.add(checkClipboardItem);
+ // Open main window:
+ final MenuItem restoreItem = new MenuItem(StringTools.getLabel(messages
+ .getString("guiMenuShowMainWindow")));
+ restoreItem.addActionListener(rmbListener);
+ popup.add(restoreItem);
+ // Exit:
+ final MenuItem exitItem = new MenuItem(StringTools.getLabel(messages
+ .getString("guiMenuQuit")));
+ exitItem.addActionListener(rmbListener);
+ popup.add(exitItem);
+ return popup;
+ }
+
+ void addLanguage() {
+ final LanguageManagerDialog lmd = new LanguageManagerDialog(frame, Language
+ .getExternalLanguages());
+ lmd.show();
+ try {
+ Language.reInit(lmd.getLanguages());
+ } catch (final RuleFilenameException e) {
+ Tools.showErrorMessage(e);
+ }
+ populateLanguageBox();
+ }
+
+ void showOptions() {
+ final JLanguageTool langTool = getCurrentLanguageTool();
+ final List<Rule> rules = langTool.getAllRules();
+ final ConfigurationDialog configDialog = getCurrentConfigDialog();
+ configDialog.show(rules); // this blocks until OK/Cancel is clicked in the
+ // dialog
+ config.setDisabledRuleIds(configDialog.getDisabledRuleIds());
+ config.setEnabledRuleIds(configDialog.getEnabledRuleIds());
+ config.setDisabledCategoryNames(configDialog.getDisabledCategoryNames());
+ config.setMotherTongue(configDialog.getMotherTongue());
+ config.setRunServer(configDialog.getRunServer());
+ config.setServerPort(configDialog.getServerPort());
+ // Stop server, start new server if requested:
+ stopServer();
+ maybeStartServer();
+ }
+
+ private void restoreFromTray() {
+ frame.setVisible(true);
+ }
+
+ // show GUI and check the text from clipboard/selection:
+ private void restoreFromTrayAndCheck() {
+ final String s = getClipboardText();
+ restoreFromTray();
+ textArea.setText(s);
+ final JLanguageTool langTool = getCurrentLanguageTool();
+ checkTextAndDisplayResults(langTool, getCurrentLanguage());
+ }
+
+ void checkClipboardText() {
+ final String s = getClipboardText();
+ textArea.setText(s);
+ final JLanguageTool langTool = getCurrentLanguageTool();
+ checkTextAndDisplayResults(langTool, getCurrentLanguage());
+ }
+
+ private String getClipboardText() {
+ // get text from clipboard or selection:
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemSelection();
+ if (clipboard == null) { // on Windows
+ clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ }
+ String s = null;
+ final Transferable data = clipboard.getContents(this);
+ try {
+ if (data != null
+ && data.isDataFlavorSupported(DataFlavor.getTextPlainUnicodeFlavor())) {
+ final DataFlavor df = DataFlavor.getTextPlainUnicodeFlavor();
+ final Reader sr = df.getReaderForText(data);
+ s = StringTools.readerToString(sr);
+ } else {
+ s = "";
+ }
+ } catch (final Exception ex) {
+ ex.printStackTrace();
+ if (data != null) {
+ s = data.toString();
+ } else {
+ s = "";
+ }
+ }
+ return s;
+ }
+
+ void quitOrHide() {
+ if (trayMode) {
+ hideToTray();
+ } else {
+ quit();
+ }
+ }
+
+ void quit() {
+ stopServer();
+ try {
+ config.saveConfiguration();
+ } catch (final IOException e) {
+ Tools.showError(e);
+ }
+ frame.setVisible(false);
+ System.exit(0);
+ }
+
+ private void maybeStartServer() {
+ if (config.getRunServer()) {
+ httpServer = new HTTPServer(config.getServerPort());
+ try {
+ httpServer.run();
+ } catch (final PortBindingException e) {
+ JOptionPane.showMessageDialog(null, e.getMessage(), "Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ private void stopServer() {
+ if (httpServer != null) {
+ httpServer.stop();
+ httpServer = null;
+ }
+ }
+
+ private Language getCurrentLanguage() {
+ final String langName = langBox.getSelectedItem().toString();
+ String lang = langName;
+ for (final Enumeration<String> e = messages.getKeys(); e.hasMoreElements();) {
+ final String elem = e.nextElement();
+ if (messages.getString(elem).equals(langName)) {
+ lang = elem;
+ break;
+ }
+ }
+ // external rules:
+ if (lang.length() > 2) {
+ return Language.getLanguageForName(lang);
+ }
+ return Language.getLanguageForShortName(lang);
+ }
+
+ private ConfigurationDialog getCurrentConfigDialog() {
+ final Language language = getCurrentLanguage();
+ ConfigurationDialog configDialog = null;
+ if (configDialogs.containsKey(language)) {
+ configDialog = configDialogs.get(language);
+ } else {
+ configDialog = new ConfigurationDialog(frame, false);
+ configDialog.setMotherTongue(config.getMotherTongue());
+ configDialog.setDisabledRules(config.getDisabledRuleIds());
+ configDialog.setEnabledRules(config.getEnabledRuleIds());
+ configDialog.setDisabledCategories(config.getDisabledCategoryNames());
+ configDialog.setRunServer(config.getRunServer());
+ configDialog.setServerPort(config.getServerPort());
+ configDialogs.put(language, configDialog);
+ }
+ return configDialog;
+ }
+
+ private JLanguageTool getCurrentLanguageTool() {
+ final JLanguageTool langTool;
+ try {
+ final ConfigurationDialog configDialog = getCurrentConfigDialog();
+ langTool = new JLanguageTool(getCurrentLanguage(), configDialog
+ .getMotherTongue());
+ langTool.activateDefaultPatternRules();
+ langTool.activateDefaultFalseFriendRules();
+ final Set<String> disabledRules = configDialog.getDisabledRuleIds();
+ if (disabledRules != null) {
+ for (final String ruleId : disabledRules) {
+ langTool.disableRule(ruleId);
+ }
+ }
+ final Set<String> disabledCategories = configDialog
+ .getDisabledCategoryNames();
+ if (disabledCategories != null) {
+ for (final String categoryName : disabledCategories) {
+ langTool.disableCategory(categoryName);
+ }
+ }
+ final Set<String> enabledRules = configDialog.getEnabledRuleIds();
+ if (enabledRules != null) {
+ for (String ruleName : enabledRules) {
+ langTool.enableDefaultOffRule(ruleName);
+ langTool.enableRule(ruleName);
+ }
+ }
+ } catch (final IOException ioe) {
+ throw new RuntimeException(ioe);
+ } catch (final ParserConfigurationException ex) {
+ throw new RuntimeException(ex);
+ } catch (final SAXException ex) {
+ throw new RuntimeException(ex);
+ }
+ return langTool;
+ }
+
+ private void checkTextAndDisplayResults(final JLanguageTool langTool,
+ final Language lang) {
+ if (StringTools.isEmpty(textArea.getText().trim())) {
+ textArea.setText(messages.getString("enterText2"));
+ } else {
+ final StringBuilder sb = new StringBuilder();
+ final String startCheckText = Tools.makeTexti18n(messages,
+ "startChecking", new Object[] { lang.getTranslatedName(messages) });
+ resultArea.setText(HTML_FONT_START + startCheckText + "<br>\n"
+ + HTML_FONT_END);
+ resultArea.repaint(); // FIXME: why doesn't this work?
+ // TODO: resultArea.setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ sb.append(startCheckText);
+ sb.append("...<br>\n");
+ int matches = 0;
+ try {
+ matches = checkText(langTool, textArea.getText(), sb);
+ } catch (final Exception ex) {
+ sb.append("<br><br><b><font color=\"red\">" + ex.toString() + "<br>");
+ final StackTraceElement[] elements = ex.getStackTrace();
+ for (final StackTraceElement element : elements) {
+ sb.append(element);
+ sb.append("<br>");
+ }
+ sb.append("</font></b><br>");
+ ex.printStackTrace();
+ }
+ final String checkDone = Tools.makeTexti18n(messages, "checkDone",
+ new Object[] {matches});
+ sb.append(checkDone);
+ sb.append("<br>\n");
+ resultArea.setText(HTML_FONT_START + sb.toString() + HTML_FONT_END);
+ resultArea.setCaretPosition(0);
+ }
+ }
+
+ private int checkText(final JLanguageTool langTool, final String text,
+ final StringBuilder sb) throws IOException {
+ final long startTime = System.currentTimeMillis();
+ final List<RuleMatch> ruleMatches = langTool.check(text);
+ final long startTimeMatching = System.currentTimeMillis();
+ int i = 0;
+ for (final RuleMatch match : ruleMatches) {
+ final String output = Tools.makeTexti18n(messages, "result1",
+ new Object[] {i + 1,
+ match.getLine() + 1,
+ match.getColumn()});
+ sb.append(output);
+ String msg = match.getMessage();
+ msg = msg.replaceAll("<suggestion>", "<b>");
+ msg = msg.replaceAll("</suggestion>", "</b>");
+ msg = msg.replaceAll("<old>", "<b>");
+ msg = msg.replaceAll("</old>", "</b>");
+ sb.append("<b>" + messages.getString("errorMessage") + "</b> " + msg + "<br>\n");
+ if (match.getSuggestedReplacements().size() > 0) {
+ final String repl = StringTools.listToString(match
+ .getSuggestedReplacements(), "; ");
+ sb.append("<b>" + messages.getString("correctionMessage") + "</b> "
+ + repl + "<br>\n");
+ }
+ final String context = Tools.getContext(match.getFromPos(), match
+ .getToPos(), text);
+ sb.append("<b>" + messages.getString("errorContext") + "</b> " + context);
+ sb.append("<br>\n");
+ i++;
+ }
+ final long endTime = System.currentTimeMillis();
+ sb.append(Tools.makeTexti18n(messages, "resultTime", new Object[] {
+ endTime - startTime,
+ endTime - startTimeMatching}));
+ return ruleMatches.size();
+ }
+
+ private void setTrayMode(boolean trayMode) {
+ this.trayMode = trayMode;
+ }
+
+ public static void main(final String[] args) {
+ try {
+ final Main prg = new Main();
+ if (args.length == 1
+ && (args[0].equals("-t") || args[0].equals("--tray"))) {
+ // dock to systray on startup
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ prg.createGUI();
+ prg.setTrayMode(true);
+ prg.hideToTray();
+ } catch (final MissingJdicException e) {
+ JOptionPane.showMessageDialog(null, e.getMessage(), "Error",
+ JOptionPane.ERROR_MESSAGE);
+ System.exit(1);
+ } catch (final Exception e) {
+ Tools.showError(e);
+ System.exit(1);
+ }
+ }
+ });
+ } else if (args.length >= 1) {
+ System.out
+ .println("Usage: java de.danielnaber.languagetool.gui.Main [-t|--tray]");
+ System.out
+ .println(" -t, --tray: dock LanguageTool to system tray on startup");
+ } else {
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ prg.createGUI();
+ prg.showGUI();
+ } catch (final Exception e) {
+ Tools.showError(e);
+ }
+ }
+ });
+ }
+ } catch (final Exception e) {
+ Tools.showError(e);
+ }
+ }
+
+ //
+ // The System Tray stuff
+ //
+
+ class TrayActionRMBListener implements ActionListener {
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equalsIgnoreCase(
+ StringTools.getLabel(messages.getString("guiMenuCheckClipboard")))) {
+ restoreFromTrayAndCheck();
+ } else if (e.getActionCommand().equalsIgnoreCase(
+ StringTools.getLabel(messages.getString("guiMenuShowMainWindow")))) {
+ restoreFromTray();
+ } else if (e.getActionCommand().equalsIgnoreCase(
+ StringTools.getLabel(messages.getString("guiMenuQuit")))) {
+ quit();
+ } else {
+ JOptionPane.showMessageDialog(null, "Unknown action: "
+ + e.getActionCommand(), "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ }
+
+ class TrayActionListener implements ActionListener, MouseListener {
+
+ // for Java 1.5 / Jdic:
+ public void actionPerformed(@SuppressWarnings("unused")ActionEvent e) {
+ handleClick();
+ }
+
+ // Java 1.6:
+ public void mouseClicked(@SuppressWarnings("unused")MouseEvent e) {
+ handleClick();
+ }
+
+ private void handleClick() {
+ if (frame.isVisible() && frame.isActive()) {
+ frame.setVisible(false);
+ } else if (frame.isVisible() && !frame.isActive()) {
+ frame.toFront();
+ restoreFromTrayAndCheck();
+ } else {
+ restoreFromTrayAndCheck();
+ }
+ }
+
+ public void mouseEntered(@SuppressWarnings("unused") MouseEvent e) {
+ }
+
+ public void mouseExited(@SuppressWarnings("unused")MouseEvent e) {
+ }
+
+ public void mousePressed(@SuppressWarnings("unused")MouseEvent e) {
+ }
+
+ public void mouseReleased(@SuppressWarnings("unused")MouseEvent e) {
+ }
+
+ }
+
+ class CloseListener implements WindowListener {
+
+ public void windowClosing(@SuppressWarnings("unused")WindowEvent e) {
+ quitOrHide();
+ }
+
+ public void windowActivated(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ public void windowClosed(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ public void windowDeactivated(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ public void windowDeiconified(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ public void windowIconified(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ public void windowOpened(@SuppressWarnings("unused")WindowEvent e) {
+ }
+
+ }
+
+ static class PlainTextFilter extends FileFilter {
+
+ @Override
+ public boolean accept(final File f) {
+ if (f.getName().toLowerCase().endsWith(".txt")) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getDescription() {
+ return "*.txt";
+ }
+
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MainMenuBar.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MainMenuBar.java
new file mode 100644
index 0000000..72e3191
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MainMenuBar.java
@@ -0,0 +1,170 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.awt.Event;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.util.ResourceBundle;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.KeyStroke;
+
+import de.danielnaber.languagetool.tools.StringTools;
+
+/**
+ * The menu bar of the main dialog.
+ *
+ * @author Daniel Naber
+ */
+class MainMenuBar extends JMenuBar implements ActionListener {
+
+ private static final long serialVersionUID = -7160998682243081767L;
+
+ private final ResourceBundle messages;
+
+ // File:
+ private String openText;
+ private String checkClipboardText;
+ private String dockToTrayText;
+ private String addLanguageText;
+ private String optionsText;
+ private String quitText;
+ // Help:
+ private String aboutText;
+
+ private final Main prg;
+ private JMenu fileMenu;
+ private JMenu helpMenu;
+
+ MainMenuBar(Main prg, ResourceBundle messages) {
+ this.prg = prg;
+ this.messages = messages;
+ initStrings();
+ fileMenu.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuFile")));
+ helpMenu.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuHelp")));
+ // "Open":
+ final JMenuItem openItem = new JMenuItem(openText);
+ openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Event.CTRL_MASK));
+ openItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuOpen")));
+ openItem.addActionListener(this);
+ fileMenu.add(openItem);
+ // "Check Text in Clipboard":
+ final JMenuItem checkClipboardItem = new JMenuItem(checkClipboardText);
+ checkClipboardItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK));
+ checkClipboardItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuCheckClipboard")));
+ checkClipboardItem.addActionListener(this);
+ fileMenu.add(checkClipboardItem);
+ // "Hide to System Tray":
+ final JMenuItem dockToTrayItem = new JMenuItem(dockToTrayText);
+ dockToTrayItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuHide")));
+ dockToTrayItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, Event.CTRL_MASK));
+ dockToTrayItem.addActionListener(this);
+ fileMenu.add(dockToTrayItem);
+ // "Add Language":
+ final JMenuItem addLanguageItem = new JMenuItem(addLanguageText);
+ addLanguageItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuAddRules")));
+ addLanguageItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Event.CTRL_MASK));
+ addLanguageItem.addActionListener(this);
+ fileMenu.add(addLanguageItem);
+ // "Options":
+ final JMenuItem optionsItem = new JMenuItem(optionsText);
+ optionsItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuOptions")));
+ optionsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK));
+ optionsItem.addActionListener(this);
+ fileMenu.add(optionsItem);
+ // "Quit":
+ final JMenuItem quitItem = new JMenuItem(quitText);
+ quitItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuQuit")));
+ quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, Event.CTRL_MASK));
+ quitItem.addActionListener(this);
+ fileMenu.add(quitItem);
+ // "About":
+ final JMenuItem helpItem = new JMenuItem(aboutText);
+ helpItem.addActionListener(this);
+ helpItem.setMnemonic(StringTools.getMnemonic(
+ messages.getString("guiMenuAbout")));
+ helpMenu.add(helpItem);
+ // add menus:
+ add(fileMenu);
+ add(helpMenu);
+ }
+
+ private void initStrings() {
+ fileMenu = new JMenu(StringTools.getLabel(
+ messages.getString("guiMenuFile")));
+ helpMenu = new JMenu(StringTools.getLabel(
+ messages.getString("guiMenuHelp")));
+ // File:
+ openText = StringTools.getLabel(
+ messages.getString("guiMenuOpen"));
+ checkClipboardText = StringTools.getLabel(
+ messages.getString("guiMenuCheckClipboard"));
+ dockToTrayText = StringTools.getLabel(
+ messages.getString("guiMenuHide"));
+ addLanguageText = StringTools.getLabel(
+ messages.getString("guiMenuAddRules"));
+ optionsText = StringTools.getLabel(
+ messages.getString("guiMenuOptions"));
+ quitText = StringTools.getLabel(
+ messages.getString("guiMenuQuit"));
+ // Help:
+ aboutText = StringTools.getLabel(
+ messages.getString("guiMenuAbout"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals(openText)) {
+ prg.loadFile();
+ } else if (e.getActionCommand().equals(checkClipboardText)) {
+ prg.checkClipboardText();
+ } else if (e.getActionCommand().equals(dockToTrayText)) {
+ try {
+ prg.hideToTray();
+ } catch (MissingJdicException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ } else if (e.getActionCommand().equals(addLanguageText)) {
+ prg.addLanguage();
+ } else if (e.getActionCommand().equals(optionsText)) {
+ prg.showOptions();
+ } else if (e.getActionCommand().equals(quitText)) {
+ prg.quit();
+ } else if (e.getActionCommand().equals(aboutText)) {
+ final AboutDialog about = new AboutDialog(messages);
+ about.show();
+ } else {
+ throw new IllegalArgumentException("Unknown action " + e);
+ }
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MissingJdicException.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MissingJdicException.java
new file mode 100644
index 0000000..6dcf5de
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/MissingJdicException.java
@@ -0,0 +1,38 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2007 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+/**
+ * Exception thrown with Java 1.5 if the jdic library cannot be found.
+ *
+ * @author Daniel Naber
+ */
+public class MissingJdicException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8822404582351420654L;
+
+ public MissingJdicException(Throwable throwable) {
+ super("TrayIcon class not found. Please unzip " +
+ "'standalone-libs.zip' in your LanguageTool installation directory.", throwable);
+ }
+
+}
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Tools.java b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Tools.java
new file mode 100644
index 0000000..5abe803
--- /dev/null
+++ b/JLanguageTool/src/java/de/danielnaber/languagetool/gui/Tools.java
@@ -0,0 +1,192 @@
+/* LanguageTool, a natural language style checker
+ * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+package de.danielnaber.languagetool.gui;
+
+import java.awt.Frame;
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.filechooser.FileFilter;
+
+import de.danielnaber.languagetool.tools.StringTools;
+
+/**
+ * GUI-related tools.
+ *
+ * @author Daniel Naber
+ */
+public class Tools {
+
+ private static final int DEFAULT_CONTEXT_SIZE = 40; // characters
+ private static final String MARKER_START = "<b><font color=\"red\">";
+ private static final String MARKER_END = "</font></b>";
+
+ private Tools() {
+ // no constructor
+ }
+
+ public static String makeTexti18n(final ResourceBundle messages, final String key,
+ final Object[] messageArguments) {
+ final MessageFormat formatter = new MessageFormat("");
+ formatter.applyPattern(messages.getString(key));
+ return formatter.format(messageArguments);
+ }
+
+ /**
+ * Get the default context (40 characters) of the given text range,
+ * highlighting the range with HTML.
+ */
+ public static String getContext(final int fromPos, final int toPos, final String text) {
+ return getContext(fromPos, toPos, text, DEFAULT_CONTEXT_SIZE);
+ }
+
+ /**
+ * Get the context (<code>contextSize</code> characters) of the given text
+ * range, highlighting the range with HTML code.
+ */
+ public static String getContext(final int fromPos, final int toPos, final String fileContents,
+ int contextSize) {
+ return getContext(fromPos, toPos, fileContents, contextSize, MARKER_START,
+ MARKER_END, true);
+ }
+
+ /**
+ * Get the context (<code>contextSize</code> characters) of the given text
+ * range, highlighting the range with the given marker strings, not escaping
+ * HTML.
+ */
+ public static String getContext(final int fromPos, final int toPos,
+ final String fileContents, final int contextSize,
+ final String markerStart, final String markerEnd) {
+ return getContext(fromPos, toPos, fileContents, contextSize, markerStart,
+ markerEnd, false);
+ }
+ /**
+ * Get the context (<code>contextSize</code> characters) of the given text
+ * range, highlighting the range with the given marker strings.
+ *
+ * @param fromPos
+ * the start position of the error in characters
+ * @param toPos
+ * the end position of the error in characters
+ * @param text
+ * the text from which the context should be taken
+ * @param contextSize
+ * the size of the context in characters
+ * @param markerStart
+ * the string used to mark the beginning of the error
+ * @param markerEnd
+ * the string used to mark the end of the error
+ * @param escapeHTML
+ * whether HTML/XML characters should be escaped
+ */
+ public static String getContext(final int fromPos, final int toPos,
+ String text, final int contextSize, final String markerStart,
+ final String markerEnd, final boolean escapeHTML) {
+ text = text.replace('\n', ' ');
+ // calculate context region:
+ int startContent = fromPos - contextSize;
+ String prefix = "...";
+ String postfix = "...";
+ String markerPrefix = " ";
+ if (startContent < 0) {
+ prefix = "";
+ markerPrefix = "";
+ startContent = 0;
+ }
+ int endContent = toPos + contextSize;
+ final int fileLen = text.length();
+ if (endContent > fileLen) {
+ postfix = "";
+ endContent = fileLen;
+ }
+ // make "^" marker. inefficient but robust implementation:
+ final StringBuilder marker = new StringBuilder();
+ final int totalLen = fileLen + prefix.length();
+ for (int i = 0; i < totalLen; i++) {
+ if (i >= fromPos && i < toPos) {
+ marker.append('^');
+ } else {
+ marker.append(' ');
+ }
+ }
+ // now build context string plus marker:
+ final StringBuilder sb = new StringBuilder();
+ sb.append(prefix);
+ sb.append(text.substring(startContent, endContent));
+ final String markerStr = markerPrefix
+ + marker.substring(startContent, endContent);
+ sb.append(postfix);
+ final int startMark = markerStr.indexOf('^');
+ final int endMark = markerStr.lastIndexOf('^');
+ String result = sb.toString();
+ if (escapeHTML) {
+ result = StringTools.escapeHTML(result.substring(0, startMark))
+ + markerStart
+ + StringTools.escapeHTML(result.substring(startMark, endMark + 1))
+ + markerEnd + StringTools.escapeHTML(result.substring(endMark + 1));
+ } else {
+ result = result.substring(0, startMark) + markerStart
+ + result.substring(startMark, endMark + 1) + markerEnd
+ + result.substring(endMark + 1);
+ }
+ return result;
+ }
+
+ /**
+ * Show a file chooser dialog and return the file selected by the user or
+ * <code>null</code>.
+ */
+ static File openFileDialog(final Frame frame, final FileFilter fileFilter) {
+ final JFileChooser jfc = new JFileChooser();
+ jfc.setFileFilter(fileFilter);
+ jfc.showOpenDialog(frame);
+ final File file = jfc.getSelectedFile();
+ if (file == null) {
+ return null;
+ }
+ return file;
+ }
+
+ /**
+ * Show the exception (with stacktrace) in a dialog and print it to STDERR.
+ */
+ static void showError(final Exception e) {
+ final String msg = de.danielnaber.languagetool.tools.Tools
+ .getFullStackTrace(e);
+ JOptionPane
+ .showMessageDialog(null, msg, "Error", JOptionPane.ERROR_MESSAGE);
+ e.printStackTrace();
+ }
+
+ /**
+ * Show the exception (message without stacktrace) in a dialog and print it to
+ * STDERR.
+ */
+ static void showErrorMessage(final Exception e) {
+ final String msg = e.getMessage();
+ JOptionPane
+ .showMessageDialog(null, msg, "Error", JOptionPane.ERROR_MESSAGE);
+ e.printStackTrace();
+ }
+
+}