/* Copyright (C) 2003-2011 JabRef contributors. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package net.sf.jabref.oo; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.Property; import com.sun.star.text.*; import com.sun.star.uno.UnoRuntime; import com.sun.star.frame.XDesktop; import net.sf.jabref.BibtexDatabase; import net.sf.jabref.BibtexEntry; import net.sf.jabref.Globals; import net.sf.jabref.BibtexFields; import net.sf.jabref.export.layout.Layout; import javax.swing.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.List; import java.util.Iterator; /** * Utility methods for processing OO Writer documents. */ public class OOUtil { static Pattern htmlTag = Pattern.compile("</?[a-z]+>"); static OOPreFormatter postformatter = new OOPreFormatter(); /** * Insert a reference, formatted using a Layout, at the position of a given cursor. * @param text The text to insert in. * @param cursor The cursor giving the insert location. * @param layout The Layout to format the reference with. * @param parStyle The name of the paragraph style to use. * @param entry The entry to insert. * @param database The database the entry belongs to. * @param uniquefier Uniqiefier letter, if any, to append to the entry's year. * @throws Exception */ public static void insertFullReferenceAtCurrentLocation(XText text, XTextCursor cursor, Layout layout, String parStyle, BibtexEntry entry, BibtexDatabase database, String uniquefier) throws UndefinedParagraphFormatException, Exception { final String UNIQUEFIER_FIELD = "uniq"; // Backup the value of the uniq field, just in case the entry already has it: String oldUniqVal = (String)entry.getField(UNIQUEFIER_FIELD); // Set the uniq field with the supplied uniquefier: entry.setField(UNIQUEFIER_FIELD, uniquefier); // Do the layout for this entry: String lText = layout.doLayout(entry, database); // Afterwards, reset the old value: entry.setField(UNIQUEFIER_FIELD, oldUniqVal); // Insert the formatted text: insertOOFormattedTextAtCurrentLocation(text, cursor, lText, parStyle); } /** * Insert a text with formatting indicated by HTML-like tags, into a text at * the position given by a cursor. * @param text The text to insert in. * @param cursor The cursor giving the insert location. * @param lText The marked-up text to insert. * @param parStyle The name of the paragraph style to use. * @throws Exception */ public static void insertOOFormattedTextAtCurrentLocation(XText text, XTextCursor cursor, String lText, String parStyle) throws UndefinedParagraphFormatException, Exception { XParagraphCursor parCursor = (XParagraphCursor)UnoRuntime.queryInterface( XParagraphCursor.class, cursor); XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, parCursor); try { props.setPropertyValue("ParaStyleName", parStyle); } catch (com.sun.star.lang.IllegalArgumentException ex) { throw new UndefinedParagraphFormatException(parStyle); } // We need to extract formatting. Use a simple regexp search iteration: int piv = 0; int italic = 0, bold = 0, sup = 0, sub = 0, mono = 0, smallCaps = 0; //insertTextAtCurrentLocation(text, cursor, "_", // false, false, false, false, false, false); //cursor.goLeft((short)1, true); Matcher m = htmlTag.matcher(lText); while (m.find()) { String ss = lText.substring(piv, m.start()); if (ss.length() > 0) { insertTextAtCurrentLocation(text, cursor, ss, (bold % 2) > 0, (italic % 2) > 0, mono > 0, smallCaps > 0, sup > 0, sub > 0); } String tag = m.group(); // Handle tags: if (tag.equals("<b>")) bold++; else if (tag.equals("</b>")) bold--; else if (tag.equals("<i>") || tag.equals("<em>")) italic++; else if (tag.equals("</i>") || tag.equals("</em>")) italic--; else if (tag.equals("</monospace>")) mono = 0; else if (tag.equals("<monospace>")) mono = 1; else if (tag.equals("</smallcaps>")) smallCaps = 0; else if (tag.equals("<smallcaps>")) smallCaps = 1; else if (tag.equals("</sup>")) sup = 0; else if (tag.equals("<sup>")) sup = 1; else if (tag.equals("</sub>")) sub = 0; else if (tag.equals("<sub>")) sub = 1; piv = m.end(); } if (piv < lText.length()) insertTextAtCurrentLocation(text, cursor,lText.substring(piv), (bold % 2) > 0, (italic % 2) > 0, mono > 0, smallCaps > 0, sup > 0, sub > 0); cursor.collapseToEnd(); } public static void insertParagraphBreak(XText text, XTextCursor cursor) throws Exception { text.insertControlCharacter(cursor, ControlCharacter.PARAGRAPH_BREAK, true); cursor.collapseToEnd(); } public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string, boolean bold, boolean italic, boolean monospace, boolean smallCaps, boolean superscript, boolean subscript) throws Exception { text.insertString(cursor, string, true); // Access the property set of the cursor, and set the currently selected text // (which is the string we just inserted) to be bold XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, cursor); if (bold) xCursorProps.setPropertyValue("CharWeight", new Float(com.sun.star.awt.FontWeight.BOLD)); else xCursorProps.setPropertyValue("CharWeight", new Float(com.sun.star.awt.FontWeight.NORMAL)); if (italic) xCursorProps.setPropertyValue("CharPosture", com.sun.star.awt.FontSlant.ITALIC); else xCursorProps.setPropertyValue("CharPosture", com.sun.star.awt.FontSlant.NONE); if (smallCaps) { xCursorProps.setPropertyValue("CharCaseMap", com.sun.star.style.CaseMap.SMALLCAPS); } else { xCursorProps.setPropertyValue("CharCaseMap", com.sun.star.style.CaseMap.NONE); } // TODO: the <monospace> tag doesn't work /* if (monospace) { xCursorProps.setPropertyValue("CharFontPitch", com.sun.star.awt.FontPitch.FIXED); } else { xCursorProps.setPropertyValue("CharFontPitch", com.sun.star.awt.FontPitch.VARIABLE); } */ if (subscript) { xCursorProps.setPropertyValue("CharEscapement", (byte)-101); xCursorProps.setPropertyValue("CharEscapementHeight", (byte)58); } else if (superscript) { xCursorProps.setPropertyValue("CharEscapement", (byte)101); xCursorProps.setPropertyValue("CharEscapementHeight", (byte)58); } else { xCursorProps.setPropertyValue("CharEscapement", (byte)0); xCursorProps.setPropertyValue("CharEscapementHeight", (byte)100); } cursor.collapseToEnd(); } public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string, String parStyle) throws Exception { text.insertString(cursor, string, true); XParagraphCursor parCursor = (XParagraphCursor)UnoRuntime.queryInterface( XParagraphCursor.class, cursor); // Access the property set of the cursor, and set the currently selected text // (which is the string we just inserted) to be bold XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, parCursor); try { props.setPropertyValue("ParaStyleName", parStyle); } catch (com.sun.star.lang.IllegalArgumentException ex) { throw new UndefinedParagraphFormatException(parStyle); } cursor.collapseToEnd(); } public static Object getProperty(Object o, String property) throws Exception { XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, o); return props.getPropertyValue(property); } public static void listProperties(Object o) throws Exception { XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, o); Property[] pr = props.getPropertySetInfo().getProperties(); for (int i = 0; i < pr.length; i++) { Property property1 = pr[i]; System.out.println(property1.Name+" : "+props.getPropertyValue(property1.Name)); } } public static XTextDocument selectComponent(JFrame parent, XDesktop xDesktop, List<XTextDocument> list) throws Exception { String[] values = new String[list.size()]; int ii=0; for (Iterator<XTextDocument> iterator = list.iterator(); iterator.hasNext();) { XTextDocument doc = iterator.next(); values[ii++] = String.valueOf(getProperty(doc.getCurrentController().getFrame(), "Title")); } JList sel = new JList(values); sel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); sel.setSelectedIndex(0); int ans = JOptionPane.showConfirmDialog(parent, new JScrollPane(sel), Globals.lang("Select document"), JOptionPane.OK_CANCEL_OPTION); if (ans == JOptionPane.OK_OPTION) { return list.get(sel.getSelectedIndex()); } else return null; } /** * Make a cloned BibtexEntry and do the necessary preprocessing for use by the plugin. * If the running JabRef version doesn't support post-processing in Layout, this * preprocessing includes running the OOPreFormatter formatter for all fields except the * BibTeX key. * @param entry the original entry * @return the cloned and processed entry */ public static BibtexEntry createAdaptedEntry(BibtexEntry entry) { if (entry == null) return null; BibtexEntry e = (BibtexEntry)entry.clone(); for (String field : e.getAllFields()) { if (field.equals(BibtexFields.KEY_FIELD)) continue; String value = e.getField(field); // If the running JabRef version doesn't support post-processing in Layout, // preprocess fields instead: if (!OpenOfficePanel.postLayoutSupported && (value != null)) e.setField(field, postformatter.format(value)); } return e; } }