diff --git a/source/pro/litvinovg/libreoffice/metadata/Document.java b/source/pro/litvinovg/libreoffice/metadata/Document.java index e9c69f8..ce57393 100644 --- a/source/pro/litvinovg/libreoffice/metadata/Document.java +++ b/source/pro/litvinovg/libreoffice/metadata/Document.java @@ -16,12 +16,21 @@ import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.XPropertyContainer; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.XEnumerationAccess; import com.sun.star.document.XDocumentProperties; import com.sun.star.document.XDocumentPropertiesSupplier; import com.sun.star.frame.XDesktop; import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.XComponent; import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XTextRange; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; @@ -40,6 +49,7 @@ public class Document { private XComponent currentDocument; private XDocumentProperties documentProperties; private XDocumentPropertiesSupplier documentPropertiesSupplier; + private XText text = null; public Document(XComponentContext componentContext) { context = componentContext; @@ -48,6 +58,8 @@ public class Document { Object oDesktop = multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", context); xDesktop = UnoRuntime.queryInterface(XDesktop.class, oDesktop); getCurrentDocument(); + getDocumentText(); + updateChapterMetadata(); } catch (Exception e) { System.out.println("xDesktop inaccessible. Can not proceed."); e.printStackTrace(); @@ -56,6 +68,51 @@ public class Document { //logProperties(); } + private void getDocumentText() { + XTextDocument textDocument = UnoRuntime.queryInterface(XTextDocument.class,currentDocument); + text = textDocument.getText(); + } + + private void updateChapterMetadata() { + findAllChapters(); + } + + private void findAllChapters() { + XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, text); + XEnumeration textEnum = enumAccess.createEnumeration(); + while (textEnum.hasMoreElements()) { + try { + XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement()); + if(isSupported(textContent, "com.sun.star.text.TextTable")) { + //TODO: Go over table to check for outline elements + } else + if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) { + Short outlineLevel = null; + XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, textContent); + try { + outlineLevel = (Short) properties.getPropertyValue("OutlineLevel"); + } catch (UnknownPropertyException e) { + System.out.println("Shouldn't be here!"); + e.printStackTrace(); + } + if (outlineLevel != null && outlineLevel > 0) { + XTextRange textRange = textContent.getAnchor(); + String name = textRange.getString(); + System.out.println("Outline element found! " + name); + new OutlineElement(textRange); + //TODO: outline element found. Save outline element name and anchor + } + } + } catch (NoSuchElementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (WrappedTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + private void getCurrentDocument() throws MetadataInaccessableException { currentDocument = xDesktop.getCurrentComponent(); if (currentDocument == null) { @@ -231,6 +288,14 @@ public class Document { } return value; } + + private boolean isSupported(Object object, String service) { + XServiceInfo info = UnoRuntime.queryInterface(XServiceInfo.class, object); + if (info == null) { + return false; + } + return info.supportsService(service); + } } diff --git a/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java b/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java new file mode 100644 index 0000000..d5164b4 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java @@ -0,0 +1,43 @@ +package pro.litvinovg.libreoffice.metadata; + +import static pro.litvinovg.libreoffice.metadata.MetadataElement.METADATA_PREFIX; + +public class MetadataElement { + + public static final String METADATA_START = "## Metadata Editor extension. Outline metadata folllows: "; + public static String METADATA_PREFIX = "##"; + public static String METADATA_END = "## Metadata Editor extension. Outline metadata ends."; + + + + private String name; + private String value; + + public MetadataElement(String name, String value) { + this.name = name; + this.value = value; + } + public MetadataElement(String encodedPair) { + //TODO: Parse encoded pair + this.name = ""; + this.value = ""; + } + public String getName() { + return name; + } + + public String getValue() { + return value; + } + public static boolean isValidMetadataString(String cursorContent) { + if (!cursorContent.startsWith(METADATA_PREFIX) || + cursorContent.equals(METADATA_START) || + cursorContent.equals(METADATA_END)){ + return false; + } + String data = cursorContent.substring(cursorContent.lastIndexOf(METADATA_PREFIX)); + + return true; + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java b/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java new file mode 100644 index 0000000..f22e7b9 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java @@ -0,0 +1,79 @@ +package pro.litvinovg.libreoffice.metadata; + +import java.util.ArrayList; + +import com.sun.star.text.XParagraphCursor; +import com.sun.star.text.XText; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextRange; +import com.sun.star.uno.UnoRuntime; +import static pro.litvinovg.libreoffice.metadata.MetadataElement.*; + +public class OutlineElement { + + private String name; + private ArrayList metadataElements = null; + + public String getName() { + return name; + } + + private XTextRange textRange; + private boolean hasMetadataStorage = false; + private XTextRange metadataTextRange = null; + + public OutlineElement(XTextRange textRange) { + this.textRange = textRange; + this.name = textRange.getString(); + getMetadataStorage(); + } + + private void getMetadataStorage() { + XText curText = textRange.getText(); + XTextCursor cursor = curText.createTextCursorByRange(textRange); + XParagraphCursor paraCursor = UnoRuntime.queryInterface(XParagraphCursor.class, cursor); + readMetadataBody(paraCursor); + if (metadataElements == null) { + metadataElements = new ArrayList(); + } + } + + private void readMetadataBody(XParagraphCursor paraCursor) { + String cursorContent = getNextParaContent(paraCursor); + + if (! cursorContent.equals(METADATA_START)){ + System.out.println("Para doesn't have metadata start header" + cursorContent); + return; + } + ArrayList metadataTempElements = new ArrayList(); + cursorContent = getNextParaContent(paraCursor); + while (cursorContent.startsWith(METADATA_PREFIX)) { + if (cursorContent.equals(METADATA_END)) { + metadataElements = metadataTempElements; + return; + } + if (MetadataElement.isValidMetadataString(cursorContent)) { + metadataTempElements.add(new MetadataElement(cursorContent)); + } else { + //If reading fails exit immediately + return; + } + cursorContent = getNextParaContent(paraCursor); + } + + } + + private String getNextParaContent(XParagraphCursor paraCursor) { + boolean moved = paraCursor.gotoNextParagraph(false); + if (moved == false) { + return ""; + } + moved = paraCursor.gotoEndOfParagraph(true); + if (moved == false) { + return ""; + } + String cursorContent = paraCursor.getString(); + return cursorContent; + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java b/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java index 9ab7fd6..dbeee76 100644 --- a/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java +++ b/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java @@ -44,6 +44,7 @@ import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import javax.swing.JToggleButton; import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.JLabel; public class EditorGUI extends JFrame { //Components @@ -190,6 +191,7 @@ public class EditorGUI extends JFrame { tableDocProps.setModel(docPropertiesModel); tableDocCustomProps = new JTable(); + tableDocCustomProps.setColumnSelectionAllowed(true); tableDocCustomProps.putClientProperty("terminateEditOnFocusLost", true); tableDocCustomProps.setSurrendersFocusOnKeystroke(true); @@ -199,32 +201,49 @@ public class EditorGUI extends JFrame { btnNewButton = new JButton("Save"); + JLabel labelDocProperties = new JLabel("Основные метаданные"); + + JLabel labelDocCustomProperties = new JLabel("Дополнительные метаданные"); + GroupLayout gl_panel = new GroupLayout(panel); gl_panel.setHorizontalGroup( - gl_panel.createParallelGroup(Alignment.LEADING) - .addGroup(Alignment.TRAILING, gl_panel.createSequentialGroup() - .addContainerGap(838, Short.MAX_VALUE) - .addComponent(btnNewButton) - .addGap(58)) - .addGroup(gl_panel.createSequentialGroup() + gl_panel.createParallelGroup(Alignment.TRAILING) + .addGroup(Alignment.LEADING, gl_panel.createSequentialGroup() + .addGap(378) + .addComponent(labelDocProperties, GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) + .addGap(421)) + .addGroup(Alignment.LEADING, gl_panel.createSequentialGroup() + .addContainerGap() + .addGroup(gl_panel.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel.createSequentialGroup() + .addComponent(tableDocProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(Alignment.TRAILING, gl_panel.createSequentialGroup() + .addComponent(btnNewButton) + .addGap(294)))) + .addGroup(Alignment.LEADING, gl_panel.createSequentialGroup() + .addGap(350) + .addComponent(labelDocCustomProperties, GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE) + .addGap(381)) + .addGroup(Alignment.LEADING, gl_panel.createSequentialGroup() .addContainerGap() .addComponent(tableDocCustomProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE) .addContainerGap()) - .addGroup(gl_panel.createSequentialGroup() - .addContainerGap() - .addComponent(tableDocProps, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE) - .addContainerGap()) ); gl_panel.setVerticalGroup( gl_panel.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel.createSequentialGroup() - .addGap(86) + .addGap(53) + .addComponent(labelDocProperties) + .addGap(18) .addComponent(tableDocProps, GroupLayout.PREFERRED_SIZE, 81, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(tableDocCustomProps, GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE) - .addGap(81) + .addComponent(labelDocCustomProperties, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) + .addGap(18) + .addComponent(tableDocCustomProps, GroupLayout.PREFERRED_SIZE, 322, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED, 90, Short.MAX_VALUE) .addComponent(btnNewButton) - .addGap(27)) + .addGap(31)) ); JPopupMenu popupMenu = new JPopupMenu(); @@ -241,9 +260,6 @@ public class EditorGUI extends JFrame { JMenu mnFile = new JMenu("Файл"); menuBar.add(mnFile); - - JMenu mnEdit = new JMenu("Edit"); - menuBar.add(mnEdit); } private void createDocPropsModel() {