/** * 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; } }