Extended config API + More config ui work

git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@37 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
henrikjust 2009-09-24 18:41:50 +00:00
parent a0384669cc
commit 52694ed9c9
11 changed files with 391 additions and 158 deletions

View file

@ -0,0 +1,101 @@
/************************************************************************
*
* Config.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2009 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2009-09-23)
*
*/
package writer2latex.api;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/** A complex option is a set of named keys, each pointing to a set of named attributes
*/
public class ComplexOption {
private Map<String,Map<String,String>> options = new HashMap<String,Map<String,String>>();
/** Clear the contents of the set
*
*/
public void clear() {
options.clear();
}
/** Remove an option from the set, if it exists
*
* @param sName the name of the key to remove
*/
public void remove(String sName) {
if (options.containsKey(sName)) {
options.remove(sName);
}
}
/** Define a key. If the key already exists, the old value will be replaced
*
* @param sName the name of the key. The name must be non-empty, otherwise the request will be ignored.
* @param attributes
*/
public void put(String sName, Map<String,String> attributes) {
if (sName!=null && sName.length()>0) {
options.put(sName, attributes);
}
}
/** Get the value belonging to a key
*
* @param sName the name of the key
* @return the attributes, or null if the option doesn't exist
*/
public Map<String,String> get(String sName) {
return options.get(sName);
}
/** Copy all values from another <code>ComplexOption</code>
* (overwrites existing values)
* @param co another instance of <code>ComplexOption</code>
*/
public void copyAll(ComplexOption co) {
for (String sName : co.keySet()) {
Map<String,String> attr = co.get(sName);
Map<String,String> newAttr = new HashMap<String,String>();
for (String sAttrName : attr.keySet()) {
newAttr.put(sAttrName, attr.get(sAttrName));
}
options.put(sName, newAttr);
}
}
/** Get the names of all options that are currently defined by this complex option
*
* @return all names as a <code>Set</code>
*/
public Set<String> keySet() {
return options.keySet();
}
}

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2009-09-20)
* Version 1.2 (2009-09-22)
*
*/
@ -31,8 +31,6 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.IllegalArgumentException;
import java.util.Map;
import java.util.Set;
/** This is an interface for configuration of a {@link Converter}.
* A configuration always supports simple name/value options.
@ -97,27 +95,12 @@ public interface Config {
*/
public String getOption(String sName);
/** Set a complex option
*
* @param sGroup the group to which this option belongs
* @param sName the name of this option
* @param attributes the attributes defining the values of this option
*/
public void setComplexOption(String sGroup, String sName, Map<String,String> attributes);
/** Get a complex option
*
* @param sGroup the group to which this option belongs
* @param sName the name of this option
* @return the attributes defining the values of this option
* @param sName the name of the complex option
* @return
*/
public Map<String,String> getComplexOption(String sGroup, String sName);
public ComplexOption getComplexOption(String sName);
/** Get the collection of complex options in a specific groups
*
* @param sGroup the name of the group of options
* @return the names of the currently defined options in this group
*/
public Set<String> getComplexOptions(String sGroup);
}

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2008 by Henrik Just
* Copyright: 2002-2009 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.0 (2008-11-22)
* Version 1.2 (2009-09-24)
*
*/
@ -35,6 +35,9 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
@ -42,6 +45,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.DOMImplementation;
import writer2latex.api.ComplexOption;
import writer2latex.xmerge.NewDOMDocument;
public abstract class ConfigBase implements writer2latex.api.Config {
@ -50,9 +54,11 @@ public abstract class ConfigBase implements writer2latex.api.Config {
protected abstract String getDefaultConfigPath();
protected Option[] options;
protected Map<String,ComplexOption> optionGroups;
public ConfigBase() {
options = new Option[getOptionCount()];
optionGroups = new HashMap<String,ComplexOption>();
}
public void setOption(String sName,String sValue) {
@ -76,6 +82,16 @@ public abstract class ConfigBase implements writer2latex.api.Config {
}
return null;
}
public ComplexOption getComplexOption(String sGroup) {
return optionGroups.get(sGroup);
}
// The subclass may use this method to define option groups
protected ComplexOption addComplexOption(String sGroup) {
optionGroups.put(sGroup, new ComplexOption());
return optionGroups.get(sGroup);
}
public void readDefaultConfig(String sName) throws IllegalArgumentException {
InputStream is = this.getClass().getResourceAsStream(getDefaultConfigPath()+sName);

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.0 (2009-03-02)
* Version 1.2 (2009-09-24)
*
*/
@ -29,11 +29,9 @@ package writer2latex.latex;
import org.w3c.dom.Element;
import java.io.IOException;
import java.util.LinkedList;
import writer2latex.api.Config;
import writer2latex.api.ConverterFactory;
//import writer2latex.api.ConverterResult;
import writer2latex.base.ConverterBase;
import writer2latex.latex.i18n.ClassicI18n;
import writer2latex.latex.i18n.I18n;
@ -226,10 +224,9 @@ public final class ConverterPalette extends ConverterBase {
mathmlCv.appendDeclarations(packages,declarations);
// Add custom preamble
LinkedList<String> customPreamble = config.getCustomPreamble();
int nCPLen = customPreamble.size();
for (int i=0; i<nCPLen; i++) {
declarations.append( customPreamble.get(i) ).nl();
String sCustomPreamble = config.getCustomPreamble();
if (sCustomPreamble.length()>0) {
declarations.append(sCustomPreamble).nl();
}
// Set \title, \author and \date (for \maketitle)

View file

@ -20,14 +20,12 @@
*
* All Rights Reserved.
*
* Version 1.2 (2009-09-20)
* Version 1.2 (2009-09-24)
*
*/
package writer2latex.latex;
import java.util.LinkedList;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Map;
@ -37,13 +35,13 @@ import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import writer2latex.api.ComplexOption;
import writer2latex.base.BooleanOption;
import writer2latex.base.IntegerOption;
import writer2latex.base.Option;
import writer2latex.latex.util.HeadingMap;
import writer2latex.latex.i18n.ClassicI18n;
import writer2latex.latex.i18n.ReplacementTrie;
import writer2latex.latex.i18n.ReplacementTrieNode;
import writer2latex.latex.util.StyleMap;
import writer2latex.util.Misc;
@ -51,13 +49,29 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
protected int getOptionCount() { return 63; }
protected String getDefaultConfigPath() { return "/writer2latex/latex/config/"; }
// Override setOption to be backwards compatible
public void setOption(String sName,String sValue) {
// this option has been renamed:
if (sName.equals("keep_image_size")) { sName = "original_image_size"; }
super.setOption(sName, sValue);
// Override getter and setter methods for options in order to:
// - Treat the custom preamble like a regular option, even though the xml representation is different
// - Be backwards compatible (renamed option)
@Override public void setOption(String sName,String sValue) {
if (sName.equals("custom-preamble")) {
sCustomPreamble = sValue;
}
else {
// this option has been renamed:
if (sName.equals("keep_image_size")) { sName = "original_image_size"; }
super.setOption(sName, sValue);
}
}
@Override public String getOption(String sName) {
if (sName.equals("custom-preamble")) {
return sCustomPreamble;
}
else {
return super.getOption(sName);
}
}
// Backend
public static final int GENERIC = 0;
public static final int DVIPS = 1;
@ -155,7 +169,7 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
private static final int SAVE_IMAGES_IN_SUBDIR = 61;
private static final int DEBUG = 62;
protected LinkedList<String> customPreamble = new LinkedList<String>();
protected String sCustomPreamble = "";
protected StyleMap par = new StyleMap();
protected StyleMap parBlock = new StyleMap();
protected StyleMap text = new StyleMap();
@ -163,8 +177,9 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
protected StyleMap listItem = new StyleMap();
protected StyleMap textAttr = new StyleMap();
protected HeadingMap headingMap = new HeadingMap(5);
protected Hashtable<String, String> mathSymbols = new Hashtable<String, String>();
protected ReplacementTrie stringReplace = new ReplacementTrie();
private ComplexOption stringReplace;
private ComplexOption mathSymbols;
public LaTeXConfig() {
super();
@ -288,51 +303,46 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
headingMap.setLevelData(3,"subsubsection",3);
headingMap.setLevelData(4,"paragraph",4);
headingMap.setLevelData(5,"subparagraph",5);
// Complex options
stringReplace=addComplexOption("string-replace");
// Standard string replace:
// Fix french spacing; replace nonbreaking space
// right before em-dash, !, ?, : and ; (babel handles this)
stringReplace.put("\u00A0\u2014"," \u2014",ClassicI18n.readFontencs("any"));
stringReplace.put("\u00A0!"," !",ClassicI18n.readFontencs("any"));
stringReplace.put("\u00A0?"," ?",ClassicI18n.readFontencs("any"));
stringReplace.put("\u00A0:"," :",ClassicI18n.readFontencs("any"));
stringReplace.put("\u00A0;"," ;",ClassicI18n.readFontencs("any"));
Map<String,String> attr = new HashMap<String,String>();
attr.put("fontenc", "any");
attr.put("latex-code", " \u2014");
stringReplace.put("\u00A0\u2014",attr);
attr = new HashMap<String,String>();
attr.put("fontenc", "any");
attr.put("latex-code", " !");
stringReplace.put("\u00A0!",attr);
attr = new HashMap<String,String>();
attr.put("fontenc", "any");
attr.put("latex-code", " ?");
stringReplace.put("\u00A0?",attr);
attr = new HashMap<String,String>();
attr.put("fontenc", "any");
attr.put("latex-code", " :");
stringReplace.put("\u00A0:",attr);
attr = new HashMap<String,String>();
attr.put("fontenc", "any");
attr.put("latex-code", " ;");
stringReplace.put("\u00A0;",attr);
// Right after opening guillemet and right before closing guillemet:
// Here we must *keep* the non-breaking space
// TODO: Use \og and \fg if the document contains french...
//stringReplace.put("\u00AB\u00A0","\u00AB ",I18n.readFontencs("any"));
//stringReplace.put("\u00A0\u00BB"," \u00BB",I18n.readFontencs("any"));
mathSymbols = addComplexOption("math-symbol-map");
}
public void setComplexOption(String sGroup, String sName, Map<String,String> attributes) {
if ("string-replace".equals(sGroup)) {
String sLaTeXCode = attributes.get("latex-code");
String sFontencs = attributes.get("fontencs");
if (sLaTeXCode!=null) {
int nFontencs = ClassicI18n.readFontencs(sFontencs!=null && sFontencs.length()>0 ? sFontencs : "any");
stringReplace.put(sName,sLaTeXCode,nFontencs);
}
}
}
public Map<String,String> getComplexOption(String sGroup, String sName) {
if ("string-replace".equals(sGroup)) {
ReplacementTrieNode node = stringReplace.get(sName);
if (node!=null) {
HashMap<String,String> attributes = new HashMap<String,String>();
attributes.put("latex-code", node.getLaTeXCode());
attributes.put("fontencs", "(todo)");
}
}
return null;
}
public Set<String> getComplexOptions(String sGroup) {
if ("string-replace".equals(sGroup)) {
return stringReplace.getInputStrings();
}
return new java.util.HashSet<String>();
}
protected void readInner(Element elm) {
if (elm.getTagName().equals("style-map")) {
String sName = elm.getAttribute("name");
@ -368,25 +378,29 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
readHeadingMap(elm);
}
else if (elm.getTagName().equals("string-replace")) {
// TODO: ConfigBase should handle this
String sInput = elm.getAttribute("input");
String sLaTeXCode = elm.getAttribute("latex-code");
String sFontencs = elm.getAttribute("fontencs");
int nFontencs = ClassicI18n.readFontencs(sFontencs.length()>0 ? sFontencs : "any");
stringReplace.put(sInput,sLaTeXCode,nFontencs);
Map<String,String> attributes = new HashMap<String,String>();
attributes.put("latex-code", elm.getAttribute("latex-code"));
attributes.put("fontenc", elm.getAttribute("fontenc"));
stringReplace.put(sInput,attributes);
}
else if (elm.getTagName().equals("custom-preamble")) {
StringBuffer buf = new StringBuffer();
Node child = elm.getFirstChild();
while (child!=null) {
if (child.getNodeType()==Node.TEXT_NODE) {
customPreamble.add(child.getNodeValue());
buf.append(child.getNodeValue());
}
child = child.getNextSibling();
}
sCustomPreamble = buf.toString();
}
else if (elm.getTagName().equals("math-symbol-map")) {
String sName = elm.getAttribute("name");
String sLatex = elm.getAttribute("latex");
mathSymbols.put(sName,sLatex);
Map<String,String> attr = new HashMap<String,String>();
attr.put("latex", elm.getAttribute("latex"));
mathSymbols.put(sName, attr);
}
}
@ -410,10 +424,8 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
protected void writeInner(Document dom) {
// Write math symbol map
Enumeration<String> msEnum = mathSymbols.keys();
while (msEnum.hasMoreElements()) {
String sName = msEnum.nextElement();
String sLatex = mathSymbols.get(sName);
for (String sName : mathSymbols.keySet()) {
String sLatex = mathSymbols.get(sName).get("latex");
Element msNode = dom.createElement("math-symbol-map");
msNode.setAttribute("name",sName);
msNode.setAttribute("latex",sLatex);
@ -438,20 +450,20 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
hmNode.appendChild(hlmNode);
}
Set<String> inputStrings = stringReplace.getInputStrings();
// TODO: ConfigBase should handle this
Set<String> inputStrings = stringReplace.keySet();
for (String sInput : inputStrings) {
System.out.println("Writing input "+sInput);
ReplacementTrieNode node = stringReplace.get(sInput);
Map<String,String> attributes = stringReplace.get(sInput);
Element srNode = dom.createElement("string-replace");
srNode.setAttribute("input",sInput);
srNode.setAttribute("latex-code",node.getLaTeXCode());
srNode.setAttribute("fontenc","(todo)");
//srNode.setAttribute("fontenc",ClassicI18n.writeFontencs(node.getFontencs()));
srNode.setAttribute("latex-code",attributes.get("latex-code"));
srNode.setAttribute("fontenc",attributes.get("fontenc"));
dom.getDocumentElement().appendChild(srNode);
}
writeContent(dom,customPreamble,"custom-preamble");
Element cp = dom.createElement("custom-preamble");
cp.appendChild(dom.createTextNode( sCustomPreamble));
dom.getDocumentElement().appendChild(cp);
}
private void writeStyleMap(Document dom, StyleMap sm, String sFamily) {
@ -475,20 +487,23 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
dom.getDocumentElement().appendChild(smNode);
}
}
private void writeContent(Document dom, LinkedList<String> list, String sElement) {
Element node = dom.createElement(sElement);
int nLen = list.size();
for (int i=0; i<nLen; i++) {
node.appendChild( dom.createTextNode( list.get(i) ) );
}
dom.getDocumentElement().appendChild(node);
}
// Convenience accessor methods
// String replace
public ReplacementTrie getStringReplace() { return stringReplace; }
// Return current string replace as a trie
public ReplacementTrie getStringReplace() {
ReplacementTrie trie = new ReplacementTrie();
for (String sInput : stringReplace.keySet()) {
Map<String,String> attributes = stringReplace.get(sInput);
String sLaTeXCode = attributes.get("latex-code");
String sFontenc = attributes.get("fontenc");
trie.put(sInput,sLaTeXCode!=null ? sLaTeXCode : "",
ClassicI18n.readFontencs(sFontenc!=null ? sFontenc : "any"));
}
return trie;
}
public String getCustomPreamble() { return sCustomPreamble; }
// Common options
public boolean debug() { return ((BooleanOption) options[DEBUG]).getValue(); }
@ -574,7 +589,14 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
public boolean splitToplevelSections() { return ((BooleanOption) options[SPLIT_TOPLEVEL_SECTIONS]).getValue(); }
public boolean saveImagesInSubdir() { return ((BooleanOption) options[SAVE_IMAGES_IN_SUBDIR]).getValue(); }
public Hashtable<String, String> getMathSymbols() { return mathSymbols; }
public Map<String, String> getMathSymbols() {
Map<String,String> map = new HashMap<String,String>();
for (String sName : mathSymbols.keySet()) {
String sLatex = mathSymbols.get(sName).get("latex");
map.put(sName, sLatex);
}
return map;
}
public StyleMap getParStyleMap() { return par; }
public StyleMap getParBlockStyleMap() { return parBlock; }
@ -583,7 +605,6 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase {
public StyleMap getListItemStyleMap() { return listItem; }
public StyleMap getTextAttributeStyleMap() { return textAttr; }
public HeadingMap getHeadingMap() { return headingMap; }
public LinkedList<String> getCustomPreamble() { return customPreamble; }
}

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2009-09-20)
* Version 1.2 (2009-09-21)
*
*/
@ -50,10 +50,12 @@ public final class MathmlConverter extends ConverterHelper {
private StarMathConverter smc;
private boolean bContainsFormulas = false;
private boolean bAddParAfterDisplay = false;
public MathmlConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
super(ofr,config,palette);
smc = new StarMathConverter(palette.getI18n(),config);
bAddParAfterDisplay = config.formatting()>=LaTeXConfig.CONVERT_MOST;
}
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
@ -121,12 +123,14 @@ public final class MathmlConverter extends ConverterHelper {
ldp.nl()
.append(convert(null,theEquation)).nl()
.append("\\end{equation}").nl();
if (bAddParAfterDisplay) { ldp.nl(); }
}
else {
// Unnumbered equation
ldp.append("\\begin{equation*}").nl()
.append(convert(null,theEquation)).nl()
.append("\\end{equation*}").nl();
if (bAddParAfterDisplay) { ldp.nl(); }
}
return true;
}

View file

@ -18,14 +18,14 @@
*
* Copyright: 2002-2009 by Henrik Just
*
* Version 1.0 (2009-04-08)
* Version 1.2 (2009-09-24)
*
* All Rights Reserved.
*/
package writer2latex.latex;
import java.util.Hashtable;
import java.util.Map;
import writer2latex.util.*;
import writer2latex.latex.i18n.ClassicI18n;
import writer2latex.latex.i18n.I18n;
@ -698,7 +698,7 @@ public final class StarMathConverter implements writer2latex.api.StarMathConvert
private SmTokenTable keywords=new SmTokenTable(SmTokenTable.keywords);
private SmTokenTable symbols=new SmTokenTable(SmTokenTable.symbols);
private LaTeXConfig config;
private Hashtable<String, String> configSymbols;
private Map<String, String> configSymbols;
private boolean bUseColor;
private SmToken curToken=new SmToken(); // contains the data of the current token
private SimpleInputBuffer buffer; // contains the starmath formula

View file

@ -20,15 +20,13 @@
*
* All Rights Reserved.
*
* Version 1.2 (2009-09-20)
* Version 1.2 (2009-09-22)
*
*/
package writer2latex.xhtml;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -155,21 +153,6 @@ public class XhtmlConfig extends writer2latex.base.ConfigBase {
options[DOCUMENT_ICON] = new Option("document_icon","");
}
// Dummy implementation of complex options
public void setComplexOption(String sGroup, String sName, Map<String,String> attributes) {
// do nothing
}
public Map<String,String> getComplexOption(String sGroup, String sName) {
// no options are defined, return null in all cases
return null;
}
public Set<String> getComplexOptions(String sGroup) {
// Always an empty set
return new java.util.HashSet<String>();
}
protected void readInner(Element elm) {
if (elm.getTagName().equals("xhtml-style-map")) {
String sName = elm.getAttribute("name");