org.languagetool.gui.ConfigurationDialog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of languagetool-gui-commons Show documentation
Show all versions of languagetool-gui-commons Show documentation
GUI classes for both stand-alone and LibreOffice/OpenOffice extension use
/* 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 org.languagetool.gui;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.languagetool.JLanguageTool;
import org.languagetool.Language;
import org.languagetool.Languages;
import org.languagetool.languagemodel.LuceneLanguageModel;
import org.languagetool.rules.Rule;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.*;
import java.util.List;
/**
* 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 static final String ACTION_COMMAND_OK = "OK";
private static final String ACTION_COMMAND_CANCEL = "CANCEL";
private static final int MAX_PORT = 65536;
private final ResourceBundle messages;
private final Configuration original;
private final Configuration config;
private final Frame owner;
private final boolean insideOffice;
private JDialog dialog;
private JCheckBox serverCheckbox;
private JTextField serverPortField;
private JTree configTree[] = new JTree[2];
private JCheckBox serverSettingsCheckbox;
private final List extraPanels = new ArrayList<>();
private final List configurableRules = new ArrayList<>();
public ConfigurationDialog(Frame owner, boolean insideOffice, Configuration config) {
this.owner = owner;
this.insideOffice = insideOffice;
this.original = config;
this.config = original.copy(original);
messages = JLanguageTool.getMessageBundle();
}
/**
* Add extra JPanel to this dialog.
*
* If the panel implements {@see SavablePanel}, this dialog will call
* {@link SavablePanel#save} after the user clicks OK.
*
* @param panel the JPanel to be added to this dialog
* @since 3.4
*/
void addExtraPanel(JPanel panel) {
extraPanels.add(panel);
}
private DefaultMutableTreeNode createTree(List rules, boolean isStyle) {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Rules");
String lastRuleId = null;
Map parents = new TreeMap<>();
for (Rule rule : rules) {
if((isStyle && (rule.getLocQualityIssueType().toString().equalsIgnoreCase("STYLE")
|| rule.getLocQualityIssueType().toString().equalsIgnoreCase("REGISTER")
|| rule.getCategory().getId().toString().equals("STYLE")
|| rule.getCategory().getId().toString().equals("TYPOGRAPHY"))) ||
(!isStyle && !rule.getLocQualityIssueType().toString().equalsIgnoreCase("STYLE")
&& !rule.getLocQualityIssueType().toString().equalsIgnoreCase("REGISTER")
&& !rule.getCategory().getId().toString().equals("STYLE")
&& !rule.getCategory().getId().toString().equals("TYPOGRAPHY"))) {
if(rule.hasConfigurableValue()) {
configurableRules.add(rule);
} else {
if (!parents.containsKey(rule.getCategory().getName())) {
boolean enabled = true;
if (config.getDisabledCategoryNames() != null && config.getDisabledCategoryNames().contains(rule.getCategory().getName())) {
enabled = false;
}
if(rule.getCategory().isDefaultOff()) {
enabled = false;
}
DefaultMutableTreeNode categoryNode = new CategoryNode(rule.getCategory(), enabled);
root.add(categoryNode);
parents.put(rule.getCategory().getName(), categoryNode);
}
if (!rule.getId().equals(lastRuleId)) {
RuleNode ruleNode = new RuleNode(rule, getEnabledState(rule));
parents.get(rule.getCategory().getName()).add(ruleNode);
}
lastRuleId = rule.getId();
}
}
}
return root;
}
private boolean getEnabledState(Rule rule) {
boolean ret = true;
if (config.getDisabledRuleIds().contains(rule.getId())) {
ret = false;
}
if (config.getDisabledCategoryNames().contains(rule.getCategory().getName())) {
ret = false;
}
if ((rule.isDefaultOff() || rule.getCategory().isDefaultOff()) && !config.getEnabledRuleIds().contains(rule.getId())) {
ret = false;
}
if (rule.isDefaultOff() && rule.getCategory().isDefaultOff()
&& config.getEnabledRuleIds().contains(rule.getId())) {
config.getDisabledCategoryNames().remove(rule.getCategory().getName());
}
return ret;
}
public void show(List rules) {
if (original != null) {
config.restoreState(original);
}
dialog = new JDialog(owner, true);
dialog.setTitle(messages.getString("guiConfigWindowTitle"));
// close dialog when user presses Escape key:
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(@SuppressWarnings("unused") ActionEvent actionEvent) {
dialog.setVisible(false);
}
};
JRootPane rootPane = dialog.getRootPane();
rootPane.registerKeyboardAction(actionListener, stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
configurableRules.clear();
JPanel checkBoxPanel = new JPanel();
checkBoxPanel.setLayout(new GridBagLayout());
GridBagConstraints cons = new GridBagConstraints();
cons.anchor = GridBagConstraints.NORTHWEST;
cons.gridx = 0;
cons.weightx = 1.0;
cons.weighty = 1.0;
cons.fill = GridBagConstraints.HORIZONTAL;
Collections.sort(rules, new CategoryComparator());
DefaultMutableTreeNode rootNode = createTree(rules, false); // grammar options
configTree[0] = new JTree(getTreeModel(rootNode));
Language lang = config.getLanguage();
if (lang == null) {
lang = Languages.getLanguageForLocale(Locale.getDefault());
}
configTree[0].applyComponentOrientation(ComponentOrientation.getOrientation(lang.getLocale()));
configTree[0].setRootVisible(false);
configTree[0].setEditable(false);
configTree[0].setCellRenderer(new CheckBoxTreeCellRenderer());
TreeListener.install(configTree[0]);
checkBoxPanel.add(configTree[0], cons);
configTree[0].addMouseListener(getMouseAdapter());
JPanel checkBoxPanel1 = new JPanel();
checkBoxPanel1.setLayout(new GridBagLayout());
cons = new GridBagConstraints();
cons.anchor = GridBagConstraints.NORTHWEST;
cons.gridx = 0;
cons.weightx = 1.0;
cons.weighty = 1.0;
cons.fill = GridBagConstraints.HORIZONTAL;
Collections.sort(rules, new CategoryComparator());
rootNode = createTree(rules, true); // Style options
configTree[1] = new JTree(getTreeModel(rootNode));
configTree[1].applyComponentOrientation(ComponentOrientation.getOrientation(lang.getLocale()));
configTree[1].setRootVisible(false);
configTree[1].setEditable(false);
configTree[1].setCellRenderer(new CheckBoxTreeCellRenderer());
TreeListener.install(configTree[1]);
checkBoxPanel1.add(configTree[1], cons);
configTree[1].addMouseListener(getMouseAdapter());
JPanel portPanel = new JPanel();
portPanel.setLayout(new GridBagLayout());
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 (!insideOffice) {
createNonOfficeElements(cons, portPanel);
}
else {
createOfficeElements(cons, portPanel);
}
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridBagLayout());
JButton okButton = new JButton(Tools.getLabel(messages.getString("guiOKButton")));
okButton.setMnemonic(Tools.getMnemonic(messages.getString("guiOKButton")));
okButton.setActionCommand(ACTION_COMMAND_OK);
okButton.addActionListener(this);
JButton cancelButton = new JButton(Tools.getLabel(messages.getString("guiCancelButton")));
cancelButton.setMnemonic(Tools.getMnemonic(messages.getString("guiCancelButton")));
cancelButton.setActionCommand(ACTION_COMMAND_CANCEL);
cancelButton.addActionListener(this);
cons = new GridBagConstraints();
cons.insets = new Insets(0, 4, 0, 0);
buttonPanel.add(okButton, cons);
buttonPanel.add(cancelButton, cons);
JTabbedPane tabpane = new JTabbedPane();
JPanel jPane = new JPanel();
jPane.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 = 0.0f;
cons.fill = GridBagConstraints.NONE;
cons.anchor = GridBagConstraints.NORTHWEST;
cons.gridy++;
cons.anchor = GridBagConstraints.WEST;
jPane.add(getMotherTonguePanel(cons), cons);
cons.gridy++;
cons.anchor = GridBagConstraints.WEST;
jPane.add(getNgramPanel(cons), cons);
cons.gridy++;
cons.anchor = GridBagConstraints.WEST;
jPane.add(getWord2VecPanel(cons), cons);
cons.gridy++;
cons.anchor = GridBagConstraints.WEST;
jPane.add(portPanel, cons);
cons.gridx = 0;
cons.gridy++;
cons.anchor = GridBagConstraints.WEST;
jPane.add(getUnderlineColorPanel(rules), cons);
cons.fill = GridBagConstraints.HORIZONTAL;
cons.anchor = GridBagConstraints.WEST;
for(JPanel extra : extraPanels) {
//in case it wasn't in a containment hierarchy when user changed L&F
SwingUtilities.updateComponentTreeUI(extra);
cons.gridy++;
jPane.add(extra, cons);
}
cons.gridy++;
cons.fill = GridBagConstraints.BOTH;
cons.weighty = 1.0f;
jPane.add(new JPanel(), cons);
tabpane.addTab(messages.getString("guiGeneral"), jPane);
jPane = new JPanel();
jPane.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;
jPane.add(new JScrollPane(checkBoxPanel), cons);
cons.weightx = 0.0f;
cons.weighty = 0.0f;
cons.gridx = 0;
cons.gridy++;
cons.fill = GridBagConstraints.NONE;
cons.anchor = GridBagConstraints.LINE_END;
jPane.add(getTreeButtonPanel(0), cons);
tabpane.addTab(messages.getString("guiGrammarRules"), jPane);
jPane = new JPanel();
jPane.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;
jPane.add(new JScrollPane(checkBoxPanel1), cons);
cons.weightx = 0.0f;
cons.weighty = 0.0f;
cons.gridx = 0;
cons.gridy++;
cons.fill = GridBagConstraints.NONE;
cons.anchor = GridBagConstraints.LINE_END;
jPane.add(getTreeButtonPanel(1), cons);
cons.gridx = 0;
cons.gridy++;
cons.weightx = 5.0f;
cons.weighty = 5.0f;
cons.fill = GridBagConstraints.BOTH;
cons.anchor = GridBagConstraints.WEST;
jPane.add(new JScrollPane(getSpecialRuleValuePanel()), cons);
tabpane.addTab(messages.getString("guiStyleRules"), jPane);
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;
cons.anchor = GridBagConstraints.NORTHWEST;
contentPane.add(tabpane, cons);
cons.weightx = 0.0f;
cons.weighty = 0.0f;
cons.gridy++;
cons.fill = GridBagConstraints.NONE;
cons.anchor = GridBagConstraints.EAST;
contentPane.add(buttonPanel, cons);
dialog.pack();
// center on screen:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = dialog.getSize();
dialog.setLocation(screenSize.width / 2 - frameSize.width / 2,
screenSize.height / 2 - frameSize.height / 2);
dialog.setLocationByPlatform(true);
for(JPanel extra : this.extraPanels) {
if(extra instanceof SavablePanel) {
((SavablePanel) extra).componentShowing();
}
}
dialog.setVisible(true);
}
private void createNonOfficeElements(GridBagConstraints cons, JPanel portPanel) {
serverCheckbox = new JCheckBox(Tools.getLabel(messages.getString("guiRunOnPort")));
serverCheckbox.setMnemonic(Tools.getMnemonic(messages.getString("guiRunOnPort")));
serverCheckbox.setSelected(config.getRunServer());
portPanel.add(serverCheckbox, cons);
serverCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) {
serverPortField.setEnabled(serverCheckbox.isSelected());
serverSettingsCheckbox.setEnabled(serverCheckbox.isSelected());
}
});
serverCheckbox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
config.setRunServer(serverCheckbox.isSelected());
}
});
serverPortField = new JTextField(Integer.toString(config.getServerPort()));
serverPortField.setEnabled(serverCheckbox.isSelected());
serverSettingsCheckbox = new JCheckBox(Tools.getLabel(messages.getString("useGUIConfig")));
serverPortField.setMinimumSize(new Dimension(100, 25)); // without this the box is just a few pixels small, but why?
cons.gridx = 1;
portPanel.add(serverPortField, cons);
serverPortField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
try {
int serverPort = Integer.parseInt(serverPortField.getText());
if (serverPort > -1 && serverPort < MAX_PORT) {
serverPortField.setForeground(null);
config.setServerPort(serverPort);
} else {
serverPortField.setForeground(Color.RED);
}
} catch (NumberFormatException ex) {
serverPortField.setForeground(Color.RED);
}
}
});
cons.gridx = 0;
cons.gridy = 10;
serverSettingsCheckbox.setMnemonic(Tools.getMnemonic(messages.getString("useGUIConfig")));
serverSettingsCheckbox.setSelected(config.getUseGUIConfig());
serverSettingsCheckbox.setEnabled(config.getRunServer());
serverSettingsCheckbox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
config.setUseGUIConfig(serverSettingsCheckbox.isSelected());
}
});
portPanel.add(serverSettingsCheckbox, cons);
}
private void createOfficeElements(GridBagConstraints cons, JPanel portPanel) {
int numParaCheck = config.getNumParasToCheck();
JRadioButton[] radioButtons = new JRadioButton[3];
ButtonGroup numParaGroup = new ButtonGroup();
radioButtons[0] = new JRadioButton(Tools.getLabel(messages.getString("guiCheckOnlyParagraph")));
radioButtons[0].setActionCommand("ParagraphCheck");
radioButtons[1] = new JRadioButton(Tools.getLabel(messages.getString("guiCheckFullText")));
radioButtons[1].setActionCommand("FullTextCheck");
radioButtons[2] = new JRadioButton(Tools.getLabel(messages.getString("guiCheckNumParagraphs")));
radioButtons[2].setActionCommand("NParagraphCheck");
radioButtons[2].setSelected(true);
JTextField numParaField = new JTextField(Integer.toString(5), 2);
numParaField.setEnabled(radioButtons[2].isSelected());
numParaField.setMinimumSize(new Dimension(30, 25));
for (int i = 0; i < 3; i++) {
numParaGroup.add(radioButtons[i]);
}
if (numParaCheck == 0) {
radioButtons[0].setSelected(true);
numParaField.setEnabled(false);
} else if (numParaCheck < 0) {
radioButtons[1].setSelected(true);
numParaField.setEnabled(false);
} else {
radioButtons[2].setSelected(true);
numParaField.setText(Integer.toString(numParaCheck));
numParaField.setEnabled(true);
}
radioButtons[0].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
numParaField.setEnabled(false);
config.setNumParasToCheck(0);
}
});
radioButtons[1].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
numParaField.setEnabled(false);
config.setNumParasToCheck(-1);
}
});
radioButtons[2].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int numParaCheck = Integer.parseInt(numParaField.getText());
if (numParaCheck < 1) numParaCheck = 1;
else if (numParaCheck > 99) numParaCheck = 99;
config.setNumParasToCheck(numParaCheck);
numParaField.setForeground(Color.BLACK);
numParaField.setText(Integer.toString(numParaCheck));
numParaField.setEnabled(true);
}
});
numParaField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
try {
int numParaCheck = Integer.parseInt(numParaField.getText());
if (numParaCheck > 0 && numParaCheck < 99) {
numParaField.setForeground(Color.BLACK);
config.setNumParasToCheck(numParaCheck);
} else {
numParaField.setForeground(Color.RED);
}
} catch (NumberFormatException ex) {
numParaField.setForeground(Color.RED);
}
}
});
for (int i = 0; i < 3; i++) {
portPanel.add(radioButtons[i], cons);
if (i < 2) cons.gridy++;
}
cons.gridx = 1;
portPanel.add(numParaField, cons);
JCheckBox resetCheckbox = new JCheckBox(Tools.getLabel(messages.getString("guiDoResetCheck")));
resetCheckbox.setSelected(config.isResetCheck());
resetCheckbox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
config.setDoResetCheck(resetCheckbox.isSelected());
}
});
cons.gridx = 0;
JLabel dummyLabel = new JLabel(" ");
cons.gridy++;
portPanel.add(dummyLabel, cons);
cons.gridy++;
portPanel.add(resetCheckbox, cons);
}
@NotNull
private DefaultTreeModel getTreeModel(DefaultMutableTreeNode rootNode) {
DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new TreeModelListener() {
@Override
public void treeNodesChanged(TreeModelEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getTreePath().getLastPathComponent();
int index = e.getChildIndices()[0];
node = (DefaultMutableTreeNode) node.getChildAt(index);
if (node instanceof RuleNode) {
RuleNode o = (RuleNode) node;
if (o.getRule().isDefaultOff() || o.getRule().getCategory().isDefaultOff()) {
if (o.isEnabled()) {
config.getEnabledRuleIds().add(o.getRule().getId());
config.getDisabledRuleIds().remove(o.getRule().getId());
} else {
config.getEnabledRuleIds().remove(o.getRule().getId());
config.getDisabledRuleIds().add(o.getRule().getId());
}
} else {
if (o.isEnabled()) {
config.getDisabledRuleIds().remove(o.getRule().getId());
} else {
config.getDisabledRuleIds().add(o.getRule().getId());
}
}
}
if (node instanceof CategoryNode) {
CategoryNode o = (CategoryNode) node;
if (o.isEnabled()) {
config.getDisabledCategoryNames().remove(o.getCategory().getName());
} else {
config.getDisabledCategoryNames().add(o.getCategory().getName());
}
}
}
@Override
public void treeNodesInserted(TreeModelEvent e) {}
@Override
public void treeNodesRemoved(TreeModelEvent e) {}
@Override
public void treeStructureChanged(TreeModelEvent e) {}
});
return treeModel;
}
@NotNull
private MouseAdapter getMouseAdapter() {
return new MouseAdapter() {
private void handlePopupEvent(MouseEvent e) {
JTree tree = (JTree) e.getSource();
TreePath path = tree.getPathForLocation(e.getX(), e.getY());
if (path == null) {
return;
}
DefaultMutableTreeNode node
= (DefaultMutableTreeNode) path.getLastPathComponent();
TreePath[] paths = tree.getSelectionPaths();
boolean isSelected = false;
if (paths != null) {
for (TreePath selectionPath : paths) {
if (selectionPath.equals(path)) {
isSelected = true;
}
}
}
if (!isSelected) {
tree.setSelectionPath(path);
}
if (node.isLeaf()) {
JPopupMenu popup = new JPopupMenu();
JMenuItem aboutRuleMenuItem = new JMenuItem(messages.getString("guiAboutRuleMenu"));
aboutRuleMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
RuleNode node = (RuleNode) tree.getSelectionPath().getLastPathComponent();
Rule rule = node.getRule();
Language lang = config.getLanguage();
if(lang == null) {
lang = Languages.getLanguageForLocale(Locale.getDefault());
}
Tools.showRuleInfoDialog(tree, messages.getString("guiAboutRuleTitle"),
rule.getDescription(), rule, messages,
lang.getShortCodeWithCountryAndVariant());
}
});
popup.add(aboutRuleMenuItem);
popup.show(tree, e.getX(), e.getY());
}
}
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
handlePopupEvent(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
handlePopupEvent(e);
}
}
};
}
@NotNull
private JPanel getTreeButtonPanel(int num) {
GridBagConstraints cons;
JPanel treeButtonPanel = new JPanel();
cons = new GridBagConstraints();
cons.gridx = 0;
cons.gridy = 0;
JButton expandAllButton = new JButton(messages.getString("guiExpandAll"));
treeButtonPanel.add(expandAllButton, cons);
expandAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TreeNode root = (TreeNode) configTree[num].getModel().getRoot();
TreePath parent = new TreePath(root);
for (Enumeration cat = root.children(); cat.hasMoreElements();) {
TreeNode n = (TreeNode) cat.nextElement();
TreePath child = parent.pathByAddingChild(n);
configTree[num].expandPath(child);
}
}
});
cons.gridx = 1;
cons.gridy = 0;
JButton collapseAllButton = new JButton(messages.getString("guiCollapseAll"));
treeButtonPanel.add(collapseAllButton, cons);
collapseAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TreeNode root = (TreeNode) configTree[num].getModel().getRoot();
TreePath parent = new TreePath(root);
for (Enumeration categ = root.children(); categ.hasMoreElements();) {
TreeNode n = (TreeNode) categ.nextElement();
TreePath child = parent.pathByAddingChild(n);
configTree[num].collapsePath(child);
}
}
});
return treeButtonPanel;
}
@NotNull
private JPanel getMotherTonguePanel(GridBagConstraints cons) {
JPanel motherTonguePanel = new JPanel();
motherTonguePanel.add(new JLabel(messages.getString("guiMotherTongue")), cons);
JComboBox motherTongueBox = new JComboBox<>(getPossibleMotherTongues());
if (config.getMotherTongue() != null) {
motherTongueBox.setSelectedItem(config.getMotherTongue().getTranslatedName(messages));
}
motherTongueBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
Language motherTongue;
if (motherTongueBox.getSelectedItem() instanceof String) {
motherTongue = getLanguageForLocalizedName(motherTongueBox.getSelectedItem().toString());
} else {
motherTongue = (Language) motherTongueBox.getSelectedItem();
}
config.setMotherTongue(motherTongue);
}
}
});
motherTonguePanel.add(motherTongueBox, cons);
return motherTonguePanel;
}
private JPanel getNgramPanel(GridBagConstraints cons) {
JPanel panel = new JPanel();
panel.add(new JLabel(messages.getString("guiNgramDir")), cons);
File dir = config.getNgramDirectory();
int maxDirDisplayLength = 45;
String buttonText = dir != null ? StringUtils.abbreviate(dir.getAbsolutePath(), maxDirDisplayLength) : messages.getString("guiNgramDirSelect");
JButton ngramDirButton = new JButton(buttonText);
ngramDirButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File newDir = Tools.openDirectoryDialog(owner, dir);
if (newDir != null) {
try {
if (config.getLanguage() != null) { // may happen in office context
File checkDir = new File(newDir, config.getLanguage().getShortCode());
LuceneLanguageModel.validateDirectory(checkDir);
}
config.setNgramDirectory(newDir);
ngramDirButton.setText(StringUtils.abbreviate(newDir.getAbsolutePath(), maxDirDisplayLength));
} catch (Exception ex) {
Tools.showErrorMessage(ex);
}
} else {
// not the best UI, but this way user can turn off ngram feature without another checkbox
config.setNgramDirectory(null);
ngramDirButton.setText(StringUtils.abbreviate(messages.getString("guiNgramDirSelect"), maxDirDisplayLength));
}
}
});
panel.add(ngramDirButton, cons);
JButton helpButton = new JButton(messages.getString("guiNgramHelp"));
helpButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Tools.openURL("http://wiki.languagetool.org/finding-errors-using-n-gram-data");
}
});
panel.add(helpButton, cons);
return panel;
}
private JPanel getWord2VecPanel(GridBagConstraints cons) {
JPanel panel = new JPanel();
panel.add(new JLabel(messages.getString("guiWord2VecDir")), cons);
File dir = config.getWord2VecDirectory();
int maxDirDisplayLength = 45;
String buttonText = dir != null ? StringUtils.abbreviate(dir.getAbsolutePath(), maxDirDisplayLength) : messages.getString("guiWord2VecDirSelect");
JButton word2vecDirButton = new JButton(buttonText);
word2vecDirButton.addActionListener(e -> {
File newDir = Tools.openDirectoryDialog(owner, dir);
if (newDir != null) {
try {
config.setWord2VecDirectory(newDir);
word2vecDirButton.setText(StringUtils.abbreviate(newDir.getAbsolutePath(), maxDirDisplayLength));
} catch (Exception ex) {
Tools.showErrorMessage(ex);
}
} else {
// not the best UI, but this way user can turn off word2vec feature without another checkbox
config.setWord2VecDirectory(null);
word2vecDirButton.setText(StringUtils.abbreviate(messages.getString("guiWord2VecDirSelect"), maxDirDisplayLength));
}
});
panel.add(word2vecDirButton, cons);
JButton helpButton = new JButton(messages.getString("guiWord2VecHelp"));
helpButton.addActionListener(e -> {
Tools.openURL("https://github.com/gulp21/languagetool-neural-network");
});
panel.add(helpButton, cons);
return panel;
}
private String[] getPossibleMotherTongues() {
List motherTongues = new ArrayList<>();
motherTongues.add(NO_MOTHER_TONGUE);
for (Language lang : Languages.get()) {
motherTongues.add(lang.getTranslatedName(messages));
}
return motherTongues.toArray(new String[motherTongues.size()]);
}
@Override
public void actionPerformed(ActionEvent e) {
if (ACTION_COMMAND_OK.equals(e.getActionCommand())) {
if (original != null) {
original.restoreState(config);
}
for(JPanel extra : extraPanels) {
if(extra instanceof SavablePanel) {
((SavablePanel) extra).save();
}
}
dialog.setVisible(false);
} else if (ACTION_COMMAND_CANCEL.equals(e.getActionCommand())) {
dialog.setVisible(false);
}
}
/**
* Get the Language object for the given localized language name.
*
* @param languageName e.g. English
or German
(case is significant)
* @return a Language object or null
if the language could not be found
*/
@Nullable
private Language getLanguageForLocalizedName(String languageName) {
for (Language element : Languages.get()) {
if (languageName.equals(element.getTranslatedName(messages))) {
return element;
}
}
return null;
}
static class CategoryComparator implements Comparator {
@Override
public int compare(Rule r1, Rule r2) {
boolean hasCat = r1.getCategory() != null && r2.getCategory() != null;
if (hasCat) {
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());
}
}
/* Panel to set Values for special rules like LongSentenceRule
* @since 4.1
*/
private JPanel getSpecialRuleValuePanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints cons = new GridBagConstraints();
cons.gridx = 0;
cons.gridy = 0;
cons.weightx = 0.0f;
cons.anchor = GridBagConstraints.WEST;
List ruleCheckboxes = new ArrayList();
List ruleLabels = new ArrayList();
List ruleValueFields = new ArrayList();
for(int i = 0; i < configurableRules.size(); i++) {
Rule rule = configurableRules.get(i);
JCheckBox ruleCheckbox = new JCheckBox(rule.getDescription());
ruleCheckboxes.add(ruleCheckbox);
ruleCheckbox.setSelected(getEnabledState(rule));
cons.insets = new Insets(3, 0, 0, 0);
panel.add(ruleCheckbox, cons);
cons.insets = new Insets(0, 24, 0, 0);
cons.gridy++;
JLabel ruleLabel = new JLabel(rule.getConfigureText());
ruleLabels.add(ruleLabel);
ruleLabel.setEnabled(ruleCheckbox.isSelected());
panel.add(ruleLabel, cons);
cons.gridx++;
int value = config.getConfigurableValue(rule.getId());
if(config.getConfigurableValue(rule.getId()) < 0) {
value = rule.getDefaultValue();
}
JTextField ruleValueField = new JTextField(Integer.toString(value), 2);
ruleValueFields.add(ruleValueField);
ruleValueField.setEnabled(ruleCheckbox.isSelected());
ruleValueField.setMinimumSize(new Dimension(35, 25)); // without this the box is just a few pixels small, but why?
panel.add(ruleValueField, cons);
ruleCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) {
ruleValueField.setEnabled(ruleCheckbox.isSelected());
ruleLabel.setEnabled(ruleCheckbox.isSelected());
if (ruleCheckbox.isSelected()) {
config.getEnabledRuleIds().add(rule.getId());
config.getDisabledRuleIds().remove(rule.getId());
} else {
config.getEnabledRuleIds().remove(rule.getId());
config.getDisabledRuleIds().add(rule.getId());
}
}
});
ruleValueField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
try {
int num = Integer.parseInt(ruleValueField.getText());
if (num < rule.getMinConfigurableValue()) {
num = rule.getMinConfigurableValue();
ruleValueField.setForeground(Color.RED);
} else if (num > rule.getMaxConfigurableValue()) {
num = rule.getMaxConfigurableValue();
ruleValueField.setForeground(Color.RED);
} else {
ruleValueField.setForeground(null);
}
config.setConfigurableValue(rule.getId(), num);
} catch (Exception ex) {
ruleValueField.setForeground(Color.RED);
}
}
});
cons.gridx = 0;
cons.gridy++;
}
return panel;
}
/* Panel to choose underline Colors
* @since 4.2
*/
JPanel getUnderlineColorPanel(List rules) {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints cons = new GridBagConstraints();
cons.gridx = 0;
cons.gridy = 0;
cons.weightx = 0.0f;
cons.fill = GridBagConstraints.NONE;
cons.anchor = GridBagConstraints.NORTHWEST;
panel.add(new JLabel(messages.getString("guiUnderlineColor")), cons);
List categories = new ArrayList();
for (Rule rule : rules) {
String category = rule.getCategory().getName();
boolean contain = false;
for(String c : categories) {
if (c.equals(category)) {
contain = true;
break;
}
}
if (!contain) {
categories.add(category);
}
}
JComboBox categoriesBox = new JComboBox<>(categories.toArray(new String[categories.size()]));
JLabel underlineLabel = new JLabel(" \u2588\u2588\u2588 "); // \u2587 is smaller
underlineLabel.setForeground(config.getUnderlineColor(categories.get(0)));
underlineLabel.setBackground(config.getUnderlineColor(categories.get(0)));
categoriesBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
underlineLabel.setForeground(config.getUnderlineColor(categoriesBox.getSelectedItem().toString()));
}
}
});
cons.gridy++;
panel.add(categoriesBox, cons);
cons.gridx++;
panel.add(underlineLabel, cons);
JButton changeButton = new JButton(messages.getString("guiUColorChange"));
changeButton.addActionListener( new ActionListener() {
@Override public void actionPerformed( ActionEvent e ) {
Color oldColor = underlineLabel.getForeground();
Color newColor = JColorChooser.showDialog( null, messages.getString("guiUColorDialogHeader"), oldColor);
if(newColor != null && newColor != oldColor) {
underlineLabel.setForeground(newColor);
config.setUnderlineColor(categoriesBox.getSelectedItem().toString(), newColor);
}
}
});
cons.gridx++;
panel.add(changeButton, cons);
JButton defaultButton = new JButton(messages.getString("guiUColorDefault"));
defaultButton.addActionListener( new ActionListener() {
@Override public void actionPerformed( ActionEvent e ) {
config.setDefaultUnderlineColor(categoriesBox.getSelectedItem().toString());
underlineLabel.setForeground(config.getUnderlineColor(categoriesBox.getSelectedItem().toString()));
}
});
cons.gridx++;
panel.add(defaultButton, cons);
return panel;
}
}