/* ****************************************************************************** * * Copyright 2008-2010 Hans Dijkema * * JRichTextEditor 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 3 of * the License, or (at your option) any later version. * * JRichTextEditor 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 JRichTextEditor. If not, see <http://www.gnu.org/licenses/>. * * ******************************************************************************/ package nl.dykema.jxmlnote.styles; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import java.util.Vector; import java.util.Map.Entry; import java.util.prefs.Preferences; import javax.swing.text.StyleContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import nl.dykema.jxmlnote.exceptions.BadStyleException; import nl.dykema.jxmlnote.internationalization.DefaultXMLNoteTranslator; import nl.dykema.jxmlnote.internationalization.XMLNoteTranslator; import nl.dykema.jxmlnote.utils.WeakSet; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; public class XMLNoteStyles { private interface JXMLNotePreferences { public String get(String key,String defaultValue); public void put(String key,String value); } private Hashtable<String,XMLNoteParStyle> _styles; private Vector<String> _keys; private WeakSet<XMLNoteStylesChangedListener> _listeners; private XMLNoteTranslator _translator; private String _contextName; public void addStyleChangedListener(XMLNoteStylesChangedListener l) { _listeners.add(l); } public void removeStyleChangedListener(XMLNoteStylesChangedListener l) { _listeners.remove(l); } public void informStylesChanged() { Iterator<XMLNoteStylesChangedListener> it=_listeners.iterator(); while (it.hasNext()) { XMLNoteStylesChangedListener l=it.next(); if (l!=null) { l.stylesChanged(); } } } public void styleChanged(XMLNoteParStyle p) { informStylesChanged(); } public void resetTo(XMLNoteStyles from) { Iterator<Entry<String,XMLNoteParStyle>> it=from.iterator(); _styles.clear(); while (it.hasNext()) { Entry<String,XMLNoteParStyle> e=it.next(); XMLNoteParStyle p=e.getValue().copy(); p.setContainer(this); _styles.put(e.getKey(), p); } informStylesChanged(); } public String toXML() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance (); DocumentBuilder db; try { db = dbf.newDocumentBuilder (); org.w3c.dom.Document doc = db.newDocument (); org.w3c.dom.Element root = doc.createElement ("xmlnotestyles"); Writer out = new StringWriter(); doc.appendChild (root); root.setAttribute("version", "2010.1"); org.w3c.dom.Element styles=doc.createElement("styles"); root.appendChild(styles); Iterator<Entry<String,XMLNoteParStyle>> it=this.iterator(); while (it.hasNext()) { Entry<String,XMLNoteParStyle> e=it.next(); org.w3c.dom.Element style=doc.createElement("style"); style.setAttribute("id",e.getKey()); style.setTextContent(e.getValue().toString()); styles.appendChild(style); } //Serialize DOM OutputFormat format = new OutputFormat (doc); // as a String XMLSerializer serial = new XMLSerializer (out,format); try { serial.serialize(doc); } catch (IOException e) { e.printStackTrace(); } String xml=out.toString(); return xml; } catch (ParserConfigurationException e1) { e1.printStackTrace(); } return null; } private synchronized void toPrefs(JXMLNotePreferences prefs) { Iterator<String> it=_styles.keySet().iterator(); while (it.hasNext()) { String key=it.next(); prefs.put(key, _styles.get(key).toString()); } } public synchronized void toPrefs(final Preferences prefs) { toPrefs(new JXMLNotePreferences() { public String get(String key, String defaultValue) { return prefs.get(key, defaultValue); } public void put(String key, String value) { prefs.put(key, value); } }); } /** * Returns an iterator over all entries in JXMLNoteStyles. * @return */ public Iterator<Entry<String,XMLNoteParStyle>> iterator() { Set<Entry<String,XMLNoteParStyle>> s=_styles.entrySet(); Vector<Entry<String,XMLNoteParStyle>> v=new Vector<Entry<String,XMLNoteParStyle>>(); Iterator<Entry<String,XMLNoteParStyle>> it=s.iterator(); while(it.hasNext()) { v.add(it.next()); } return v.iterator(); } /** * Returns all keys of the JXMLNoteParStyle styles in this styles, sorted alphabetically on key (or styleId). * @return */ public Vector<String> getStyleKeys() { Vector<String> v=new Vector<String>(); Enumeration<String> en=_styles.keys(); while(en.hasMoreElements()) { v.add(en.nextElement()); } Collections.sort(v); _keys=v; return v; } public int getNumberOfStyles() { if (_keys==null) { getStyleKeys(); } return _keys.size(); } public String getStyleName(int i) { if (_keys==null) { getStyleKeys(); } return _styles.get(_keys.get(i)).name(); } public XMLNoteParStyle getStyle(int i) { if (_keys==null) { getStyleKeys(); } return _styles.get(_keys.get(i)); } /** * Returns the default style for paragraphs * @return * @throws BadStyleException */ public XMLNoteParStyle getDefaultStyle() throws BadStyleException { int i=getDefaultStyleIndex(); if (i==-1) { throw new BadStyleException("No default style in XMLNoteStyles"); } return getStyle(i); } /** * Returns the index for the default style or -1 if there is none. * * @return */ public int getDefaultStyleIndex() { int i,n; for(i=0,n=getNumberOfStyles();i<n && !getStyle(i).isDefault();i++); if (i==n) { return -1; } else { return i; } } /** * Returns all JXMLNoteParStyles as a CSS String. * @return */ public String asCSS(XMLNoteStyleIdConverter cvt) { Enumeration<XMLNoteParStyle> en=_styles.elements(); StringBuffer buf=new StringBuffer(); while (en.hasMoreElements()) { buf.append(en.nextElement().asCSS(cvt)); buf.append("\n"); } return buf.toString(); } /** * Zooms all styles with the given factor. * @param factor */ public void zoom(double factor) { Vector<String> keys=getStyleKeys(); Iterator<String> it=keys.iterator(); while(it.hasNext()) { String key=it.next(); XMLNoteParStyle p=_styles.get(key); p.zoom(factor); } } /** * Returns the JXMLNoteParStyle with the given key; null, if key doesn't exist. * @param key * @return */ public XMLNoteParStyle parStyle(String key) { return _styles.get(key); } /** * Adds a JXMLNoteParStyle with the given key to the styles. * @param key * @param s */ public void addParStyle(String key,XMLNoteParStyle s) throws StyleContainedException { XMLNoteStyles q=s.getContainer(); if (q!=null && q!=this) { String form=_translator.translate("The given paragraph style with id '%s' is already part of another style container"); throw new StyleContainedException(String.format(form,s.id())); } _styles.put(key,s); _keys=null; informStylesChanged(); } /** * Removes the JXMLNoteParStyle with the given key from the styles. * @param key */ public void removeParStyle(String key) { XMLNoteParStyle p=_styles.get(key); if (p!=null) { p.setContainer(null); _styles.remove(key); _keys=null; } informStylesChanged(); } private void initContextName() { _contextName=Integer.toHexString(this.hashCode()); } /** * Creates the default styles for a JXMLNote viewer (the styles used in the JXMLNoteDocument). */ public XMLNoteStyles() { initContextName(); init(new JXMLNotePreferences() { public String get(String key, String defaultValue) { return defaultValue; } public void put(String key, String value) { } }); } /** * Creates the default styles for a JXMLNote viewer (the styles used in the XMLNoteDocument), * read from the Preferences. * @param prefs */ public XMLNoteStyles(final Preferences prefs) { initContextName(); init(new JXMLNotePreferences() { public String get(String key, String defaultValue) { return prefs.get(key, defaultValue); } public void put(String key, String value) { prefs.put(key, value); } }); } /** * Returns the context name for this XMLNoteStyles. All XMLNoteDocuments associated with * this XMLNoteStyles use this context and will therefore change their paragraph styles * on changes in this container. * * @return The context name of this XMLNoteStyles container */ public String stylesContextName() { return _contextName; } /** * Returns the associated style context for all XMLNoteStyles. For internal use only. * @return */ public StyleContext getStyleContext() { return XMLNoteParStyle.getStyleContext(); } public XMLNoteParStyle paragraphStyle() { return this.parStyle("par"); } public XMLNoteParStyle lineStyle() { return this.parStyle("line"); } public XMLNoteParStyle h1Style() { return this.parStyle("h1"); } public XMLNoteParStyle h2Style() { return this.parStyle("h2"); } public XMLNoteParStyle h3Style() { return this.parStyle("h3"); } public XMLNoteParStyle h4Style() { return this.parStyle("h4"); } private void init(JXMLNotePreferences prefs) { _translator=new DefaultXMLNoteTranslator(); _listeners=new WeakSet<XMLNoteStylesChangedListener>(); _styles=new Hashtable<String,XMLNoteParStyle>(); _keys=null; _styles.put("par", new XMLNoteParStyle(this, prefs.get( "par", "id=par!nm=Paragraph!font=Arial!pt=10!bottom=10!top=0!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!default=1!extracss=" ) ) ); _styles.put("line", new XMLNoteParStyle(this, prefs.get( "line", "id=line!nm=Paragraph (Linestyle)!font=Arial!pt=10!bottom=0!top=0!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!default=0!extracss=" ) ) ); _styles.put("h1",new XMLNoteParStyle(this, prefs.get( "h1", "id=h1!nm=Header 1!font=Arial!pt=18!bottom=12!top=10!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!keepwithnext=1!extracss=" ) ) ); _styles.put("h2",new XMLNoteParStyle(this, prefs.get( "h2", "id=h2!nm=Header 2!font=Arial!pt=16!bottom=10!top=6!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!keepwithnext=1!extracss=" ) ) ); _styles.put("h3",new XMLNoteParStyle(this, prefs.get( "h3", "id=h3!nm=Header 3!font=Arial!pt=14!bottom=10!top=6!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!keepwithnext=1!extracss=" ) ) ); _styles.put("h4",new XMLNoteParStyle(this, prefs.get( "h4", "id=h4!nm=Header 4!font=Arial!pt=12!bottom=10!top=6!bold=0!underl=0!it=0!color=#000000!bgcolor=#ffffff!keepwithnext=1!extracss=" ) ) ); } }