/**
* Copyright 1999-2009 The Pegadi Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pegadi.artis;
// UI imports
import com.kitfox.svg.app.beans.SVGIcon;
import org.pegadi.artis.text.LocalEditorKit;
import org.pegadi.artis.text.PersonInText;
import org.pegadi.artis.text.PersonInfo;
import org.pegadi.artis.text.SourceDBPersonResolver;
import org.pegadi.model.LoginContext;
import org.pegadi.util.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/**
* An editor for editing the body of an {@link org.pegadi.model.Article Article}.
* This is usually the main part of the article.
*
* @author HÃ¥vard Wigtil <havardw at pvv.org>
* @version $Revision$, $Date$
*/
public class TextEditor extends AbstractTextEditor implements ClipboardOwner {
/**
* The document {@link #text} is editing.
*/
protected TextDocument textDoc;
public TextEditor(Element xml) {
this(xml, null);
}
public TextEditor(Element xml, Artis artis) {
super(xml, artis);
}
/**
* Called when the caret is moved or the selection in the document is changed.<p>
* Remember that the dot is always the position of the cursor, while mark is
* the other end of the selection. Dragging the cursor from 2 to 5 will
* give dot=5 and mark=2.
*
* @param e The event that triggered this method.
*/
protected void caretMoved(CaretEvent e) {
log.debug("CaretMoved, canEdit: {}", artis.canEditArticle());
if (!cursorChange) {
dot = e.getDot();
mark = e.getMark();
String name = getParagraphStyle(dot);
if (name != null) {
styleChange = false;
styleCombo.setSelectedItem(name);
styleChange = true;
}
updateCharacterButtons();
updateEditActions();
}
}
/**
* Sets the element to edit.
*
* @param xml The new element for the editor to use.
*/
public void setXML(Element xml) {
xml.normalize();
Document doc = xml.getOwnerDocument();
String nodeName = xml.getNodeName();
String docName = doc.getDocumentElement().getTagName();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
factory.setIgnoringElementContentWhitespace(false);
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
log.error("Parser configuration exception", pce);
}
String schemaLocation = doc.getDocumentElement().getAttribute("xsi:noNamespaceSchemaLocation");
try {
schema = builder.parse(schemaLocation).getDocumentElement();
} catch (SAXException se) {
log.error("couldn't parse text", se);
} catch (java.io.IOException ioe) {
// If fetching schema location failed, we try with filename only as a last resort.
schemaLocation = doc.getDocumentElement().getAttribute("xsi:noNamespaceSchemaLocation").substring(schemaLocation.lastIndexOf('/') + 1, schemaLocation.length());
InputStream stream = getClass().getClassLoader().getResourceAsStream(schemaLocation);
log.info("io-exc: Trying once more without 'http://': (" + schemaLocation + ")");
try {
schema = builder.parse(stream).getDocumentElement();
} catch (SAXException se) {
log.error("couldn't parse text the second time. Giving up.", se);
return;
} catch (java.io.IOException ioe2) {
log.error("io-exc: Last try failed", ioe2);
JOptionPane.showMessageDialog(this, textStr.getString("schemafetch_failed"),
"", JOptionPane.ERROR_MESSAGE);
return;
}
}
Element schemaRoot = XMLUtil.getSchemaElement(docName, schema);
Element schemaStart = XMLUtil.getSchemaReference(nodeName, schemaRoot);
Hashtable allowed = createElementList(schemaStart);
StyleContext styles = loadStyles(allowed);
TextDocument tmpDoc = new TextDocument(xml, styles, xml.getOwnerDocument().getDoctype());
text.setStyledDocument(tmpDoc);
textDoc = tmpDoc;
textDoc.addEasterListener(new EasterListener() {
public void easterEventHappened() {
fireEaster();
}
});
mElement = xml;
text.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
caretMoved(e);
fireCaretUpdated(e);
}
});
textDoc.addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
fireTextChanged();
}
public void removeUpdate(DocumentEvent e) {
fireTextChanged();
}
public void changedUpdate(DocumentEvent e) {
}
});
loadParagraphStyles(styleCombo, styles);
}
public AbstractTextDocument getTextDoc() {
return textDoc;
}
public void setTextDoc(AbstractTextDocument textDoc) {
this.textDoc = (TextDocument) textDoc;
}
}