org.languagetool.gui.Tools Maven / Gradle / Ivy
/* 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.languagetool.JLanguageTool;
import org.languagetool.rules.*;
import org.languagetool.rules.patterns.FalseFriendPatternRule;
import org.languagetool.tools.StringTools;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import org.apache.commons.lang3.SystemUtils;
/**
* GUI-related tools.
*
* @author Daniel Naber
*/
public final class Tools {
private Tools() {
// no public constructor
}
/**
* Show a file chooser dialog and return the file selected by the user or
* null
.
*/
static File openFileDialog(Frame frame, FileFilter fileFilter) {
return openFileDialog(frame, fileFilter, null);
}
/**
* Show a file chooser dialog in a specified directory
* @param frame Owner frame
* @param fileFilter The pattern of files to choose from
* @param initialDir The initial directory
* @return the selected file
* @since 2.6
*/
static File openFileDialog(Frame frame, FileFilter fileFilter, File initialDir) {
return openFileDialog(frame, fileFilter, initialDir, JFileChooser.FILES_ONLY);
}
/**
* Show a directory chooser dialog, starting with a specified directory
* @param frame Owner frame
* @param initialDir The initial directory
* @return the selected file
* @since 3.0
*/
static File openDirectoryDialog(Frame frame, File initialDir) {
return openFileDialog(frame, null, initialDir, JFileChooser.DIRECTORIES_ONLY);
}
private static File openFileDialog(Frame frame, FileFilter fileFilter, File initialDir, int mode) {
JFileChooser jfc = new JFileChooser();
jfc.setFileSelectionMode(mode);
jfc.setCurrentDirectory(initialDir);
jfc.setFileFilter(fileFilter);
jfc.showOpenDialog(frame);
return jfc.getSelectedFile();
}
/**
* Show the exception (with stacktrace) in a dialog and print it to STDERR.
*/
static void showError(Exception e) {
String stackTrace = org.languagetool.tools.Tools.getFullStackTrace(e);
String msg = "" + StringTools.escapeHTML(stackTrace);
JOptionPane.showMessageDialog(null, msg, "Error", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
/**
* Show the exception (message without stacktrace) in a dialog and print the
* stacktrace to STDERR.
*/
static void showErrorMessage(Exception e, Component parent) {
String msg = e.getMessage();
JOptionPane.showMessageDialog(parent, msg, "Error", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
/**
* Show the exception (message without stacktrace) in a dialog and print the
* stacktrace to STDERR.
*/
static void showErrorMessage(Exception e) {
showErrorMessage(e, null);
}
/**
* LibO shortens menu items with more than ~100 characters by dropping text in the middle.
* That isn't really sensible, so we shorten the text here in order to preserve the important parts.
*/
public static String shortenComment(String comment) {
int maxCommentLength = 100;
String shortComment = comment;
if (shortComment.length() > maxCommentLength) {
// if there is text in brackets, drop it (beginning at the end)
while (shortComment.lastIndexOf(" [") > 0
&& shortComment.lastIndexOf(']') > shortComment.lastIndexOf(" [")
&& shortComment.length() > maxCommentLength) {
shortComment = shortComment.substring(0, shortComment.lastIndexOf(" [")) + shortComment.substring(shortComment.lastIndexOf(']')+1);
}
while (shortComment.lastIndexOf(" (") > 0
&& shortComment.lastIndexOf(')') > shortComment.lastIndexOf(" (")
&& shortComment.length() > maxCommentLength) {
shortComment = shortComment.substring(0, shortComment.lastIndexOf(" (")) + shortComment.substring(shortComment.lastIndexOf(')')+1);
}
// in case it's still not short enough, shorten at the end
if (shortComment.length() > maxCommentLength) {
shortComment = shortComment.substring(0, maxCommentLength-1) + "…";
}
}
return shortComment;
}
/**
* Returns translation of the UI element without the control character {@code &}. To
* have {@code &} in the UI, use {@code &&}.
*
* @param label Label to convert.
* @return String UI element string without mnemonics.
*/
public static String getLabel(String label) {
return label.replaceAll("&([^&])", "$1").replaceAll("&&", "&");
}
/**
* Returns mnemonic of a UI element.
*
* @param label String Label of the UI element
* @return Mnemonic of the UI element, or {@code \u0000} in case of no mnemonic set.
*/
public static char getMnemonic(String label) {
int mnemonicPos = label.indexOf('&');
while (mnemonicPos != -1 && mnemonicPos == label.indexOf("&&")
&& mnemonicPos < label.length()) {
mnemonicPos = label.indexOf('&', mnemonicPos + 2);
}
if (mnemonicPos == -1 || mnemonicPos == label.length()) {
return '\u0000';
}
return label.charAt(mnemonicPos + 1);
}
/**
* Set dialog location to the center of the screen
*
* @param dialog the dialog which will be centered
* @since 2.6
*/
public static void centerDialog(JDialog dialog) {
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);
}
/**
* @since 3.3
*/
public static void configureFromRules(JLanguageTool lt, Configuration config) {
Set disabledRules = config.getDisabledRuleIds();
if (disabledRules != null) {
for (String ruleId : disabledRules) {
lt.disableRule(ruleId);
}
}
Set disabledCategories = config.getDisabledCategoryNames();
if (disabledCategories != null) {
for (String categoryName : disabledCategories) {
lt.disableCategory(new CategoryId(categoryName));
}
}
if(config.getEnabledRulesOnly()) {
for (Rule rule : lt.getAllRules()) {
lt.disableRule(rule.getId());
}
}
Set enabledRules = config.getEnabledRuleIds();
if (enabledRules != null) {
for (String ruleName : enabledRules) {
lt.enableRule(ruleName);
}
}
lt.setConfigValues(config.getConfigurableValues());
}
public static void addHyperlinkListener(JTextPane pane) {
pane.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
Tools.openURL(e.getURL());
}
}
});
}
/**
* Launches the default browser to display a URL.
*
* @param url the URL to be displayed
* @since 4.1
*/
public static void openURL(String url) {
try {
openURL(new URL(url));
} catch (MalformedURLException ex) {
Tools.showError(ex);
}
}
/**
* Launches the default browser to display a URL.
*
* @param url the URL to be displayed
* @since 4.1
*/
static void openURL(URL url) {
if (Desktop.isDesktopSupported()
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(url.toURI());
} catch (Exception ex) {
Tools.showError(ex);
}
} else if(SystemUtils.IS_OS_LINUX) {
//handle the case where Desktop.browse() is not supported, e.g. kubuntu
//without libgnome
try {
Runtime.getRuntime().exec(new String[] { "xdg-open", url.toString() });
} catch (Exception ex) {
Tools.showError(ex);
}
}
}
static void showRuleInfoDialog(Component parent, String title, String message, Rule rule, URL matchUrl, ResourceBundle messages, String lang) {
int dialogWidth = 320;
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
textPane.setContentType("text/html");
textPane.setBorder(BorderFactory.createEmptyBorder());
textPane.setOpaque(false);
textPane.setBackground(new Color(0, 0, 0, 0));
Tools.addHyperlinkListener(textPane);
textPane.setSize(dialogWidth, Short.MAX_VALUE);
String messageWithBold = message.replaceAll("", "").replaceAll(" ", "");
String exampleSentences = getExampleSentences(rule, messages);
String url = "http://community.languagetool.org/rule/show/" + encodeUrl(rule)
+ "?lang=" + lang + "&ref=standalone-gui";
boolean isExternal = rule.getCategory().getLocation() == Category.Location.EXTERNAL;
String ruleDetailLink = rule instanceof FalseFriendPatternRule || isExternal ?
"" : "" + messages.getString("ruleDetailsLink") +"";
textPane.setText(""
+ messageWithBold + exampleSentences + formatURL(matchUrl)
+ "
"
+ ruleDetailLink
+ "");
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(
new Dimension(dialogWidth, textPane.getPreferredSize().height));
scrollPane.setBorder(BorderFactory.createEmptyBorder());
String cleanTitle = title.replace("", "'").replace(" ", "'");
JOptionPane.showMessageDialog(parent, scrollPane, cleanTitle,
JOptionPane.INFORMATION_MESSAGE);
}
private static String encodeUrl(Rule rule) {
try {
return URLEncoder.encode(rule.getId(), "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static String getExampleSentences(Rule rule, ResourceBundle messages) {
StringBuilder examples = new StringBuilder(200);
List incorrectExamples = rule.getIncorrectExamples();
if (incorrectExamples.size() > 0) {
String incorrectExample = incorrectExamples.iterator().next().getExample();
String sentence = incorrectExample.replace("", "").replace(" ", "");
examples.append("
").append(sentence).append(" x");
}
List correctExamples = rule.getCorrectExamples();
if (correctExamples.size() > 0) {
String correctExample = correctExamples.iterator().next().getExample();
String sentence = correctExample.replace("", "").replace(" ", "");
examples.append("
").append(sentence).append(" ✓");
} else if (incorrectExamples.size() > 0) {
IncorrectExample incorrectExample = incorrectExamples.iterator().next();
List corrections = incorrectExample.getCorrections();
if (!corrections.isEmpty() && !corrections.get(0).isEmpty()) {
String incorrectSentence = incorrectExamples.iterator().next().getExample();
String correctedSentence = incorrectSentence.replaceAll(".*? ",
"" + corrections.get(0) + "");
examples.append("
").append(correctedSentence).append(" ✓");
}
}
if (examples.length() > 0) {
examples.insert(0, "
" + messages.getString("guiExamples"));
}
return examples.toString();
}
private static String formatURL(URL url) {
if (url == null) {
return "";
}
return String.format("
%s",
url.toExternalForm(), StringUtils.abbreviate(url.toString(), 50));
}
}