diff --git a/.classpath b/.classpath index 6e6fd97..49276ea 100644 --- a/.classpath +++ b/.classpath @@ -3,6 +3,10 @@ - + + + + + diff --git a/.project b/.project index 605dc2d..98f7e58 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - StarterProject + Metadata Editor diff --git a/.unoproject b/.unoproject index fa56036..1a2dfbc 100644 --- a/.unoproject +++ b/.unoproject @@ -1,10 +1,10 @@ #UNO project configuration file -#Tue Apr 05 17:37:26 CEST 2016 +#Fri Apr 10 17:20:27 CEST 2020 project.srcdir=/source -regclassname=org.libreoffice.example.comp.RegistrationHandler +regclassname=pro.litvinovg.libreoffice.metadata.RegistrationHandler javaversion=java5 -project.sdk=5.0.5.2 -project.ooo=LibreOffice 5.0 +project.sdk=6.3.5.2 +project.ooo=LibreOffice 6.3 \#1 project.implementation=comp project.build=build project.language=Java diff --git a/README.md b/README.md index ca44bb9..4475d8c 100644 --- a/README.md +++ b/README.md @@ -1,35 +1 @@ -# LibreOffice Starter Extension - -This repository contains some boilerplate code and config you need to get started to build your own LibreOffice Extension. - -You can use this project as a starting point to write your own extension for LibreOffice. - -## Get started - -1. Install [LibreOffice](http://www.libreoffice.org/download) & the [LibreOffice SDK](http://www.libreoffice.org/download) (5.0 or greater) -2. Install [Eclipse](http://www.eclipse.org/) IDE for Java Developers & the [LOEclipse plugin](https://marketplace.eclipse.org/content/loeclipse) -3. [Download](https://github.com/smehrbrodt/libreoffice-starter-extension/archive/master.zip) this starter project & unzip it -4. Import the project in Eclipse (File->Import->Existing Projects into Workspace) -5. Let Eclipse know the paths to LibreOffice & the SDK (Project->Properties->LibreOffice Properties) -6. Setup Run Configuration - * Go to Run->Run Configurations - * Create a new run configuration of the type "LibreOffice Application" - * Select the project - * Run! - * *Hint: Show the error log to view the output of the run configuration (Window->Show View->Error Log)* -7. The extension will be installed in LibreOffice (see Tools->Extension Manager) -8. To launch the example dialog, click on the newly added toolbar/menu entry which have been added to Writer (named "Starter Project/Action One"). - -## Development Hints -* The entry point is in [StarterProjectImpl.java](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/source/org/libreoffice/example/comp/StarterProjectImpl.java). -* Toolbar items and menu entries are defined in [Addons.xcu](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/registry/org/openoffice/Office/Addons.xcu). -* Shortcuts are defined in [Accelerators.xcu](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/registry/org/openoffice/Office/Accelerators.xcu). -* The position of the toolbar is defined in [WriterWindowState.xcu](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/registry/org/openoffice/Office/UI/WriterWindowState.xcu). -* The dialog shown when clicking "Action One" is [ActionOneDialog.xdl](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/dialog/ActionOneDialog.xdl). The dialog itself contains information how to edit it. -* The [DialogHelper](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/source/org/libreoffice/example/helper/DialogHelper.java) contains some helper methods to work with the dialog. -* To debug the Java code, just stick a breakpoint anywhere in Eclipse and start your run configuration in debug mode. -* If you add non-code files (or an external .jar) to your extension, you need to mention them in [package.properties](https://github.com/smehrbrodt/libreoffice-starter-extension/blob/master/package.properties), else they won't be included in the packaged extension. -* Now go on customizing the extension to your needs. Some helpful links: - * [OpenOffice Wiki](https://wiki.openoffice.org/wiki/Extensions_development) - * [API Reference](http://api.libreoffice.org/docs/idl/ref/index.html) - * [Example extensions](http://api.libreoffice.org/examples/examples.html#Java_examples) +Metadata editor extension diff --git a/description.xml b/description.xml index c7b31ab..9a34e6b 100644 --- a/description.xml +++ b/description.xml @@ -1,10 +1,20 @@ - - + + + + + + + + - StarterProject + MetadataEditor + + + + diff --git a/description/desc_en.txt b/description/desc_en.txt index c7f5de7..abfb432 100644 --- a/description/desc_en.txt +++ b/description/desc_en.txt @@ -1 +1 @@ -LibreOffice Starter Project +Metadata editor for LibreOffice diff --git a/dist/StarterProject.oxt b/dist/StarterProject.oxt deleted file mode 100644 index 1a01ab8..0000000 Binary files a/dist/StarterProject.oxt and /dev/null differ diff --git a/images/actionOne_16.png b/images/actionOne_16.png deleted file mode 100644 index fb7409d..0000000 Binary files a/images/actionOne_16.png and /dev/null differ diff --git a/images/actionOne_26.png b/images/actionOne_26.png deleted file mode 100644 index 268a528..0000000 Binary files a/images/actionOne_26.png and /dev/null differ diff --git a/metadataeditor.update.xml b/metadataeditor.update.xml new file mode 100644 index 0000000..b46d38e --- /dev/null +++ b/metadataeditor.update.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/package.properties b/package.properties index cfffe3d..6463bb9 100644 --- a/package.properties +++ b/package.properties @@ -1,3 +1,3 @@ #Written by the OOEclipseIntegration -#Thu Apr 07 11:36:27 CEST 2016 -contents=description, description/desc_en.txt, dialog, dialog/ActionOneDialog.xdl, images, images/actionOne_16.png, images/actionOne_26.png, registry, registry/org, registry/org/openoffice, registry/org/openoffice/Office, registry/org/openoffice/Office/Accelerators.xcu, registry/org/openoffice/Office/Addons.xcu, registry/org/openoffice/Office/UI, registry/org/openoffice/Office/UI/WriterWindowState.xcu +#Fri Apr 10 17:15:09 CEST 2020 +contents=description, description/desc_en.txt, releasenotes.txt, images, images/actionOne_16.png, images/actionOne_26.png, json-20190722.jar, registry, registry/org, registry/org/openoffice, registry/org/openoffice/Office, registry/org/openoffice/Office/Accelerators.xcu, registry/org/openoffice/Office/Addons.xcu, registry/org/openoffice/Office/UI, registry/org/openoffice/Office/UI/WriterWindowState.xcu diff --git a/registry/org/openoffice/Office/Accelerators.xcu b/registry/org/openoffice/Office/Accelerators.xcu index 07dad35..1374d70 100644 --- a/registry/org/openoffice/Office/Accelerators.xcu +++ b/registry/org/openoffice/Office/Accelerators.xcu @@ -7,7 +7,7 @@ - service:org.libreoffice.example.StarterProject?actionOne + service:pro.litvinovg.libreoffice.MetadataEditor?openGUI diff --git a/registry/org/openoffice/Office/Addons.xcu b/registry/org/openoffice/Office/Addons.xcu index 65cc464..b9d93f3 100644 --- a/registry/org/openoffice/Office/Addons.xcu +++ b/registry/org/openoffice/Office/Addons.xcu @@ -1,32 +1,30 @@ - + - + - service:org.libreoffice.example.StarterProject?actionOne + service:pro.litvinovg.libreoffice.MetadataEditor?openGUI - - vnd.sun.star.extension://org.libreoffice.example.starterproject/images/actionOne_16.png - - - vnd.sun.star.extension://org.libreoffice.example.starterproject/images/actionOne_26.png + + vnd.sun.star.extension://pro.litvinovg.libreoffice.metadata/images/metadata.png - + Starter Project + true - service:org.libreoffice.example.StarterProject?actionOne + service:pro.litvinovg.libreoffice.MetadataEditor?openGUI _self @@ -35,35 +33,14 @@ com.sun.star.text.TextDocument - Action One + Open metadata editor GUI + Открыть редактор метаданных - - - - Starter Project - - - com.sun.star.text.TextDocument - - - - - Action One - - - service:org.libreoffice.example.StarterProject?actionOne - - - _self - - - - - + diff --git a/registry/org/openoffice/Office/UI/WriterWindowState.xcu b/registry/org/openoffice/Office/UI/WriterWindowState.xcu index 3340e7f..a246559 100644 --- a/registry/org/openoffice/Office/UI/WriterWindowState.xcu +++ b/registry/org/openoffice/Office/UI/WriterWindowState.xcu @@ -6,9 +6,10 @@ - + - Aktensystem + Metadata editor + Редактор метаданных 10,0 diff --git a/releasenotes.txt b/releasenotes.txt new file mode 100644 index 0000000..d8a1a26 --- /dev/null +++ b/releasenotes.txt @@ -0,0 +1 @@ +0.3.1 Alpha version diff --git a/source/org/libreoffice/example/comp/RegistrationHandler.classes b/source/org/libreoffice/example/comp/RegistrationHandler.classes deleted file mode 100644 index c145ca0..0000000 --- a/source/org/libreoffice/example/comp/RegistrationHandler.classes +++ /dev/null @@ -1 +0,0 @@ -org.libreoffice.example.comp.StarterProjectImpl diff --git a/source/org/libreoffice/example/comp/StarterProjectImpl.java b/source/org/libreoffice/example/comp/StarterProjectImpl.java deleted file mode 100644 index 912c44c..0000000 --- a/source/org/libreoffice/example/comp/StarterProjectImpl.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.libreoffice.example.comp; - -import com.sun.star.uno.XComponentContext; -import com.sun.star.lib.uno.helper.Factory; - -import org.libreoffice.example.dialog.ActionOneDialog; -import org.libreoffice.example.helper.DialogHelper; - -import com.sun.star.lang.XSingleComponentFactory; -import com.sun.star.registry.XRegistryKey; -import com.sun.star.lib.uno.helper.WeakBase; - - -public final class StarterProjectImpl extends WeakBase - implements com.sun.star.lang.XServiceInfo, - com.sun.star.task.XJobExecutor -{ - private final XComponentContext m_xContext; - private static final String m_implementationName = StarterProjectImpl.class.getName(); - private static final String[] m_serviceNames = { - "org.libreoffice.example.StarterProject" }; - - - public StarterProjectImpl( XComponentContext context ) - { - m_xContext = context; - }; - - public static XSingleComponentFactory __getComponentFactory( String sImplementationName ) { - XSingleComponentFactory xFactory = null; - - if ( sImplementationName.equals( m_implementationName ) ) - xFactory = Factory.createComponentFactory(StarterProjectImpl.class, m_serviceNames); - return xFactory; - } - - public static boolean __writeRegistryServiceInfo( XRegistryKey xRegistryKey ) { - return Factory.writeRegistryServiceInfo(m_implementationName, - m_serviceNames, - xRegistryKey); - } - - // com.sun.star.lang.XServiceInfo: - public String getImplementationName() { - return m_implementationName; - } - - public boolean supportsService( String sService ) { - int len = m_serviceNames.length; - - for( int i=0; i < len; i++) { - if (sService.equals(m_serviceNames[i])) - return true; - } - return false; - } - - public String[] getSupportedServiceNames() { - return m_serviceNames; - } - - // com.sun.star.task.XJobExecutor: - public void trigger(String action) - { - switch (action) { - case "actionOne": - ActionOneDialog actionOneDialog = new ActionOneDialog(m_xContext); - actionOneDialog.show(); - break; - default: - DialogHelper.showErrorMessage(m_xContext, null, "Unknown action: " + action); - } - - } - -} diff --git a/source/org/libreoffice/example/dialog/ActionOneDialog.java b/source/org/libreoffice/example/dialog/ActionOneDialog.java deleted file mode 100644 index f3f398f..0000000 --- a/source/org/libreoffice/example/dialog/ActionOneDialog.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.libreoffice.example.dialog; - -import org.libreoffice.example.helper.DialogHelper; - -import com.sun.star.awt.XDialog; -import com.sun.star.awt.XDialogEventHandler; -import com.sun.star.lang.WrappedTargetException; -import com.sun.star.uno.XComponentContext; - - -public class ActionOneDialog implements XDialogEventHandler { - - private XDialog dialog; - private static final String actionOk = "actionOk"; - private String[] supportedActions = new String[] { actionOk }; - - public ActionOneDialog(XComponentContext xContext) { - this.dialog = DialogHelper.createDialog("ActionOneDialog.xdl", xContext, this); - } - - public void show() { - dialog.execute(); - } - - private void onOkButtonPressed() { - dialog.endExecute(); - } - - @Override - public boolean callHandlerMethod(XDialog dialog, Object eventObject, String methodName) throws WrappedTargetException { - if (methodName.equals(actionOk)) { - onOkButtonPressed(); - return true; // Event was handled - } - return false; // Event was not handled - } - - @Override - public String[] getSupportedMethodNames() { - return supportedActions; - } - -} diff --git a/source/org/libreoffice/example/helper/DialogHelper.java b/source/org/libreoffice/example/helper/DialogHelper.java deleted file mode 100644 index a6df22c..0000000 --- a/source/org/libreoffice/example/helper/DialogHelper.java +++ /dev/null @@ -1,184 +0,0 @@ -package org.libreoffice.example.helper; - -import java.io.File; - -import com.sun.star.awt.MessageBoxType; -import com.sun.star.awt.Point; -import com.sun.star.awt.XButton; -import com.sun.star.awt.XComboBox; -import com.sun.star.awt.XControl; -import com.sun.star.awt.XControlContainer; -import com.sun.star.awt.XControlModel; -import com.sun.star.awt.XDialog; -import com.sun.star.awt.XDialogEventHandler; -import com.sun.star.awt.XDialogProvider2; -import com.sun.star.awt.XFixedText; -import com.sun.star.awt.XListBox; -import com.sun.star.awt.XMessageBox; -import com.sun.star.awt.XMessageBoxFactory; -import com.sun.star.awt.XTextComponent; -import com.sun.star.awt.XToolkit; -import com.sun.star.awt.XWindow; -import com.sun.star.awt.XWindowPeer; -import com.sun.star.beans.PropertyVetoException; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.beans.XPropertySet; -import com.sun.star.lang.WrappedTargetException; -import com.sun.star.uno.Exception; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; - -public class DialogHelper { - - /** - * Create a dialog from an xdl file. - * - * @param xdlFile - * The filename in the `dialog` folder - * @param context - * @return XDialog - */ - public static XDialog createDialog(String xdlFile, XComponentContext context, XDialogEventHandler handler) { - Object oDialogProvider; - try { - oDialogProvider = context.getServiceManager().createInstanceWithContext("com.sun.star.awt.DialogProvider2", - context); - XDialogProvider2 xDialogProv = (XDialogProvider2) UnoRuntime.queryInterface(XDialogProvider2.class, - oDialogProvider); - File dialogFile = FileHelper.getDialogFilePath(xdlFile, context); - return xDialogProv.createDialogWithHandler(convertToURL(context, dialogFile), handler); - } catch (Exception e) { - return null; - } - } - - /** Returns a URL to be used with XDialogProvider to create a dialog */ - public static String convertToURL(XComponentContext xContext, File dialogFile) { - String sURL = null; - try { - com.sun.star.ucb.XFileIdentifierConverter xFileConverter = (com.sun.star.ucb.XFileIdentifierConverter) UnoRuntime - .queryInterface(com.sun.star.ucb.XFileIdentifierConverter.class, xContext.getServiceManager() - .createInstanceWithContext("com.sun.star.ucb.FileContentProvider", xContext)); - sURL = xFileConverter.getFileURLFromSystemPath("", dialogFile.getAbsolutePath()); - } catch (com.sun.star.uno.Exception ex) { - return null; - } - return sURL; - } - - /** Returns a button (XButton) from a dialog */ - public static XButton getButton(XDialog dialog, String componentId) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - Object control = xDlgContainer.getControl(componentId); - return (XButton) UnoRuntime.queryInterface(XButton.class, control); - } - - /** Returns a text field (XTextComponent) from a dialog */ - public static XTextComponent getEditField(XDialog dialog, String componentId) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - Object control = xDlgContainer.getControl(componentId); - return (XTextComponent) UnoRuntime.queryInterface(XTextComponent.class, control); - } - - /** Returns a Combo box (XComboBox) from a dialog */ - public static XComboBox getCombobox(XDialog dialog, String componentId) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - Object control = xDlgContainer.getControl(componentId); - return (XComboBox) UnoRuntime.queryInterface(XComboBox.class, control); - } - - /** Returns a List box (XListBox) from a dialog */ - public static XListBox getListBox(XDialog dialog, String componentId) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - Object control = xDlgContainer.getControl(componentId); - return (XListBox) UnoRuntime.queryInterface(XListBox.class, control); - } - - /** Returns a label (XFixedText) from a dialog */ - public static XFixedText getLabel(XDialog dialog, String componentId) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - Object control = xDlgContainer.getControl(componentId); - return (XFixedText) UnoRuntime.queryInterface(XFixedText.class, control); - } - - public static void EnableButton(XDialog dialog, String componentId, boolean enable) { - XControlContainer xDlgContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, - dialog); - // retrieve the control that we want to disable or enable - XControl xControl = UnoRuntime.queryInterface(XControl.class, xDlgContainer.getControl(componentId)); - XPropertySet xModelPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xControl.getModel()); - try { - xModelPropertySet.setPropertyValue("Enabled", Boolean.valueOf(enable)); - } catch (IllegalArgumentException | UnknownPropertyException | PropertyVetoException - | WrappedTargetException e) { - return; - } - } - - /** Set the focus to an input field */ - public static void SetFocus(XTextComponent editField) { - XWindow xControlWindow = UnoRuntime.queryInterface(XWindow.class, editField); - xControlWindow.setFocus(); - } - - public static void setPosition(XDialog dialog, int posX, int posY) { - XControlModel xDialogModel = UnoRuntime.queryInterface(XControl.class, dialog).getModel(); - XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xDialogModel); - try { - xPropSet.setPropertyValue("PositionX", posX); - xPropSet.setPropertyValue("PositionY", posY); - } catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException - | WrappedTargetException e) { - return; - } - } - - public static Point getPosition(XDialog dialog) { - int posX = 0; - int posY = 0; - XControlModel xDialogModel = UnoRuntime.queryInterface(XControl.class, dialog).getModel(); - XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xDialogModel); - try { - posX = (int) xPropSet.getPropertyValue("PositionX"); - posY = (int) xPropSet.getPropertyValue("PositionY"); - } catch (UnknownPropertyException | WrappedTargetException e) { - } - return new Point(posX, posY); - } - - public static void showInfoMessage(XComponentContext context, XDialog dialog, String message) { - showMessageBox(context, dialog, MessageBoxType.INFOBOX, "Info", message); - } - - public static void showWarningMessage(XComponentContext context, XDialog dialog, String message) { - showMessageBox(context, dialog, MessageBoxType.WARNINGBOX, "Warnung", message); - } - - public static void showErrorMessage(XComponentContext context, XDialog dialog, String message) { - showMessageBox(context, dialog, MessageBoxType.ERRORBOX, "Fehler", message); - } - - public static void showMessageBox(XComponentContext context, XDialog dialog, MessageBoxType type, String sTitle, String sMessage) { - XToolkit xToolkit; - try { - xToolkit = UnoRuntime.queryInterface(XToolkit.class, - context.getServiceManager().createInstanceWithContext("com.sun.star.awt.Toolkit", context)); - } catch (Exception e) { - return; - } - XMessageBoxFactory xMessageBoxFactory = UnoRuntime.queryInterface(XMessageBoxFactory.class, xToolkit); - XWindowPeer xParentWindowPeer = UnoRuntime.queryInterface(XWindowPeer.class, dialog); - XMessageBox xMessageBox = xMessageBoxFactory.createMessageBox(xParentWindowPeer, type, - com.sun.star.awt.MessageBoxButtons.BUTTONS_OK, sTitle, sMessage); - if (xMessageBox == null) - return; - - xMessageBox.execute(); - } - -} diff --git a/source/org/libreoffice/example/helper/DocumentHelper.java b/source/org/libreoffice/example/helper/DocumentHelper.java deleted file mode 100644 index 4d0be80..0000000 --- a/source/org/libreoffice/example/helper/DocumentHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.libreoffice.example.helper; - -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XFrame; -import com.sun.star.frame.XModel; -import com.sun.star.lang.XComponent; -import com.sun.star.lang.XMultiComponentFactory; -import com.sun.star.text.XTextDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; - -public class DocumentHelper { - - /** Returns the curerent XDesktop */ - public static XDesktop getCurrentDesktop(XComponentContext xContext) { - XMultiComponentFactory xMCF = (XMultiComponentFactory) UnoRuntime.queryInterface(XMultiComponentFactory.class, - xContext.getServiceManager()); - Object desktop = null; - try { - desktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); - } catch (Exception e) { - return null; - } - return (XDesktop) UnoRuntime.queryInterface(com.sun.star.frame.XDesktop.class, desktop); - } - - /** Returns the current XComponent */ - private static XComponent getCurrentComponent(XComponentContext xContext) { - return (XComponent) getCurrentDesktop(xContext).getCurrentComponent(); - } - - /** Returns the current frame */ - public static XFrame getCurrentFrame(XComponentContext xContext) { - XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, getCurrentComponent(xContext)); - return xModel.getCurrentController().getFrame(); - } - - /** Returns the current text document (if any) */ - public static XTextDocument getCurrentDocument(XComponentContext xContext) { - return (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, getCurrentComponent(xContext)); - } -} diff --git a/source/org/libreoffice/example/helper/FileHelper.java b/source/org/libreoffice/example/helper/FileHelper.java deleted file mode 100644 index e9596a2..0000000 --- a/source/org/libreoffice/example/helper/FileHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.libreoffice.example.helper; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; - -import com.sun.star.deployment.PackageInformationProvider; -import com.sun.star.deployment.XPackageInformationProvider; -import com.sun.star.uno.Exception; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; -import com.sun.star.util.XURLTransformer; - -public class FileHelper { - - final static String DIALOG_RESOURCES = "dialog/"; - - /** - * Returns a path to a dialog file - */ - public static File getDialogFilePath(String xdlFile, XComponentContext xContext) { - return getFilePath(DIALOG_RESOURCES + xdlFile, xContext); - } - - /** - * Returns a file path for a file in the installed extension, or null on failure. - */ - public static File getFilePath(String file, XComponentContext xContext) { - XPackageInformationProvider xPackageInformationProvider = PackageInformationProvider.get(xContext); - String location = xPackageInformationProvider.getPackageLocation("org.libreoffice.example.starterproject"); - Object oTransformer; - try { - oTransformer = xContext.getServiceManager().createInstanceWithContext("com.sun.star.util.URLTransformer", xContext); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface(XURLTransformer.class, oTransformer); - com.sun.star.util.URL[] oURL = new com.sun.star.util.URL[1]; - oURL[0] = new com.sun.star.util.URL(); - oURL[0].Complete = location + "/" + file; - xTransformer.parseStrict(oURL); - URL url; - try { - url = new URL(oURL[0].Complete); - } catch (MalformedURLException e1) { - return null; - } - File f; - try { - f = new File(url.toURI()); - } catch (URISyntaxException e1) { - return null; - } - return f; - } - -} diff --git a/source/pro/litvinovg/libreoffice/DocumentParser.java b/source/pro/litvinovg/libreoffice/DocumentParser.java new file mode 100644 index 0000000..91b227f --- /dev/null +++ b/source/pro/litvinovg/libreoffice/DocumentParser.java @@ -0,0 +1,6 @@ +package pro.litvinovg.libreoffice; + +public interface DocumentParser { + + public void parse(); +} diff --git a/source/pro/litvinovg/libreoffice/DocumentParserImpl.java b/source/pro/litvinovg/libreoffice/DocumentParserImpl.java new file mode 100644 index 0000000..7c1131f --- /dev/null +++ b/source/pro/litvinovg/libreoffice/DocumentParserImpl.java @@ -0,0 +1,90 @@ +package pro.litvinovg.libreoffice; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.table.XCell; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextRange; +import com.sun.star.text.XTextTable; +import com.sun.star.uno.UnoRuntime; + + +public class DocumentParserImpl implements DocumentParser{ + XText text = null; + protected XTextRange documentEnd = null; + public DocumentParserImpl(XText text) { + super(); + this.text = text; + } + public void parse() { + parseText(text); + } + protected void parseText(XText curText) { + XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, curText); + XEnumeration textEnum = enumAccess.createEnumeration(); + while (textEnum.hasMoreElements()) { + try { + XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, textEnum.nextElement()); + documentEnd = textContent.getAnchor().getEnd(); + if(isSupported(textContent, "com.sun.star.text.TextTable")) { + parseTable(textContent); + } else + if (isSupported(textContent, "com.sun.star.style.ParagraphProperties")) { + parseParagraph(textContent); + } + } catch (NoSuchElementException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } + } + } + + private void parseTable(XTextContent textContent) { + XTextTable table = UnoRuntime.queryInterface(XTextTable.class, textContent); + String[] cellNames = table.getCellNames(); + for (String cellName : cellNames) { + XCell cell = table.getCellByName(cellName); + XText cellText = UnoRuntime.queryInterface(XText.class, cell); + cellText.getText(); + parseText(cellText); + } + } + + private void parseParagraph(XTextContent textContent) { + XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, textContent); + paraProperties(properties, textContent); + XEnumerationAccess enumAccess = UnoRuntime.queryInterface(XEnumerationAccess.class, textContent); + XEnumeration paraEnum = enumAccess.createEnumeration(); + while (paraEnum.hasMoreElements()) { + try { + XPropertySet portionPoperties = UnoRuntime.queryInterface(com.sun.star.beans.XPropertySet.class, paraEnum.nextElement()); + portionProperties(portionPoperties, textContent); + } catch (NoSuchElementException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + protected void portionProperties(XPropertySet portionPoperties, XTextContent textContent) { + } + protected void paraProperties(XPropertySet properties,XTextContent textContent) { + } + + 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/MetadataCleaner.java b/source/pro/litvinovg/libreoffice/MetadataCleaner.java new file mode 100644 index 0000000..3b0e28c --- /dev/null +++ b/source/pro/litvinovg/libreoffice/MetadataCleaner.java @@ -0,0 +1,47 @@ +package pro.litvinovg.libreoffice; + +import static pro.litvinovg.libreoffice.metadata.Document.METADATA_EXTENSION; + +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextField; +import com.sun.star.text.XTextRange; +import com.sun.star.uno.UnoRuntime; + +public class MetadataCleaner extends DocumentParserImpl { + + public MetadataCleaner(XText text) { + super(text); + } + + @Override + public void portionProperties(XPropertySet portionPoperties, XTextContent textContent) { + String portionType = null; + try { + portionType = (String) portionPoperties.getPropertyValue("TextPortionType"); + if (portionType != null && portionType.equals("Annotation")) { + Object annotation = portionPoperties.getPropertyValue("TextField"); + XPropertySet annotationProperties = UnoRuntime.queryInterface(XPropertySet.class, annotation); + String author = (String) annotationProperties.getPropertyValue("Author"); + if (author != null && author.equals(METADATA_EXTENSION)) { + XTextRange anchor = textContent.getAnchor(); + XText curText = anchor.getText(); + XTextField textField = UnoRuntime.queryInterface(XTextField.class, annotation); + try { + curText.removeTextContent( textField ); + } catch (NoSuchElementException e) { + e.printStackTrace(); + } + } + } + } catch (UnknownPropertyException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } + } +} diff --git a/source/pro/litvinovg/libreoffice/MetadataReader.java b/source/pro/litvinovg/libreoffice/MetadataReader.java new file mode 100644 index 0000000..cbc6d2e --- /dev/null +++ b/source/pro/litvinovg/libreoffice/MetadataReader.java @@ -0,0 +1,72 @@ +package pro.litvinovg.libreoffice; + +import java.util.ArrayList; + +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextRange; +import com.sun.star.uno.UnoRuntime; +import pro.litvinovg.libreoffice.metadata.OutlineElement; +import static pro.litvinovg.libreoffice.metadata.Document.*; + + +public class MetadataReader extends DocumentParserImpl { + private ArrayList outline; + private boolean firstPara = true; + + public MetadataReader(XText text, ArrayList outline) { + super(text); + this.outline = outline; + } + @Override + public void parse() { + parseText(text); + OutlineElement lastElement = outline.get(outline.size()-1); + } + + @Override + public void portionProperties(XPropertySet portionPoperties, XTextContent textContent) { + String portionType = null; + try { + portionType = (String) portionPoperties.getPropertyValue("TextPortionType"); + if (portionType != null && portionType.equals("Annotation")) { + Object annotation = portionPoperties.getPropertyValue("TextField"); + XPropertySet annotationProperties = UnoRuntime.queryInterface(XPropertySet.class, annotation); + String author = (String) annotationProperties.getPropertyValue("Author"); + if (author != null && author.equals(METADATA_EXTENSION)) { + String content = (String) annotationProperties.getPropertyValue("Content"); + OutlineElement lastElement = outline.get(outline.size()-1); + lastElement.readMetadata(content); + } + } + } catch (UnknownPropertyException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } + } + + @Override + protected void paraProperties(XPropertySet properties, XTextContent textContent) { + Short outlineLevel = null; + try { + outlineLevel = (Short) properties.getPropertyValue("OutlineLevel"); + } catch (UnknownPropertyException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } + if (firstPara || (outlineLevel != null && outlineLevel > 0)) { + XTextRange textRange = textContent.getAnchor(); + if (firstPara) { + outline.add(new OutlineElement(textRange, "Документ")); + firstPara = false; + } else { + outline.add(new OutlineElement(textRange, textRange.getString())); + } + } + } +} diff --git a/source/pro/litvinovg/libreoffice/metadata/CustomDocumentProperty.java b/source/pro/litvinovg/libreoffice/metadata/CustomDocumentProperty.java new file mode 100644 index 0000000..b2efd3b --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/CustomDocumentProperty.java @@ -0,0 +1,21 @@ +package pro.litvinovg.libreoffice.metadata; + +public class CustomDocumentProperty { + private String name; + private String value; + private String type; + public CustomDocumentProperty(String name, String value, String type) { + this.name = name; + this.value = value; + this.type = type; + } + public String getType() { + return type; + } + public String getName() { + return name; + } + public String getValue() { + return value; + } +} diff --git a/source/pro/litvinovg/libreoffice/metadata/Document.java b/source/pro/litvinovg/libreoffice/metadata/Document.java new file mode 100644 index 0000000..9d920a7 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/Document.java @@ -0,0 +1,328 @@ +package pro.litvinovg.libreoffice.metadata; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +import com.sun.star.beans.IllegalTypeException; +import com.sun.star.beans.NotRemoveableException; +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyExistException; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyVetoException; +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.document.XDocumentProperties; +import com.sun.star.document.XDocumentPropertiesSupplier; +import com.sun.star.frame.XController; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchHelper; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.frame.XFrame; +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.XMultiServiceFactory; +import com.sun.star.text.XText; +import com.sun.star.text.XTextDocument; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.view.XViewSettingsSupplier; + +import pro.litvinovg.libreoffice.DocumentParser; +import pro.litvinovg.libreoffice.MetadataCleaner; +import pro.litvinovg.libreoffice.MetadataReader; + +public class Document { + + private static final String DOC_AUTHOR = "Document author"; + private static final String DOC_TITLE = "Document title"; + private static final String DOC_SUBJECT = "Document subject"; + private static final String DOC_DESCRIPTION = "Document description"; + private static final String DOC_KEYWORDS = "Document keywords"; + private static final short REMOVEABLE_ATTRIBUTE = 128; + public static final String METADATA_EXTENSION = "Metadata Extension"; + + private XComponentContext context; + private XDesktop xDesktop; + private XMultiComponentFactory multiComponentFactory; + private XMultiServiceFactory multiServiceFactory; + private XComponent currentDocument; + private XDocumentProperties documentProperties; + private XDocumentPropertiesSupplier documentPropertiesSupplier; + private XText text = null; + private ArrayList outline = new ArrayList(); + private XFrame frame; + private XDispatchProvider dispatchProvider; + XTextDocument textDocument; + + public Document(XComponentContext componentContext) { + context = componentContext; + multiComponentFactory = context.getServiceManager(); + try { + Object oDesktop = multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", context); + xDesktop = UnoRuntime.queryInterface(XDesktop.class, oDesktop); + getCurrentDocument(); + getDocumentText(); + multiServiceFactory = UnoRuntime.queryInterface(XMultiServiceFactory.class, currentDocument); + readMetadataInDocument(); + frame = xDesktop.getCurrentFrame(); + dispatchProvider = UnoRuntime.queryInterface( com.sun.star.frame.XDispatchProvider.class, frame ); + hideAnnotations(); + } catch (Exception e) { + System.out.println("xDesktop inaccessible. Can not proceed."); + e.printStackTrace(); + System.exit(1); + } + } + + private void getDocumentText() { + textDocument = UnoRuntime.queryInterface(XTextDocument.class,currentDocument); + text = textDocument.getText(); + } + + private void readMetadataInDocument() { + DocumentParser reader = new MetadataReader(text, outline); + reader.parse(); + } + + private void cleanMetadataInDocument() { + DocumentParser reader = new MetadataCleaner(text); + reader.parse(); + } + + public void writeOutlineMetadata() { + cleanMetadataInDocument(); + for (OutlineElement element : outline){ + if (!element.isEmpty()) { + Object annotation; + try { + annotation = multiServiceFactory.createInstance("com.sun.star.text.TextField.Annotation"); + element.writeMetadata(annotation); + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace(); + } + } + } + } + + private void getCurrentDocument() throws MetadataInaccessableException { + currentDocument = xDesktop.getCurrentComponent(); + if (currentDocument == null) { + throw new MetadataInaccessableException("Could not access current document."); + } + } + + public void logProperties() { + logDocumentProperties(); + logDocumentCustomProperties(); + } + + public void setCustomDocumentProperties(ArrayList docCustomProps) { + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + removeStringProperties(); + addStringProperties(docCustomProps); + } + + private void addStringProperties(ArrayList docCustomProps) { + XPropertyContainer userDifinedProperties = documentProperties.getUserDefinedProperties(); + for (int i = 0; i < docCustomProps.size();i++) { + CustomDocumentProperty property = docCustomProps.get(i); + try { + userDifinedProperties.addProperty(property.getName(), REMOVEABLE_ATTRIBUTE, property.getValue()); + // System.out.println("added "+ property.getName() + " value " + property.getValue()); + + } catch (IllegalArgumentException e) { + System.out.println("IllegalArgumentException while adding new property"); + e.printStackTrace(); + } catch (PropertyExistException e) { + System.out.println("Property already exists"); + e.printStackTrace(); + } catch (IllegalTypeException e) { + System.out.println("Property type illegal"); + e.printStackTrace(); + } + } + + } + + private void removeStringProperties() { + XPropertyContainer userDifinedProperties = documentProperties.getUserDefinedProperties(); + XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class, userDifinedProperties); + if (propertySet != null) { + XPropertySetInfo propertySetInfo = propertySet.getPropertySetInfo(); + if (propertySetInfo != null) { + Property[] props = propertySetInfo.getProperties(); + for (Property prop : props) { + if (prop.Type.getTypeName().equals("string")){ + try { + userDifinedProperties.removeProperty(prop.Name); + // System.out.println("removed "+ prop.Name); + } catch (UnknownPropertyException e) { + System.out.println("Property " + prop.Name + " does not exist."); + e.printStackTrace(); + } catch (NotRemoveableException e) { + System.out.println("Property " + prop.Name + " is not removeable."); + e.printStackTrace(); + } + } + } + } + } + } + + public ArrayList getDocumentCustomProperties() { + ArrayList customProps = new ArrayList(); + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + XPropertyContainer userDifinedProperties = documentProperties.getUserDefinedProperties(); + XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class, userDifinedProperties); + if (propertySet != null) { + XPropertySetInfo propertySetInfo = propertySet.getPropertySetInfo(); + if (propertySetInfo != null) { + Property[] props = propertySetInfo.getProperties(); + Arrays.sort(props, new Comparator() { + public int compare(Property p1, Property p2) { + return (p1.Name).compareTo(p2.Name); + } + }); + + for (Property prop : props) { + Object propValue = getProperty(propertySet, prop.Name); + if (prop.Type.getTypeName().equals("string")){ + customProps.add(new CustomDocumentProperty(prop.Name, propValue.toString(), prop.Type.getTypeName())); + } + } + } + } + return customProps; + } + + public Map getDocumentProperties() { + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + Map docProps = new HashMap(); + docProps.put(DOC_AUTHOR, documentProperties.getAuthor()); + docProps.put(DOC_TITLE, documentProperties.getTitle()); + docProps.put(DOC_SUBJECT, documentProperties.getSubject()); + docProps.put(DOC_DESCRIPTION, documentProperties.getDescription()); + String[] keywords = documentProperties.getKeywords(); + StringBuilder keys = new StringBuilder(); + for (int i = 0; i < keywords.length; i++) { + if (i > 0) { + keys.append(","); + } + keys.append(keywords[i]); + } + docProps.put(DOC_KEYWORDS, keys.toString()); + + return docProps; + } + + public void setDocumentProperties(Map docProps) { + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + if (docProps.containsKey(DOC_AUTHOR)) { + documentProperties.setAuthor(docProps.get(DOC_AUTHOR)); + } + if (docProps.containsKey(DOC_TITLE)) { + documentProperties.setTitle(docProps.get(DOC_TITLE)); + } + if (docProps.containsKey(DOC_SUBJECT)) { + documentProperties.setSubject(docProps.get(DOC_SUBJECT)); + } + if (docProps.containsKey(DOC_DESCRIPTION)) { + documentProperties.setDescription(docProps.get(DOC_DESCRIPTION)); + } + if (docProps.containsKey(DOC_KEYWORDS)) { + documentProperties.setKeywords(docProps.get(DOC_KEYWORDS).split(",")); + } + } + + private void logDocumentProperties() { + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + System.out.println(" Author: " + documentProperties.getAuthor()); + System.out.println(" Title: " + documentProperties.getTitle()); + System.out.println(" Subject: " + documentProperties.getSubject()); + System.out.println(" Description: " + documentProperties.getDescription()); + } + + private void logDocumentCustomProperties() { + documentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, currentDocument); + documentProperties = documentPropertiesSupplier.getDocumentProperties(); + XPropertyContainer userDifinedProperties = documentProperties.getUserDefinedProperties(); + XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class, userDifinedProperties); + if (propertySet != null) { + XPropertySetInfo propertySetInfo = propertySet.getPropertySetInfo(); + if (propertySetInfo != null) { + Property[] props = propertySetInfo.getProperties(); + Arrays.sort(props, new Comparator() { + public int compare(Property p1, Property p2) { + return (p1.Name).compareTo(p2.Name); + } + }); + + for (Property prop : props) { + Object propValue = getProperty(propertySet, prop.Name); + System.out.println(" " + prop.Name + ": " + prop.Type.getTypeName() + " == " + propValue); + } + } + } + } + + private static Object getProperty(XPropertySet xProps, String propName) { + Object value = null; + try { + value = xProps.getPropertyValue(propName); + } catch (Exception e) { + System.out.println("Could not get property " + propName); + } + return value; + } + + public ArrayList getOutline(){ + return outline; + } + + public void hideAnnotations() { + XController controller = textDocument.getCurrentController(); + XViewSettingsSupplier viewSettings = UnoRuntime.queryInterface( XViewSettingsSupplier.class, controller); + XPropertySet properties = viewSettings.getViewSettings(); + try { + properties.setPropertyValue("ShowAnnotations", false); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (UnknownPropertyException e) { + e.printStackTrace(); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } + + /* + * try { Object dispatchHelperObj = + * multiComponentFactory.createInstanceWithContext( + * "com.sun.star.frame.DispatchHelper", context); XDispatchHelper dispatchHelper + * = UnoRuntime.queryInterface( XDispatchHelper.class, dispatchHelperObj); + * PropertyValue empty = new PropertyValue(); PropertyValue[] array = new + * PropertyValue[] {empty}; XDispatchProvider dispatchProvider = + * UnoRuntime.queryInterface( XDispatchProvider.class, frame); + * dispatchHelper.executeDispatch(dispatchProvider, ".uno:ShowAnnotations", "", + * 0, array); + * + * + * } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); } + */ + + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java b/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java new file mode 100644 index 0000000..55d5c26 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/MetadataElement.java @@ -0,0 +1,21 @@ +package pro.litvinovg.libreoffice.metadata; + +public class MetadataElement { + + private String name; + private String value; + + public MetadataElement(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/MetadataElementFactory.java b/source/pro/litvinovg/libreoffice/metadata/MetadataElementFactory.java new file mode 100644 index 0000000..5bc37f7 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/MetadataElementFactory.java @@ -0,0 +1,42 @@ +package pro.litvinovg.libreoffice.metadata; + +import java.util.Iterator; +import org.json.JSONException; +import org.json.JSONObject; + +public class MetadataElementFactory { + public static final String METADATA_START = "## Metadata Editor extension. Outline metadata in JSON folllows:"; + public static final String METADATA_PREFIX = "## "; + public static final String METADATA_END = "## Outline metadata finished."; + + + public static MetadataElement fromString(String cursorContent){ + String data = cursorContent.substring(METADATA_PREFIX.length()); + System.out.println("DATA " + data); + //TODO: Switch to Jackson or GSON + JSONObject json = new JSONObject(data); + Iterator iterator = json.keys(); + String name = iterator.next(); + String value = json.getString(name); + return new MetadataElement(name, value); + } + + public static String toString(MetadataElement element) { + + JSONObject json = new JSONObject(); + json.put(element.getName(), element.getValue()); + return METADATA_PREFIX + json.toString(); + } + + public boolean isJSONValid(String test) { + try { + new JSONObject(test); + } catch (JSONException e) { + return false; + } + return true; +} + + + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/MetadataExtensionImpl.java b/source/pro/litvinovg/libreoffice/metadata/MetadataExtensionImpl.java new file mode 100644 index 0000000..b3a8c75 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/MetadataExtensionImpl.java @@ -0,0 +1,98 @@ +package pro.litvinovg.libreoffice.metadata; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +import pro.litvinovg.libreoffice.metadata.views.EditorGUI; + +import com.sun.star.lib.uno.helper.Factory; + +import java.util.Arrays; +import java.util.Comparator; + +import com.sun.star.beans.Property; +import com.sun.star.beans.XPropertyContainer; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.document.XDocumentProperties; +import com.sun.star.document.XDocumentPropertiesSupplier; +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.lib.uno.helper.WeakBase; + + +public final class MetadataExtensionImpl extends WeakBase + implements com.sun.star.lang.XServiceInfo, + com.sun.star.task.XJobExecutor +{ + private final XComponentContext context; + private XDesktop xDesktop; + private XMultiComponentFactory multiComponentFactory; + private XComponent currentDocument; + private XDocumentProperties documentProperties; + private XDocumentPropertiesSupplier documentPropertiesSupplier; + private static final String m_implementationName = MetadataExtensionImpl.class.getName(); + private static final String[] m_serviceNames = { "pro.litvinovg.libreoffice.MetadataEditor" }; + + + public MetadataExtensionImpl(XComponentContext componentContext) { + context = componentContext; + + }; + + public static XSingleComponentFactory __getComponentFactory( String sImplementationName ) { + XSingleComponentFactory xFactory = null; + + if ( sImplementationName.equals( m_implementationName ) ) + xFactory = Factory.createComponentFactory(MetadataExtensionImpl.class, m_serviceNames); + return xFactory; + } + + public static boolean __writeRegistryServiceInfo( XRegistryKey xRegistryKey ) { + return Factory.writeRegistryServiceInfo(m_implementationName, + m_serviceNames, + xRegistryKey); + } + + // com.sun.star.lang.XServiceInfo: + public String getImplementationName() { + return m_implementationName; + } + + public boolean supportsService( String sService ) { + int len = m_serviceNames.length; + + for( int i=0; i < len; i++) { + if (sService.equals(m_serviceNames[i])) + return true; + } + return false; + } + + public String[] getSupportedServiceNames() { + return m_serviceNames; + } + + // com.sun.star.task.XJobExecutor: + public void trigger(String action) + { + switch (action) { + case "openGUI": + Document doc = new Document(context); + EditorGUI.runGUI(doc); + break; + default: + } + + } + + + + + + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/MetadataInaccessableException.java b/source/pro/litvinovg/libreoffice/metadata/MetadataInaccessableException.java new file mode 100644 index 0000000..b4236bb --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/MetadataInaccessableException.java @@ -0,0 +1,7 @@ +package pro.litvinovg.libreoffice.metadata; + +public class MetadataInaccessableException extends Exception { + public MetadataInaccessableException(String errorMessage) { + super(errorMessage); + } +} diff --git a/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java b/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java new file mode 100644 index 0000000..a29b722 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/OutlineElement.java @@ -0,0 +1,130 @@ +package pro.litvinovg.libreoffice.metadata; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Set; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XText; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextField; +import com.sun.star.text.XTextRange; +import com.sun.star.uno.UnoRuntime; +import static pro.litvinovg.libreoffice.metadata.Document.*; +public class OutlineElement { + + private String elementName; + private ArrayList metadata = null; + private XTextRange textRange; + + public String getName() { + return elementName; + } + public boolean isEmpty() { + if (metadata.isEmpty()) { + return true; + } + for (int i = 0; i < metadata.size(); i++) { + if (!metadata.get(i).getName().isEmpty() && !metadata.get(i).getValue().isEmpty()) { + return false; + } + } + return true; + } + + public OutlineElement(XTextRange textRange, String name) { + this.textRange = textRange; + this.elementName = name; + this.metadata = new ArrayList(); + } + + public Object[][] metadataToArray() { + Object [] [] result = null; + int size = metadata.size(); + if (metadata.size() == 0) { + result = new Object[][] { + {"", ""}, + {"", ""}, + {"", ""}, + }; + } else { + result = new Object [size] [2]; + for (int i = 0; i < size; i++) { + result[i][0] = metadata.get(i).getName(); + result[i][1] = metadata.get(i).getValue(); + } + } + return result; + } + + public void readMetadata(String data) { + try { + JSONObject json = new JSONObject(data); + Set nums = json.keySet(); + for (String number : nums) { + JSONObject meta = (JSONObject) json.get(number); + Set names = meta.keySet(); + for (String name: names) { + String value = meta.getString(name); + metadata.add(new MetadataElement(name, value)); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +private String metadataToString() { + JSONObject json = new JSONObject(); + Integer i = 0; + for (MetadataElement element : metadata) { + String name = element.getName(); + String value = element.getValue(); + if (!name.isEmpty() && !value.isEmpty()) { + JSONObject meta = new JSONObject(); + meta.put(element.getName(), element.getValue()); + json.put(i.toString(), meta); + i++; + } + } + return json.toString(); + } + +public void writeMetadata(Object annotation) { + XPropertySet properties = UnoRuntime.queryInterface(XPropertySet.class, annotation); + XText text = textRange.getText(); + try { + properties.setPropertyValue("Author", METADATA_EXTENSION); + properties.setPropertyValue("Content", metadataToString()); + + XTextRange annotationRange = null; + annotationRange = textRange; + XTextField textField = UnoRuntime.queryInterface(XTextField.class, annotation); + text.insertTextContent( annotationRange, textField, false ); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (UnknownPropertyException e) { + e.printStackTrace(); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } catch (WrappedTargetException e) { + e.printStackTrace(); + } +} +public void setMetadata(ArrayList metadataInput) { + this.metadata.clear(); + this.metadata.addAll(metadataInput); +} + + + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.classes b/source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.classes new file mode 100644 index 0000000..11d576c --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.classes @@ -0,0 +1 @@ +pro.litvinovg.libreoffice.metadata.MetadataExtensionImpl diff --git a/source/org/libreoffice/example/comp/RegistrationHandler.java b/source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.java similarity index 99% rename from source/org/libreoffice/example/comp/RegistrationHandler.java rename to source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.java index 3819b73..a67e63e 100644 --- a/source/org/libreoffice/example/comp/RegistrationHandler.java +++ b/source/pro/litvinovg/libreoffice/metadata/RegistrationHandler.java @@ -35,7 +35,7 @@ * * ************************************************************************/ -package org.libreoffice.example.comp; +package pro.litvinovg.libreoffice.metadata; import java.io.IOException; import java.io.InputStream; diff --git a/source/pro/litvinovg/libreoffice/metadata/resources/metadata.png b/source/pro/litvinovg/libreoffice/metadata/resources/metadata.png new file mode 100644 index 0000000..a7af7ee Binary files /dev/null and b/source/pro/litvinovg/libreoffice/metadata/resources/metadata.png differ diff --git a/source/pro/litvinovg/libreoffice/metadata/tests/UnoTests.java b/source/pro/litvinovg/libreoffice/metadata/tests/UnoTests.java new file mode 100644 index 0000000..197cf39 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/tests/UnoTests.java @@ -0,0 +1,13 @@ +package pro.litvinovg.libreoffice.metadata.tests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; +import pro.litvinovg.libreoffice.metadata.tests.uno.WriterTest; + +import pro.litvinovg.libreoffice.metadata.tests.base.UnoSuite; + +@RunWith(UnoSuite.class) +@SuiteClasses({WriterTest.class}) +public class UnoTests { + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/tests/base/UnoSuite.java b/source/pro/litvinovg/libreoffice/metadata/tests/base/UnoSuite.java new file mode 100644 index 0000000..96f31f6 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/tests/base/UnoSuite.java @@ -0,0 +1,75 @@ +package pro.litvinovg.libreoffice.metadata.tests.base; + +import java.util.List; + +import org.junit.runner.Runner; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +public class UnoSuite extends Suite { + + private static XComponentContext componentContext; + + public UnoSuite(Class klass, RunnerBuilder builder) throws InitializationError { + super(klass, builder); + } + + public UnoSuite(RunnerBuilder builder, Class[] classes) throws InitializationError { + super(builder, classes); + } + + public UnoSuite(Class klass, Class[] suiteClasses) throws InitializationError { + super(klass, suiteClasses); + } + + public UnoSuite(Class klass, List runners) throws InitializationError { + super(klass, runners); + } + + public UnoSuite(RunnerBuilder builder, Class klass, Class[] suiteClasses) throws InitializationError { + super(builder, klass, suiteClasses); + } + + @Override + public void run(RunNotifier arg0) { + try { + startOffice(); + } catch (Exception e) { + e.printStackTrace(); + } + super.run(arg0); + + stopOffice(); + } + + private void startOffice() throws Exception { + componentContext = com.sun.star.comp.helper.Bootstrap.bootstrap(); + } + + private void stopOffice() { + try { + if (componentContext != null) { + // Only the uno test suite which started the office can stop it + XMultiComponentFactory xMngr = componentContext.getServiceManager(); + Object oDesktop = xMngr.createInstanceWithContext("com.sun.star.frame.Desktop", componentContext); + XDesktop xDesktop = (XDesktop)UnoRuntime.queryInterface(XDesktop.class, oDesktop); + + xDesktop.terminate(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static XComponentContext getComponentContext() { + return componentContext; + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/tests/helper/UnoHelper.java b/source/pro/litvinovg/libreoffice/metadata/tests/helper/UnoHelper.java new file mode 100644 index 0000000..b639762 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/tests/helper/UnoHelper.java @@ -0,0 +1,28 @@ +package pro.litvinovg.libreoffice.metadata.tests.helper; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.FrameSearchFlag; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.text.XTextDocument; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; + +import pro.litvinovg.libreoffice.metadata.tests.base.UnoSuite; + +public class UnoHelper { + + public static XTextDocument getWriterDocument() throws Exception { + XMultiComponentFactory xMngr = UnoSuite.getComponentContext().getServiceManager(); + Object oDesktop = xMngr.createInstanceWithContext("com.sun.star.frame.Desktop", UnoSuite.getComponentContext()); + XComponentLoader xLoader = (XComponentLoader)UnoRuntime.queryInterface( + XComponentLoader.class, oDesktop); + + XComponent xDoc = xLoader.loadComponentFromURL("private:factory/swriter", "_default", + FrameSearchFlag.ALL, new PropertyValue[0]); + + return (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class, xDoc); + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/tests/uno/WriterTest.java b/source/pro/litvinovg/libreoffice/metadata/tests/uno/WriterTest.java new file mode 100644 index 0000000..752bba8 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/tests/uno/WriterTest.java @@ -0,0 +1,26 @@ +package pro.litvinovg.libreoffice.metadata.tests.uno; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +import com.sun.star.text.XTextDocument; + +import pro.litvinovg.libreoffice.metadata.tests.helper.UnoHelper; + +public class WriterTest { + + private XTextDocument xTextDocument; + + @Before + public void setUp() throws Exception { + xTextDocument = UnoHelper.getWriterDocument(); + } + + @Test + public void test() { + assertNotNull(xTextDocument); + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java b/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java new file mode 100644 index 0000000..4de8c9e --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/views/EditorGUI.java @@ -0,0 +1,449 @@ +package pro.litvinovg.libreoffice.metadata.views; + +import java.awt.BorderLayout; +import java.awt.EventQueue; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import java.awt.GridBagLayout; +import javax.swing.JCheckBox; +import java.awt.GridBagConstraints; +import javax.swing.JButton; +import java.awt.Insets; +import javax.swing.BoxLayout; +import javax.swing.UIManager; +import java.awt.Toolkit; +import javax.swing.JTabbedPane; +import java.awt.GridLayout; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JMenu; +import javax.swing.JTable; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; + +import pro.litvinovg.libreoffice.metadata.CustomDocumentProperty; +import pro.litvinovg.libreoffice.metadata.Document; +import pro.litvinovg.libreoffice.metadata.OutlineElement; + +import javax.swing.JScrollPane; +import javax.swing.JPopupMenu; +import java.awt.Component; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Vector; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import javax.swing.JToggleButton; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.JLabel; +import javax.swing.ScrollPaneConstants; +import java.awt.Dimension; + +public class EditorGUI extends JFrame { + //Components + private JTable tableDocStandard; + private JTable tableDocCustom; + private ArrayList tableModels ; + + //Component models + private DefaultTableModel docPropertiesModel; + private DefaultTableModel docCustomPropsModel; + + + private static JFrame singleFrame = null; + + + private Map docProps; + private ArrayList docCustomProps; + private Document document = null; + private JButton btnSaveButton; + private JMenuItem menuItemPupupDocUserProps; + private ArrayList outline; + private JTabbedPane tabbedPane; + private JPanel panelStandardMetadata; + private JMenuBar menuBar; + + + /** + * Launch the application. + */ + public static void main(String[] args) { + testGUI(); + } + + public static void runGUI(Document doc) { + if (singleFrame != null) { + singleFrame.dispose(); + } + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Throwable e) { + e.printStackTrace(); + } + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + EditorGUI frame = new EditorGUI(doc); + singleFrame = frame; + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setVisible(true); + + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + } + + private static void testGUI() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Throwable e) { + e.printStackTrace(); + } + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + EditorGUI frame = new EditorGUI(); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + public EditorGUI(Document doc) { + this.document = doc; + docProps = document.getDocumentProperties(); + docCustomProps = document.getDocumentCustomProperties(); + outline = document.getOutline(); + tableModels = new ArrayList(); + initComponents(); + createEvents(); + } + + public EditorGUI() { + outline = new ArrayList(); + initComponents(); + createEvents(); + } + + private void createEvents() { + + btnSaveButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + saveAction(); + } + }); + + menuItemPupupDocUserProps.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + docCustomPropsModel.addRow(new Object[] {null, null}); + } + }); + } + private void updateDocCustomProps() { + Vector dataVector = docCustomPropsModel.getDataVector(); + Enumeration elements = dataVector.elements(); + docCustomProps.clear(); + while (elements.hasMoreElements()) { + Vector row = (Vector) elements.nextElement(); + String name = (String) row.get(0); + String value = (String) row.get(1); + if (!name.isEmpty() && !value.isEmpty()) { + docCustomProps.add(new CustomDocumentProperty(name, value, "string")); + } + } + } + + private void updateDocProps() { + Vector dataVector = docPropertiesModel.getDataVector(); + Enumeration elements = dataVector.elements(); + docProps.clear(); + while (elements.hasMoreElements()) { + Vector row = (Vector) elements.nextElement(); + String name = (String) row.get(0); + String value = (String) row.get(1); + docProps.put(name, value); + } + } + private void initComponents() { + configureWindow(); + panelStandardMetadata = new JPanel(); + tabbedPane.addTab("Метаданные либры", null, panelStandardMetadata, null); + tabbedPane.setEnabledAt(0, true); + + + for (OutlineElement element : outline) { + addMetadataTab(element); + } + + createDocPropsModel(); + createCustomDocPropsModel(); + tableDocStandard = new MetadataTable(); + tableDocCustom = new MetadataTable(); + configureTableDocStandard(); + configureTableDocCustom(); + + btnSaveButton = new JButton("Сохранить"); + + GroupLayout gl_panelStandardMetadata = new GroupLayout(panelStandardMetadata); + configureGroupLayoutDoc(gl_panelStandardMetadata); + + JPopupMenu popupMenu = new JPopupMenu(); + addPopup(tableDocCustom, popupMenu); + + menuItemPupupDocUserProps = new JMenuItem("Добавить строку"); + + popupMenu.add(menuItemPupupDocUserProps); + panelStandardMetadata.setLayout(gl_panelStandardMetadata); + + menuBar = new JMenuBar(); + setJMenuBar(menuBar); + + JMenu mnFile = new JMenu("Файл"); + menuBar.add(mnFile); + } + + private void addMetadataTab(OutlineElement element) { + JPanel panelOutline = new JPanel(); + MetadataTableModel outlineTableModel = createOutlineTableModel(element); + tableModels.add(outlineTableModel); + + JButton btnOutlineSave = new JButton("Сохранить"); + btnOutlineSave.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + saveAction(); + } + }); + + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setSize(new Dimension(50, 50)); + + JButton btnOutlineSave_1 = new JButton("Закрыть"); + + GroupLayout groupLayoutOutlineMetadata = new GroupLayout(panelOutline); + groupLayoutOutlineMetadata.setHorizontalGroup( + groupLayoutOutlineMetadata.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayoutOutlineMetadata.createSequentialGroup() + .addGroup(groupLayoutOutlineMetadata.createParallelGroup(Alignment.TRAILING) + .addGroup(groupLayoutOutlineMetadata.createSequentialGroup() + .addContainerGap(557, Short.MAX_VALUE) + .addComponent(btnOutlineSave_1, GroupLayout.PREFERRED_SIZE, 108, GroupLayout.PREFERRED_SIZE) + .addGap(104) + .addComponent(btnOutlineSave) + .addGap(32)) + .addGroup(groupLayoutOutlineMetadata.createSequentialGroup() + .addGap(45) + .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 864, Short.MAX_VALUE))) + .addGap(90)) + ); + groupLayoutOutlineMetadata.setVerticalGroup( + groupLayoutOutlineMetadata.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayoutOutlineMetadata.createSequentialGroup() + .addContainerGap() + .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 600, Short.MAX_VALUE) + .addGap(31) + .addGroup(groupLayoutOutlineMetadata.createParallelGroup(Alignment.BASELINE) + .addComponent(btnOutlineSave_1) + .addComponent(btnOutlineSave)) + .addGap(34)) + ); + JTable tableOutline = new MetadataTable(); + scrollPane.setViewportView(tableOutline); + configureTableOutline(tableOutline, outlineTableModel); + + JPopupMenu popupMenu = new JPopupMenu(); + addPopup(tableOutline, popupMenu); + + JMenuItem menuItem = new JMenuItem("Добавить строку"); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + outlineTableModel.addRow(new Object[] {null, null}); + } + }); + popupMenu.add(menuItem); + panelOutline.setLayout(groupLayoutOutlineMetadata); + tabbedPane.addTab(element.getName(), null, panelOutline, null); + } + + private void configureTableOutline(JTable tableOutline, DefaultTableModel outlineTableModel) { + tableOutline.setModel(outlineTableModel); + tableOutline.putClientProperty("terminateEditOnFocusLost", true); + tableOutline.setSurrendersFocusOnKeystroke(true); + tableOutline.setCellSelectionEnabled(true); + tableOutline.setFillsViewportHeight(true); + } + + private void configureWindow() { + setIconImage(Toolkit.getDefaultToolkit().getImage(EditorGUI.class.getResource("/pro/litvinovg/libreoffice/metadata/resources/metadata.png"))); + setTitle("Редактор метаданных"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setBounds(100, 100, 1170, 755); + getContentPane().setLayout(null); + getContentPane().setLayout(new GridLayout(0, 1, 0, 0)); + + tabbedPane = new JTabbedPane(JTabbedPane.LEFT, JTabbedPane.SCROLL_TAB_LAYOUT); + tabbedPane.setBounds(125, 138, 913, 546); + getContentPane().add(tabbedPane); + } + + private void configureTableDocStandard() { + tableDocStandard.putClientProperty("terminateEditOnFocusLost", true); + tableDocStandard.setSurrendersFocusOnKeystroke(true); + tableDocStandard.setCellSelectionEnabled(true); + tableDocStandard.setFillsViewportHeight(true); + tableDocStandard.setModel(docPropertiesModel); + } + + private void configureTableDocCustom() { + tableDocCustom.setColumnSelectionAllowed(true); + tableDocCustom.putClientProperty("terminateEditOnFocusLost", true); + tableDocCustom.setSurrendersFocusOnKeystroke(true); + tableDocCustom.setFillsViewportHeight(true); + tableDocCustom.setCellSelectionEnabled(true); + tableDocCustom.setModel(docCustomPropsModel); + } + + private void configureGroupLayoutDoc(GroupLayout gl_panelStandardMetadata) { + JLabel labelDocProperties = new JLabel("Основные метаданные"); + JLabel labelDocCustomProperties = new JLabel("Дополнительные метаданные"); + gl_panelStandardMetadata.setHorizontalGroup( + gl_panelStandardMetadata.createParallelGroup(Alignment.TRAILING) + .addGroup(Alignment.LEADING, gl_panelStandardMetadata.createSequentialGroup() + .addGap(378) + .addComponent(labelDocProperties, GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) + .addGap(421)) + .addGroup(Alignment.LEADING, gl_panelStandardMetadata.createSequentialGroup() + .addContainerGap() + .addGroup(gl_panelStandardMetadata.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panelStandardMetadata.createSequentialGroup() + .addComponent(tableDocStandard, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(Alignment.TRAILING, gl_panelStandardMetadata.createSequentialGroup() + .addComponent(btnSaveButton) + .addGap(154)))) + .addGroup(Alignment.LEADING, gl_panelStandardMetadata.createSequentialGroup() + .addGap(350) + .addComponent(labelDocCustomProperties, GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE) + .addGap(381)) + .addGroup(Alignment.LEADING, gl_panelStandardMetadata.createSequentialGroup() + .addContainerGap() + .addComponent(tableDocCustom, GroupLayout.DEFAULT_SIZE, 940, Short.MAX_VALUE) + .addContainerGap()) + ); + gl_panelStandardMetadata.setVerticalGroup( + gl_panelStandardMetadata.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panelStandardMetadata.createSequentialGroup() + .addGap(53) + .addComponent(labelDocProperties) + .addGap(18) + .addComponent(tableDocStandard, GroupLayout.PREFERRED_SIZE, 81, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(labelDocCustomProperties, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) + .addGap(18) + .addComponent(tableDocCustom, GroupLayout.PREFERRED_SIZE, 322, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED, 90, Short.MAX_VALUE) + .addComponent(btnSaveButton) + .addGap(31)) + ); + } + + private void createDocPropsModel() { + Object[][] tableArray = new Object[][] { + {null, null}, + {null, null}, + {null, null}, + {null, null}, + {null, null}, + }; + if (docProps != null) { + Object[] arrayOfEntries = docProps.entrySet().toArray(); + tableArray = new Object[docProps.size()][2]; + for (int i = 0; i < tableArray.length; i++) { + Entry entry = (Entry) arrayOfEntries[i]; + tableArray[i][0] = entry.getKey(); + tableArray[i][1] = entry.getValue(); + } + } + docPropertiesModel = new DefaultTableModel( + tableArray, + new String[] { + "Metadata name", "Metadata value" + }); + } + + private MetadataTableModel createOutlineTableModel(OutlineElement element) { + + MetadataTableModel outlineTableModel = new MetadataTableModel(element); + return outlineTableModel; + } + private void createCustomDocPropsModel() { + Object[][] tableArray = new Object[][] { + {null, null}, + {null, null}, + {null, null}, + {null, null}, + }; + if (docCustomProps != null) { + tableArray = new Object[docCustomProps.size()][2]; + for (int i = 0; i < tableArray.length; i++) { + CustomDocumentProperty curProp = docCustomProps.get(i); + tableArray[i][0] = curProp.getName(); + tableArray[i][1] = curProp.getValue(); + } + } + docCustomPropsModel = new DefaultTableModel( + tableArray, + new String[] { + "Metadata name", "Metadata value" + }); + } + + + private static void addPopup(Component component, JPopupMenu popup) { + component.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + showMenu(e); + } + } + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + showMenu(e); + } + } + private void showMenu(MouseEvent e) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + }); + } + public void saveAction() { + updateDocProps(); + document.setDocumentProperties(docProps); + updateDocCustomProps(); + document.setCustomDocumentProperties(docCustomProps); + updateOutlineMetadata(); + document.writeOutlineMetadata(); + document.hideAnnotations(); + } + + + private void updateOutlineMetadata() { + for (MetadataTableModel table : tableModels) { + table.writeToOutline(); + } + } +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/MetadataCellEditor.java b/source/pro/litvinovg/libreoffice/metadata/views/MetadataCellEditor.java new file mode 100644 index 0000000..bc1fe6a --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/views/MetadataCellEditor.java @@ -0,0 +1,50 @@ +package pro.litvinovg.libreoffice.metadata.views; + +import java.awt.Component; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.table.TableCellEditor; + +public class MetadataCellEditor extends AbstractCellEditor implements TableCellEditor { + JTextArea comp = new JTextArea(); + JTable table; + int row; + + public MetadataCellEditor() { + comp.setLineWrap(true); + comp.setWrapStyleWord(true); + comp.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + super.componentResized(e); + table.setRowHeight(row, (int) (comp.getPreferredSize().getHeight())); + } + }); + comp.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + super.keyTyped(e); + table.setRowHeight(row, (int) (comp.getPreferredSize().getHeight())); + } + }); + } + + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + this.table = table; + this.row = row; + + comp.setText((String) value); + comp.setFont(table.getFont()); + + return comp; + } + + public Object getCellEditorValue() { + return comp.getText(); + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/MetadataTable.java b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTable.java new file mode 100644 index 0000000..63ea8ad --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTable.java @@ -0,0 +1,20 @@ +package pro.litvinovg.libreoffice.metadata.views; + +import javax.swing.DefaultCellEditor; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + +public class MetadataTable extends JTable { + + public TableCellRenderer getCellRenderer(int row, int col) { + return new MetadataTableRenderer(); + } + + public TableCellEditor getCellEditor(int row, int col) { + return new MetadataCellEditor(); + } + +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableModel.java b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableModel.java new file mode 100644 index 0000000..124ae13 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableModel.java @@ -0,0 +1,35 @@ +package pro.litvinovg.libreoffice.metadata.views; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Vector; + +import javax.swing.table.DefaultTableModel; + +import pro.litvinovg.libreoffice.metadata.CustomDocumentProperty; +import pro.litvinovg.libreoffice.metadata.MetadataElement; +import pro.litvinovg.libreoffice.metadata.OutlineElement; + +public class MetadataTableModel extends DefaultTableModel { + private OutlineElement outlineElement; + public MetadataTableModel(OutlineElement element) { + super(element.metadataToArray(), new String[] { "Metadata Name", "Metadata Value" }); + this.outlineElement = element; + } + + public void writeToOutline() { + Vector dataVector = this.getDataVector(); + Enumeration elements = dataVector.elements(); + ArrayList metadata = new ArrayList(); + while (elements.hasMoreElements()) { + Vector row = (Vector) elements.nextElement(); + String name = (String) row.get(0); + String value = (String) row.get(1); + + if (name != null && !name.isEmpty() && value != null && !value.isEmpty()) { + metadata.add(new MetadataElement(name, value)); + } + } + outlineElement.setMetadata(metadata); + } +} diff --git a/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableRenderer.java b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableRenderer.java new file mode 100644 index 0000000..cde3583 --- /dev/null +++ b/source/pro/litvinovg/libreoffice/metadata/views/MetadataTableRenderer.java @@ -0,0 +1,23 @@ +package pro.litvinovg.libreoffice.metadata.views; + +import java.awt.Component; + +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.table.TableCellRenderer; + +public class MetadataTableRenderer extends JTextArea implements TableCellRenderer{ + private static final long serialVersionUID = 1L; + + public MetadataTableRenderer() { + setOpaque(true); + setLineWrap(true); + setWrapStyleWord(true); + } + + public Component getTableCellRendererComponent(JTable table,Object value, + boolean isSelected, boolean hasFocus, int row,int column) { + this.setText(value == null ? "" : value.toString()); + return this; + } +}