/*
* WPCleaner: A tool to help on Wikipedia maintenance tasks.
* Copyright (C) 2013 Nicolas Vervelle
*
* See README.txt file for licensing information.
*/
package org.wikipediacleaner.gui.swing.action;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.TextAction;
import org.wikipediacleaner.api.data.LinkReplacement;
import org.wikipediacleaner.api.data.Page;
import org.wikipediacleaner.gui.swing.basic.Utilities;
import org.wikipediacleaner.gui.swing.component.MWPaneFormatter;
import org.wikipediacleaner.i18n.GT;
import org.wikipediacleaner.utils.Configuration;
import org.wikipediacleaner.utils.ConfigurationValueBoolean;
/**
* An action listener for replacing internal links.
*/
@SuppressWarnings("serial")
public class ReplaceLinkAction extends TextAction {
private final String oldTitle;
private final String newTitle;
private final String text;
private final Element element;
private final JTextPane textPane;
private final boolean fullReplacement;
public ReplaceLinkAction(boolean fullReplacement) {
this(null, null, null, null, null, fullReplacement);
}
public ReplaceLinkAction(
String oldTitle,
String newTitle,
String text,
Element element,
JTextPane textPane,
boolean fullReplacement) {
super("ReplaceLink");
this.oldTitle = oldTitle;
this.newTitle = newTitle;
this.text = text;
this.element = element;
this.textPane = textPane;
this.fullReplacement = fullReplacement;
}
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
JTextPane localTextPane = textPane;
if (localTextPane == null) {
JTextComponent textComponent = getTextComponent(e);
if (textComponent instanceof JTextPane) {
localTextPane = (JTextPane) textComponent;
}
}
Element localElement = element;
if ((localTextPane != null) && (localElement == null)) {
localElement = localTextPane.getStyledDocument().getCharacterElement(
localTextPane.getSelectionStart());
}
String localText = text;
if ((localElement != null) && (localText == null)) {
Object attrText = localElement.getAttributes().getAttribute(MWPaneFormatter.ATTRIBUTE_TEXT);
if (attrText instanceof String) {
localText = (String) attrText;
}
}
String localOldTitle = oldTitle;
if ((localElement != null) && (localOldTitle == null)) {
Object attrPage = localElement.getAttributes().getAttribute(MWPaneFormatter.ATTRIBUTE_PAGE);
if (attrPage instanceof Page) {
localOldTitle = ((Page) attrPage).getTitle();
}
}
String localNewTitle = newTitle;
if ((localOldTitle != null) && (localNewTitle == null)) {
localNewTitle = LinkReplacement.getLastReplacement(localOldTitle);
}
if (fullReplacement) {
fullyReplace(localOldTitle, localNewTitle, localText, localElement, localTextPane);
} else {
replace(localOldTitle, localNewTitle, localText, localElement, localTextPane);
}
}
/**
* Replace link and displayed text.
*/
private void fullyReplace(
String localOldTitle,
String localNewTitle,
String localText,
Element localElement,
JTextPane localTextPane) {
if ((localElement != null) &&
(localTextPane != null) &&
(localNewTitle != null) &&
(localNewTitle.length() > 0)) {
localTextPane.setCaretPosition(MWPaneFormatter.getUUIDStartOffset(localTextPane, localElement));
localTextPane.moveCaretPosition(MWPaneFormatter.getUUIDEndOffet(localTextPane, localElement));
String newText = null;
if ((localText != null) &&
(localText.length() > 0) &&
(localNewTitle.length() > 0) &&
(localText.charAt(0) != localNewTitle.charAt(0)) &&
(Character.toUpperCase(localText.charAt(0)) == Character.toUpperCase(localNewTitle.charAt(0)))) {
newText = "[[" + localText.charAt(0) + localNewTitle.substring(1) + "]]";
} else {
newText = "[[" + localNewTitle + "]]";
}
localTextPane.replaceSelection(newText);
LinkReplacement.addLastReplacement(localOldTitle, localNewTitle);
}
}
/**
* Replace link (but keep displayed text).
*/
private void replace(
String localOldTitle,
String localNewTitle,
String localText,
Element localElement,
JTextPane localTextPane) {
if ((localElement == null) ||
(localTextPane == null) ||
(localNewTitle == null) || (localNewTitle.length() == 0) ||
(localText == null) || (localText.length() == 0)) {
return;
}
// Initialize
final int startOffset = MWPaneFormatter.getUUIDStartOffset(localTextPane, localElement);
final int endOffset = MWPaneFormatter.getUUIDEndOffet(localTextPane, localElement);
String newText = null;
int offsetBefore = 0;
int offsetAfter = 0;
boolean firstCharEqual = (Character.toUpperCase(localNewTitle.charAt(0)) == Character.toUpperCase(localText.charAt(0)));
String title2 = localNewTitle.substring(1);
String text2 = localText.substring(1);
String originalNewTitle = localNewTitle;
if (firstCharEqual && (localNewTitle.charAt(0) != localText.charAt(0))) {
localNewTitle = "" + localText.charAt(0) + title2;
}
// Check for equality between title and text
if (firstCharEqual && title2.equals(text2)) {
newText = "[[" + localText + "]]";
}
String originalNewText = newText;
// Check for possible extension of the title to the right
if ((newText == null) && firstCharEqual && title2.startsWith(text2)) {
try {
String textAfter = localNewTitle.substring(localText.length());
if (textAfter.equals(localTextPane.getText(localElement.getEndOffset(), textAfter.length()))) {
newText = "[[" + localText.charAt(0) + title2 + "]]";
offsetAfter = textAfter.length();
}
} catch (BadLocationException e2) {
// Nothing to be done
}
}
// Check for possible extension of the title to the left (and possibly to the right)
int position;
if ((newText == null) && ((position = localNewTitle.indexOf(localText)) > 0)) {
try {
String textBefore = localNewTitle.substring(0, position);
String currentText = localTextPane.getText(startOffset - position, position);
if ((Character.toUpperCase(textBefore.charAt(0)) == Character.toUpperCase(currentText.charAt(0))) &&
textBefore.substring(1).equals(currentText.substring(1))) {
if (position + localText.length() < localNewTitle.length()) {
// Check right
String textAfter = localNewTitle.substring(position + localText.length());
String currentText2 = localTextPane.getText(endOffset, localNewTitle.length() - position - localText.length());
if (textAfter.equals(currentText2)) {
newText = "[[" + currentText.charAt(0) + localNewTitle.substring(1) + "]]";
offsetBefore = position;
offsetAfter = currentText2.length();
}
} else {
newText = "[[" + currentText.charAt(0) + localNewTitle.substring(1) + "]]";
offsetBefore = position;
}
}
} catch (BadLocationException e2) {
// Nothing to be done
}
}
// Check with parenthesis removed
Configuration config = Configuration.getConfiguration();
if (config.getBoolean(
null,
ConfigurationValueBoolean.SHORT_NOTATION)) {
String titleRTrimmed = localNewTitle.replaceAll("\\s*\\(.*\\)\\s*$", "");
if ((newText == null) && firstCharEqual && titleRTrimmed.substring(1).equals(text2)) {
newText = "[[" + localText.charAt(0) + title2 + "|]]";
}
}
// Default replacement
if (originalNewText == null) {
originalNewText = "[[" + localNewTitle + "|" + localText + "]]";
}
if (newText == null) {
newText = "[[" + localNewTitle + "|" + localText + "]]";
}
// Ask user if there is a possible extension of the title
if ((offsetBefore != 0) || (offsetAfter != 0)) {
int answer = Utilities.displayYesNoWarning(
textPane.getRootPane(),
GT._("The link can be extended to include text before or after the current link.\n" +
"Would you like to extend the link to \"{0}\"?", newText));
if (answer != JOptionPane.YES_OPTION) {
offsetBefore = 0;
offsetAfter = 0;
newText = originalNewText;
}
}
// Replace
try {
String textAttr = localText;
if ((offsetBefore != 0) || (offsetAfter != 0)) {
textAttr =
localTextPane.getText(startOffset - offsetBefore, offsetBefore) +
localText +
localTextPane.getText(endOffset, offsetAfter);
}
localTextPane.getDocument().remove(startOffset - offsetBefore, endOffset + offsetAfter - startOffset + offsetBefore);
localTextPane.getDocument().insertString(startOffset - offsetBefore, newText, localElement.getAttributes());
if ((offsetBefore != 0) || (offsetAfter != 0)) {
SimpleAttributeSet attr = new SimpleAttributeSet();
attr.addAttribute(MWPaneFormatter.ATTRIBUTE_TEXT, textAttr);
localTextPane.getStyledDocument().setCharacterAttributes(
startOffset - offsetBefore, newText.length(), attr, false);
}
localTextPane.setCaretPosition(startOffset - offsetBefore);
localTextPane.moveCaretPosition(startOffset - offsetBefore + newText.length());
LinkReplacement.addLastReplacement(localOldTitle, originalNewTitle);
} catch (BadLocationException e1) {
// Nothing to be done
}
}
}