summaryrefslogtreecommitdiff
path: root/ooxml/source/framework/OOXMLViewer/src/org
diff options
context:
space:
mode:
Diffstat (limited to 'ooxml/source/framework/OOXMLViewer/src/org')
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/DetailViewManager.java131
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/ImageView.java75
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/KeyListener.java50
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/OOXMLViewer.java208
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/PartsView.java137
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/StreamView.java266
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/ContentView.java77
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationImporter.java81
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationModel.java43
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/Slide.java56
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideManager.java77
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideParser.java80
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/DocumentFactory.java127
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/FormatState.java61
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Formatter.java93
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Line.java239
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/LineContainer.java194
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Run.java249
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/RunRange.java87
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Style.java109
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/TokenView.java406
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/DocumentTokenFormatter.java399
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/Token.java51
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/TokenType.java41
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLScanner.java438
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLTokenViewFactory.java106
-rwxr-xr-xooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xmltokenview/XMLViewFactory.java143
27 files changed, 4024 insertions, 0 deletions
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/DetailViewManager.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/DetailViewManager.java
new file mode 100755
index 000000000000..5bf1e194cfbd
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/DetailViewManager.java
@@ -0,0 +1,131 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.util.Vector;
+
+import javax.swing.JScrollPane;
+
+import org.apache.openoffice.ooxml.framework.part.ContentType;
+import org.apache.openoffice.ooxml.framework.part.OOXMLPackage;
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.PartName;
+import org.apache.openoffice.ooxml.framework.part.parser.ParserFactory;
+import org.apache.openoffice.ooxml.viewer.tokenview.TokenView;
+import org.apache.openoffice.ooxml.viewer.xml.TokenType;
+import org.apache.openoffice.ooxml.viewer.xml.XMLTokenViewFactory;
+import org.apache.openoffice.ooxml.viewer.xmltokenview.XMLViewFactory;
+
+public class DetailViewManager
+{
+ public DetailViewManager (
+ final JScrollPane aDetailViewContainer,
+ final OOXMLPackage aPackage)
+ {
+ maDetailViewContainer = aDetailViewContainer;
+ maPackage = aPackage;
+ maViewFactory = new XMLTokenViewFactory();
+ }
+
+
+
+
+ public void ShowPart (
+ final PartName aName,
+ final ContentType eType)
+ {
+ ShowPart(maPackage.getPart(aName));
+ }
+
+
+
+
+ public void ShowPart (final Part aPart)
+ {
+ switch(aPart.getContentType())
+ {
+ case ImageGIF:
+ case ImageJPG:
+ case ImagePNG:
+ maDetailViewContainer.setViewportView(
+ new ImageView(aPart.getStream()).GetComponent());
+ break;
+
+ case ApplicationDrawing:
+ case ApplicationExcel:
+ case ApplicationXML:
+ case Chart:
+ case ContentTypes:
+ case CoreProperties:
+ case CustomXMLProperties:
+ case ExtendedProperties:
+ case PmlDocument:
+ case PmlHandoutMaster:
+ case PmlNotesMaster:
+ case PmlNotesSlide:
+ case PmlProperties:
+ case PmlSlide:
+ case PmlSlideLayout:
+ case PmlSlideMaster:
+ case PmlTableStyles:
+ case PmlViewProperties:
+ case Relationships:
+ case SmlSheet:
+ case Theme:
+ case ThemeOverride:
+ case WmlDocument:
+ case WmlEndNotes:
+ case WmlFontTable:
+ case WmlFootNotes:
+ case WmlFooter:
+ case WmlHeader:
+ case WmlNumbering:
+ case WmlSettings:
+ case WmlStyles:
+ case WmlWebSettings:
+ final TokenView<TokenType> aTokenView = maViewFactory.Create(aPart.getStream());
+ maDetailViewContainer.setViewportView(aTokenView);
+ final Vector<String> aErrorsAndWarnings = new Vector<>();
+ XMLViewFactory.AddSemanticInformation(
+ aTokenView,
+ ParserFactory.getParser(
+ aPart.getContentType(),
+ aPart.getStream(),
+ aErrorsAndWarnings),
+ aErrorsAndWarnings);
+ break;
+
+ case OleObject:
+ case Unknown:
+ default:
+ maDetailViewContainer.setViewportView(null);
+ break;
+ }
+ }
+
+
+
+
+ private final JScrollPane maDetailViewContainer;
+ private XMLTokenViewFactory maViewFactory;
+ private OOXMLPackage maPackage;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/ImageView.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/ImageView.java
new file mode 100755
index 000000000000..b7ea3baf4c7c
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/ImageView.java
@@ -0,0 +1,75 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+@SuppressWarnings("serial")
+public class ImageView
+ extends JPanel
+{
+ public ImageView (final InputStream aInputStream)
+ {
+ BufferedImage aImage = null;
+ try
+ {
+ aImage = ImageIO.read(aInputStream);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ maImage = aImage;
+ }
+
+
+
+
+ public JComponent GetComponent()
+ {
+ return this;
+ }
+
+
+
+
+ @Override
+ public void paintComponent (final Graphics aGraphics)
+ {
+ super.paintComponent(aGraphics);
+ if (maImage != null)
+ {
+ aGraphics.drawImage(maImage, 10, 10, null);
+ }
+ }
+
+
+
+ private final BufferedImage maImage;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/KeyListener.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/KeyListener.java
new file mode 100755
index 000000000000..ed752ef8e465
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/KeyListener.java
@@ -0,0 +1,50 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.awt.event.KeyEvent;
+
+public class KeyListener
+ implements java.awt.event.KeyListener
+{
+
+ @Override
+ public void keyTyped(KeyEvent e)
+ {
+ System.out.println(e);
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/OOXMLViewer.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/OOXMLViewer.java
new file mode 100755
index 000000000000..cc7f3636eb2f
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/OOXMLViewer.java
@@ -0,0 +1,208 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.Vector;
+
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.UIManager;
+
+import org.apache.openoffice.ooxml.framework.part.OOXMLPackage;
+import org.apache.openoffice.ooxml.framework.part.parser.ParserFactory;
+import org.apache.openoffice.ooxml.parser.Log;
+import org.apache.openoffice.ooxml.viewer.content.ContentView;
+
+/** A simple viewer for the streams inside an OOXML file.
+ */
+public class OOXMLViewer
+{
+ public static void main (final String[] aArguments)
+ {
+ try
+ {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ Log.Dbg = null;
+
+ // Process options.
+ final Vector<String> aFilenames = new Vector<>();
+ for (int nIndex=0; nIndex<aArguments.length; ++nIndex)
+ {
+ if (aArguments[nIndex].startsWith("-"))
+ {
+ switch (aArguments[nIndex])
+ {
+ case "-t":
+ ++nIndex;
+ if (nIndex >= aArguments.length)
+ {
+ System.err.printf("expecting argument after option '-t'");
+ System.exit(1);
+ }
+ ParserFactory.SetParserTableFilename(aArguments[nIndex]);
+ break;
+
+ default:
+ System.out.printf("unknown option '%s'\n", aArguments[nIndex]);
+ System.exit(1);;
+ break;
+
+ }
+ }
+ else
+ aFilenames.add(aArguments[nIndex]);
+ }
+
+ for (final String sFilename : aFilenames)
+ {
+ final OOXMLViewer aViewer = new OOXMLViewer();
+ aViewer.SetFile(new File(sFilename));
+ aViewer.maFrame.setVisible(true);
+ }
+ }
+
+
+
+
+ private OOXMLViewer ()
+ {
+ maFrame = new JFrame("OOXML Viewer");
+ maFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ maFrame.setSize(1024,768);
+ maContainer = new JPanel();
+ maFrame.add(maContainer, BorderLayout.CENTER);
+
+ maFrame.setJMenuBar(CreateMenuBar());
+ maFrame.addKeyListener(new KeyListener());
+ }
+
+
+
+
+ private void SetFile (final File aFile)
+ {
+ if ( ! aFile.exists())
+ {
+ JOptionPane.showMessageDialog(
+ maFrame,
+ "File '"+aFile.toString()+"' does not exist",
+ "File Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ else if ( ! aFile.canRead())
+ {
+ JOptionPane.showMessageDialog(
+ maFrame,
+ "Can not open '"+aFile.toString()+"' for reading",
+ "File Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ else
+ {
+ maContainer.removeAll();
+ maContainer.setLayout(new BorderLayout());
+
+ final OOXMLPackage aPackage = OOXMLPackage.Create(aFile);
+ final JScrollPane aDetailViewContainer = new JScrollPane(
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ aDetailViewContainer.getVerticalScrollBar().setUnitIncrement(10);
+ final DetailViewManager aDetailViewManager = new DetailViewManager(aDetailViewContainer, aPackage);
+
+ final JTabbedPane aLeftSidebar = new JTabbedPane();
+
+ final ContentView aContentView = new ContentView(aDetailViewManager, aPackage);
+ aLeftSidebar.addTab("Content", new JScrollPane(aContentView));
+
+ final StreamView aFragmentView = new StreamView(aDetailViewManager, aPackage);
+ aLeftSidebar.addTab("Streams", new JScrollPane(aFragmentView));
+
+ final PartsView aPartsView = new PartsView(aDetailViewManager, aPackage);
+ aLeftSidebar.addTab("Parts", new JScrollPane(aPartsView));
+
+ final JSplitPane aPane = new JSplitPane(
+ JSplitPane.HORIZONTAL_SPLIT,
+ aLeftSidebar,
+ aDetailViewContainer
+ );
+ aPane.setDividerLocation(200);
+
+ maContainer.add(aPane, BorderLayout.CENTER);
+
+ aFragmentView.ShowInitialPart();
+ }
+ }
+
+
+
+
+ private JMenuBar CreateMenuBar ()
+ {
+ final JMenuBar aMenuBar = new JMenuBar();
+
+ final JMenu aFileMenu = new JMenu("File");
+ aMenuBar.add(aFileMenu);
+
+ final JMenuItem aOpenItem = new JMenuItem("Open");
+ aOpenItem.addActionListener(new ActionListener()
+ {
+ @Override public void actionPerformed (final ActionEvent aEvent)
+ {
+ final JFileChooser aFileChooser = new JFileChooser();
+ final int nResult = aFileChooser.showOpenDialog(null);
+ if (nResult == JFileChooser.APPROVE_OPTION)
+ {
+ final OOXMLViewer aViewer = new OOXMLViewer();
+ aViewer.SetFile(aFileChooser.getSelectedFile());
+ }
+ }
+ });
+ aFileMenu.add(aOpenItem);
+
+ return aMenuBar;
+ }
+
+
+
+
+ private final JFrame maFrame;
+ private final JComponent maContainer;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/PartsView.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/PartsView.java
new file mode 100755
index 000000000000..caa9b3a9e308
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/PartsView.java
@@ -0,0 +1,137 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+import org.apache.openoffice.ooxml.framework.part.ContentType;
+import org.apache.openoffice.ooxml.framework.part.IReferenceProvider;
+import org.apache.openoffice.ooxml.framework.part.OOXMLPackage;
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.PartName;
+
+@SuppressWarnings("serial")
+public class PartsView
+ extends JTree
+ implements TreeSelectionListener
+{
+ public PartsView (
+ final DetailViewManager aDetailViewManager,
+ final OOXMLPackage aPackage)
+ {
+ maPackage = aPackage;
+ maDetailViewManager = aDetailViewManager;
+
+ Initialize();
+
+ getSelectionModel().addTreeSelectionListener(this);
+ }
+
+
+
+ private final void Initialize ()
+ {
+ final DefaultMutableTreeNode aRootNode = new DefaultMutableTreeNode(
+ "top level relations");
+ final TreeModel aModel = new DefaultTreeModel(aRootNode);
+
+ final Queue<IReferenceProvider> aWorklist = new LinkedList<IReferenceProvider>();
+ aWorklist.add(maPackage);
+ final Set<PartName> aProcessedPartNames = new TreeSet<PartName>();
+ CreateChildren(aRootNode, aProcessedPartNames, maPackage);
+ setModel(aModel);
+ }
+
+
+
+
+ private void CreateChildren (
+ final DefaultMutableTreeNode aNode,
+ final Set<PartName> aProcessedPartNames,
+ final IReferenceProvider aReferences)
+ {
+ for (final PartName aTarget : aReferences.getRelatedParts().getAllTargets())
+ {
+ Part aPart = maPackage.getPart(aTarget);
+ final DefaultMutableTreeNode aRelationNode;
+ if ( ! aProcessedPartNames.contains(aPart.getPartName()))
+ {
+ aProcessedPartNames.add(aPart.getPartName());
+ aRelationNode = new DefaultMutableTreeNode(aPart.getPartName().GetFullname());
+ CreateChildren(aRelationNode, aProcessedPartNames, aPart);
+ }
+ else
+ {
+ aRelationNode = new DefaultMutableTreeNode(aPart.getPartName().GetFullname() + "...");
+ }
+ aNode.add(aRelationNode);
+ }
+ }
+
+
+
+
+ /** Callback for clicks on the part view.
+ */
+ @Override
+ public void valueChanged (final TreeSelectionEvent aEvent)
+ {
+ final TreePath aPath = aEvent.getNewLeadSelectionPath();
+ if (aPath != null)
+ {
+ final PartName aName= GetPackagePathForTreePath(aPath);
+ final ContentType eType = maPackage.getPart(
+ aName).getContentType();
+ maDetailViewManager.ShowPart(
+ aName,
+ eType);
+ }
+ }
+
+
+
+
+
+ private PartName GetPackagePathForTreePath (final TreePath aPath)
+ {
+ final PartName aName = new PartName(aPath.getLastPathComponent().toString());
+ return aName;
+ }
+
+
+
+
+
+ private final OOXMLPackage maPackage;
+ private final DetailViewManager maDetailViewManager;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/StreamView.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/StreamView.java
new file mode 100755
index 000000000000..61d497d02a5f
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/StreamView.java
@@ -0,0 +1,266 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import org.apache.openoffice.ooxml.framework.part.ContentType;
+import org.apache.openoffice.ooxml.framework.part.OOXMLPackage;
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.PartName;
+
+/** Overview of the individual parts/streams in an OOXML file.
+ */
+@SuppressWarnings("serial")
+public class StreamView
+ extends JTree
+ implements TreeSelectionListener, MouseMotionListener
+{
+ /** Create a new PartsView object for the given OOXML file.
+ * When the user clicks on one part entry then the DetailViewManager is
+ * called and asked to display the part.
+ */
+ StreamView (
+ final DetailViewManager aDetailViewManager,
+ final OOXMLPackage aPackage)
+ {
+ maDetailViewManager = aDetailViewManager;
+ maOOXMLPackage = aPackage;
+ getSelectionModel().addTreeSelectionListener(this);
+
+ // Listen for motion events so that the tooltip can be set according to
+ // the entry under the mouse pointer.
+ addMouseMotionListener(this);
+
+ // Create a tree model for the streams in the (zip) file, set the model
+ // asynchronously at the JTree and finally expand all nodes.
+ final TreeModel aModel = CreateTreeModel(aPackage);
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ setModel(aModel);
+ for (int nIndex=0; nIndex<getRowCount(); ++nIndex)
+ {
+ expandRow(nIndex);
+ }
+ }
+ });
+
+ setToolTipText("hallo");
+ }
+
+
+
+
+ private TreeModel CreateTreeModel (final OOXMLPackage aPackage)
+ {
+ final DefaultMutableTreeNode aRootNode = new DefaultMutableTreeNode(
+ aPackage.getFileName());
+ final DefaultTreeModel aModel = new DefaultTreeModel(aRootNode);
+ try
+ {
+ for (final String sStreamName : aPackage.listStreamNames())
+ {
+ DefaultMutableTreeNode aNode = aRootNode;
+ for (final String sPart : sStreamName.split("/"))
+ {
+ DefaultMutableTreeNode aChild = GetChildNodeForName(aNode, sPart);
+ if (aChild == null)
+ {
+ aChild = new DefaultMutableTreeNode(sPart);
+ aNode.add(aChild);
+ }
+
+ aNode = aChild;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return aModel;
+ }
+
+
+
+
+ public void ShowInitialPart ()
+ {
+ final Part aPart = maOOXMLPackage.getOfficeDocumentPart();
+ MakePartVisible(aPart);
+ maDetailViewManager.ShowPart(aPart);
+ }
+
+
+
+
+ private DefaultMutableTreeNode GetChildNodeForName (final TreeNode aNode, final String sName)
+ {
+ for (int nIndex=0; nIndex<aNode.getChildCount(); ++nIndex)
+ {
+ final TreeNode aChild = aNode.getChildAt(nIndex);
+ if (aChild.toString().equals(sName))
+ {
+ return (DefaultMutableTreeNode)aChild;
+ }
+ }
+ return null;
+ }
+
+
+
+
+ /** Callback for clicks on the part view.
+ */
+ @Override
+ public void valueChanged (final TreeSelectionEvent aEvent)
+ {
+ final TreePath aPath = aEvent.getNewLeadSelectionPath();
+ if (aPath != null)
+ {
+ final String sPath = GetPackagePathForTreePath(aPath);
+ final PartName aName = new PartName(sPath);
+ final ContentType eType = maOOXMLPackage.getPart(
+ aName).getContentType();
+ maDetailViewManager.ShowPart(
+ aName,
+ eType);
+ }
+ }
+
+
+
+
+ @Override
+ public void mouseDragged (final MouseEvent aEvent)
+ {
+ }
+
+
+
+
+ @Override
+ public void mouseMoved (final MouseEvent aEvent)
+ {
+ final int nRow = getRowForLocation(aEvent.getX(), aEvent.getY());
+ if (nRow >= 0)
+ {
+ final String sPath = GetPackagePathForTreePath(getPathForRow(nRow));
+ SetPartUnderMouse(sPath);
+ }
+ }
+
+
+
+
+ private String GetPackagePathForTreePath (final TreePath aPath)
+ {
+ final StringBuffer sPath = new StringBuffer("");
+ final Object aNodes[] = aPath.getPath();
+ for (int nIndex=1; nIndex<aNodes.length; ++nIndex)
+ {
+ sPath.append("/");
+ sPath.append(aNodes[nIndex].toString());
+ }
+ return sPath.toString();
+ }
+
+
+
+
+ private void SetPartUnderMouse (final String sPartPath)
+ {
+ if (msPartPathUnderMouse==null
+ || ! msPartPathUnderMouse.equals(sPartPath))
+ {
+ msPartPathUnderMouse = sPartPath;
+
+ final ContentType eType = maOOXMLPackage.getPart(
+ new PartName(msPartPathUnderMouse)).getContentType();
+ String sToolTipText = eType.toString();
+ if ( ! eType.GetLongName().isEmpty())
+ sToolTipText += " (" + eType.GetLongName() + ")";
+ setToolTipText(sToolTipText);
+ }
+ }
+
+
+
+
+ private void MakePartVisible (final Part aPart)
+ {
+ final String[] aPathParts = aPart.getPartName().GetFullname().substring(1).split("/");
+ final TreeNode[] aTreeNodePath = new TreeNode[aPathParts.length+1];
+ TreeNode aNode = (TreeNode)getModel().getRoot();
+ int nDepth = 0;
+ aTreeNodePath[nDepth++] = aNode;
+ for (final String sPathPart : aPathParts)
+ {
+ boolean bFoundChild = false;
+ for (int nIndex=0; nIndex<aNode.getChildCount(); ++nIndex)
+ {
+ final TreeNode aChildNode = aNode.getChildAt(nIndex);
+ final String sChildName = aChildNode.toString();
+ if (sChildName.equals(sPathPart))
+ {
+ aNode = aChildNode;
+ aTreeNodePath[nDepth++] = aNode;
+ bFoundChild = true;
+ break;
+ }
+ }
+ if ( ! bFoundChild)
+ return;
+ }
+
+ SelectNode(new TreePath(aTreeNodePath));
+ }
+
+
+
+
+ private void SelectNode (final TreePath aTreePath)
+ {
+// getSelectionModel().setSelectionPath(aTreePath);
+// scrollPathToVisible(aTreePath);
+ }
+
+
+
+
+ private final DetailViewManager maDetailViewManager;
+ private final OOXMLPackage maOOXMLPackage;
+ private String msPartPathUnderMouse;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/ContentView.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/ContentView.java
new file mode 100755
index 000000000000..a5049813ba5d
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/ContentView.java
@@ -0,0 +1,77 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+
+import org.apache.openoffice.ooxml.framework.part.OOXMLPackage;
+import org.apache.openoffice.ooxml.viewer.DetailViewManager;
+
+/** Overview of the individual parts/streams in an OOXML file.
+ */
+@SuppressWarnings("serial")
+public class ContentView
+ extends JTree
+{
+ public ContentView (
+ final DetailViewManager aDetailViewManager,
+ final OOXMLPackage aPackage)
+ {
+ TreeModel aModel = null;
+ switch(aPackage.getOfficeDocumentPart().getContentType())
+ {
+ case PmlDocument:
+ aModel = CreateTreeForPresentationModel(new PresentationImporter().importModel(
+ aPackage.getOfficeDocumentPart()));
+ break;
+ //case SmlDocument:
+ //case WmlDocument:
+ default:
+ break;
+ }
+ if (aModel != null)
+ setModel(aModel);
+ }
+
+
+
+
+
+
+ private TreeModel CreateTreeForPresentationModel (final PresentationModel aModel)
+ {
+ final DefaultMutableTreeNode aRootNode = new DefaultMutableTreeNode(
+ "presentation");
+ final DefaultTreeModel aTreeModel = new DefaultTreeModel(aRootNode);
+
+ for (final Slide aSlide : aModel.GetSlideManager().GetSlides())
+ {
+ DefaultMutableTreeNode aNode = new DefaultMutableTreeNode(
+ aSlide.toString());
+ aRootNode.add(aNode);
+ }
+ return aTreeModel;
+ }
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationImporter.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationImporter.java
new file mode 100755
index 000000000000..5581ca41887a
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationImporter.java
@@ -0,0 +1,81 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+import java.io.InputStream;
+import java.util.Vector;
+
+import javax.xml.stream.Location;
+
+import org.apache.openoffice.ooxml.framework.part.ContentType;
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.parser.ParserFactory;
+import org.apache.openoffice.ooxml.parser.ElementContext;
+import org.apache.openoffice.ooxml.parser.Parser;
+import org.apache.openoffice.ooxml.parser.action.ActionTrigger;
+import org.apache.openoffice.ooxml.parser.action.IAction;
+
+public class PresentationImporter
+{
+ public PresentationModel importModel (final Part aPart)
+ {
+ final PresentationModel aModel = new PresentationModel();
+ final Parser aParser = CreateParser(
+ aPart.getStream(),
+ aModel,
+ aPart);
+ aParser.Parse();
+ return aModel;
+ }
+
+
+
+ private Parser CreateParser (
+ final InputStream aStream,
+ final PresentationModel aModel,
+ final Part aPart)
+ {
+ final Parser aParser = ParserFactory.getParser(
+ ContentType.PmlDocument,
+ aStream,
+ new Vector<String>());
+
+ aParser.GetActionManager().AddElementStartAction(
+ "p06_CT_SlideIdListEntry",
+ new IAction()
+ {
+ @Override public void Run(ActionTrigger eTrigger,
+ ElementContext aContext, String sText,
+ Location aStartLocation, Location aEndLocation)
+ {
+ final String aReferenceId = aContext.GetAttributes().GetRawAttributeValue("r06_id");
+
+ aModel.GetSlideManager().GetSlideForPart(
+ aPart.getPartById(aReferenceId));
+
+ System.out.println(aReferenceId);
+ }
+ });
+
+ return aParser;
+ }
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationModel.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationModel.java
new file mode 100755
index 000000000000..b111ad58b382
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/PresentationModel.java
@@ -0,0 +1,43 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+public class PresentationModel
+{
+ PresentationModel()
+ {
+ maSlideManager = new SlideManager();
+ }
+
+
+
+
+ public SlideManager GetSlideManager()
+ {
+ return maSlideManager;
+ }
+
+
+
+
+ private final SlideManager maSlideManager;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/Slide.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/Slide.java
new file mode 100755
index 000000000000..3dc09db12cfd
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/Slide.java
@@ -0,0 +1,56 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+public class Slide
+{
+ Slide (
+ final String sSlideName,
+ final int nShapeCount)
+ {
+ msSlideName = sSlideName;
+ mnShapeCount = nShapeCount;
+ }
+
+
+
+
+ public String getSlideName ()
+ {
+ return msSlideName;
+ }
+
+
+
+
+ @Override
+ public String toString ()
+ {
+ return msSlideName +" has "+mnShapeCount+" shapes";
+ }
+
+
+
+
+ private final String msSlideName;
+ private final int mnShapeCount;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideManager.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideManager.java
new file mode 100755
index 000000000000..153ac3986ec6
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideManager.java
@@ -0,0 +1,77 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.PartName;
+
+public class SlideManager
+{
+ SlideManager ()
+ {
+ maSlides = new Vector<>();
+ maPartNameToSlideMap = new TreeMap<>();
+ }
+
+
+
+ public void AddSlide (
+ final PartName aName,
+ final Slide aSlide)
+ {
+ maSlides.add(aSlide);
+ maPartNameToSlideMap.put(aName, aSlide);
+ }
+
+
+
+
+ public Iterable<Slide> GetSlides ()
+ {
+ return maSlides;
+ }
+
+
+
+
+ public Slide GetSlideForPart (final Part aPart)
+ {
+ Slide aSlide = maPartNameToSlideMap.get(aPart.getPartName());
+ if (aSlide == null)
+ {
+ aSlide = new SlideParser(aPart).ParseSlide(maSlides.size());
+
+ AddSlide(aPart.getPartName(), aSlide);
+ }
+ return aSlide;
+ }
+
+
+
+
+ private final Vector<Slide> maSlides;
+ private final Map<PartName,Slide> maPartNameToSlideMap;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideParser.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideParser.java
new file mode 100755
index 000000000000..82dfedbdfcd2
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/content/SlideParser.java
@@ -0,0 +1,80 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.content;
+
+import java.util.Vector;
+
+import javax.xml.stream.Location;
+
+import org.apache.openoffice.ooxml.framework.part.Part;
+import org.apache.openoffice.ooxml.framework.part.parser.ParserFactory;
+import org.apache.openoffice.ooxml.parser.ElementContext;
+import org.apache.openoffice.ooxml.parser.Parser;
+import org.apache.openoffice.ooxml.parser.action.ActionTrigger;
+import org.apache.openoffice.ooxml.parser.action.IAction;
+
+public class SlideParser
+{
+ SlideParser (final Part aPart)
+ {
+ maParser = ParserFactory.getParser(
+ aPart.getContentType(),
+ aPart.getStream(),
+ new Vector<String>());
+ mnShapeCount = 0;
+
+ maParser.GetActionManager().AddElementStartAction(
+ "p06_CT_Shape",
+ new IAction()
+ {
+ @Override public void Run(ActionTrigger eTrigger, ElementContext aContext,
+ String sText, Location aStartLocation, Location aEndLocation)
+ {
+ SlideParser.this.IncreaseShapeCount();
+ }
+ });
+ }
+
+
+
+
+ Slide ParseSlide (final int nSlideIndex)
+ {
+ maParser.Parse();
+ final Slide aSlide = new Slide("slide "+nSlideIndex, mnShapeCount);
+ return aSlide;
+ }
+
+
+
+
+ private void IncreaseShapeCount ()
+ {
+ ++mnShapeCount;
+ }
+
+
+
+
+ private final Parser maParser;
+ private int mnShapeCount;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/DocumentFactory.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/DocumentFactory.java
new file mode 100755
index 000000000000..11f2ac566945
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/DocumentFactory.java
@@ -0,0 +1,127 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.util.Stack;
+
+
+public class DocumentFactory<TokenType>
+{
+ interface IRepaintTarget
+ {
+ void RequestRepaint();
+ }
+
+
+
+
+ DocumentFactory (
+ final LineContainer<TokenType> aLines,
+ final IRepaintTarget aRepaintTarget)
+ {
+ maLines = aLines;
+ maRepaintTarget = aRepaintTarget;
+ mbIsGroupBeginPending = false;
+ maGroupStartStack = new Stack<Run<TokenType>>();
+ maLastRun = null;
+ maCurrentGroup = null;
+ StartNewLine();
+ }
+
+
+
+
+ public void AddText (
+ final String sText,
+ final TokenType eTokenType,
+ final Style aStyle,
+ final int nOffset)
+ {
+ final Run<TokenType> aRun = new Run<TokenType>(sText, eTokenType, aStyle, nOffset);
+ synchronized(maLines)
+ {
+ maCurrentLine.AddRun(aRun);
+ if (sText.endsWith("\n"))
+ StartNewLine();
+ }
+
+ if (mbIsGroupBeginPending)
+ {
+ maGroupStartStack.push(maCurrentGroup);
+ aRun.SetGroupParent(maCurrentGroup);
+ maCurrentGroup = aRun;
+ mbIsGroupBeginPending = false;
+ }
+ else if (maCurrentGroup != null)
+ aRun.SetGroupParent(maCurrentGroup);
+ maLastRun = aRun;
+
+ maRepaintTarget.RequestRepaint();
+ }
+
+
+
+
+ public void FinishText ()
+ {
+ StartNewLine();
+ }
+
+
+
+
+ public void BeginGroup()
+ {
+ mbIsGroupBeginPending = true;
+ }
+
+
+
+
+ public void EndGroup ()
+ {
+ maCurrentGroup.SetGroupEnd(maLastRun);
+ maCurrentGroup = maGroupStartStack.pop();
+ }
+
+
+
+
+
+ private void StartNewLine ()
+ {
+ if (maCurrentLine != null)
+ maLines.AddLine(maCurrentLine);
+ maCurrentLine = new Line<TokenType>();
+ }
+
+
+
+
+ private final LineContainer<TokenType> maLines;
+ private final IRepaintTarget maRepaintTarget;
+ private Line<TokenType> maCurrentLine;
+ private boolean mbIsGroupBeginPending;
+ private Stack<Run<TokenType>> maGroupStartStack;
+ private Run<TokenType> maLastRun;
+ private Run<TokenType> maCurrentGroup;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/FormatState.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/FormatState.java
new file mode 100755
index 000000000000..071ac1426472
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/FormatState.java
@@ -0,0 +1,61 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Dimension;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class FormatState<TokenType>
+ implements Iterable<Line<TokenType>>
+{
+ FormatState (
+ final Dimension aBoundingSize,
+ final Vector<Line<TokenType>> aVisibleLines)
+ {
+ maBoundingSize = aBoundingSize;
+ maVisibleLines = aVisibleLines;
+ }
+
+
+
+
+ public Dimension GetTextBoundingSize()
+ {
+ return maBoundingSize;
+ }
+
+
+
+
+ @Override
+ public Iterator<Line<TokenType>> iterator ()
+ {
+ return maVisibleLines.iterator();
+ }
+
+
+
+
+ private final Dimension maBoundingSize;
+ private final Vector<Line<TokenType>> maVisibleLines;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Formatter.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Formatter.java
new file mode 100755
index 000000000000..605aeab38950
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Formatter.java
@@ -0,0 +1,93 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.util.Vector;
+
+public class Formatter<TokenType>
+{
+ public Formatter ()
+ {
+ mnLastFormattedLine = -1;
+ mnWidth = 0;
+ mnHeight = 0;
+ }
+
+
+
+
+ public FormatState<TokenType> FormatText (
+ final Graphics2D aG2,
+ final LineContainer<TokenType> aLines)
+ {
+ FormatLines(aG2, aLines);
+
+ final double nTop = aG2.getClipBounds().getMinY();
+ final double nBottom = aG2.getClipBounds().getMaxY();
+ final Vector<Line<TokenType>> aVisibleLines = new Vector<>();
+ for (final Line<TokenType> aLine : aLines.GetLines())
+ {
+ if (aLine.Overlaps(nTop, nBottom))
+ {
+ // Line is (partially) visible.
+ aVisibleLines.add(aLine);
+ }
+ }
+
+ return new FormatState<TokenType>(
+ new Dimension(mnWidth,mnHeight),
+ aVisibleLines);
+ }
+
+
+
+
+ private void FormatLines (
+ final Graphics2D aG2,
+ final LineContainer<TokenType> aLines)
+ {
+ for (int nIndex=mnLastFormattedLine+1,nCount=aLines.GetLineCount(); nIndex<nCount; ++nIndex)
+ {
+ final Line<TokenType> aLine = aLines.GetLine(nIndex);
+ final int nY;
+ if (nIndex > 0)
+ nY = aLines.GetLine(nIndex-1).GetBottom();
+ else
+ nY = 0;
+ aLine.Format(aG2, nY);
+ if (aLine.GetWidth() > mnWidth)
+ mnWidth = aLine.GetWidth();
+ if (aLine.GetBottom() > mnHeight)
+ mnHeight = aLine.GetBottom();
+ }
+ mnLastFormattedLine = aLines.GetLineCount()-1;
+ }
+
+
+
+
+ private int mnLastFormattedLine;
+ private int mnWidth;
+ private int mnHeight;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Line.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Line.java
new file mode 100755
index 000000000000..c39e24bf6ed3
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Line.java
@@ -0,0 +1,239 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Graphics2D;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class Line<TokenType>
+
+ implements Iterable<Run<TokenType>>
+{
+ Line ()
+ {
+ maRuns = new Vector<Run<TokenType>>();
+ mnWidth = -1;
+ mnHeight = -1;
+ mnY = -1;
+ mnStartOffset = -1;
+ mnEndOffset = -1;
+ }
+
+
+
+
+ public void AddRun (final Run<TokenType> aRun)
+ {
+ maRuns.add(aRun);
+ mnWidth += aRun.GetWidth();
+ if (aRun.GetHeight() > mnHeight)
+ mnHeight = aRun.GetHeight();
+ aRun.SetLine(this);
+
+ if (aRun.GetStreamOffset() >= 0)
+ {
+ if (mnStartOffset < 0)
+ mnStartOffset = aRun.GetStreamOffset();
+
+ if (mnEndOffset < aRun.GetStreamEndOffset())
+ mnEndOffset = aRun.GetStreamEndOffset();
+ }
+ }
+
+
+
+
+ public void Format (
+ final Graphics2D aG2,
+ final int nY)
+ {
+ mnY = nY;
+
+ mnWidth = 0;
+ mnHeight = 0;
+ for (final Run<TokenType> aRun : maRuns)
+ {
+ aRun.Format(aG2);
+ mnWidth += aRun.GetWidth();
+ if (mnHeight < aRun.GetHeight())
+ mnHeight = aRun.GetHeight();
+ }
+ }
+
+
+
+
+ public int GetWidth ()
+ {
+ return mnWidth;
+ }
+
+
+
+
+ public int GetHeight ()
+ {
+ return mnHeight;
+ }
+
+
+
+
+ public int GetTop ()
+ {
+ return mnY;
+ }
+
+
+
+
+ public int GetBottom ()
+ {
+ return mnY + mnHeight;
+ }
+
+
+
+
+ public boolean Overlaps (
+ final double nTop,
+ final double nBottom)
+ {
+ return mnY<=nBottom && mnY+mnHeight>nTop;
+ }
+
+
+
+
+ public boolean Contains (final int nY)
+ {
+ return nY>=mnY && nY<mnY+mnHeight;
+ }
+
+
+
+
+ @Override
+ public Iterator<Run<TokenType>> iterator()
+ {
+ return maRuns.iterator();
+ }
+
+
+
+
+ public Run<TokenType> GetRunForX (final int nX)
+ {
+ int nRunX = 0;
+ for (final Run<TokenType> aRun : maRuns)
+ {
+ final int nRunWidth = aRun.GetWidth();
+ final int nRight = nRunX + nRunWidth;
+ if (nX>=nRunX && nX<nRight)
+ return aRun;
+ nRunX = nRight;
+ }
+ return null;
+ }
+
+
+
+
+ public Run<TokenType> GetRunForOffset (int nOffset)
+ {
+ for (int nIndex=0; nIndex<maRuns.size(); ++nIndex)
+ {
+ final Run<TokenType> aRun = maRuns.get(nIndex);
+ final int nRunOffset = aRun.GetStreamOffset();
+ if (nRunOffset >= 0)
+ if (nRunOffset<=nOffset && nOffset<=aRun.GetStreamEndOffset())
+ return aRun;
+ }
+ return null;
+ }
+
+
+
+
+ public Iterable<Run<TokenType>> GetRunsForOffsets (
+ final int nStartOffset,
+ final int nEndOffset)
+ {
+ final Vector<Run<TokenType>> aRuns = new Vector<>();
+
+ for (final Run<TokenType> aRun : maRuns)
+ {
+ if (aRun.GetStreamOffset() >= nEndOffset)
+ break;
+ else if (aRun.GetStreamEndOffset()<nStartOffset)
+ continue;
+ else
+ aRuns.add(aRun);
+ }
+
+ return aRuns;
+ }
+
+
+
+
+ public int GetStartOffset()
+ {
+ return mnStartOffset;
+ }
+
+
+
+
+ public int GetEndOffset ()
+ {
+ return mnEndOffset;
+ }
+
+
+
+
+ public boolean ContainsOffset (final int nOffset)
+ {
+ return mnStartOffset<=nOffset && nOffset<mnEndOffset;
+ }
+
+
+
+
+ @Override
+ public String toString ()
+ {
+ return String.format("line of %d runs: %s", maRuns.size(), maRuns.toString());
+ }
+
+
+
+
+ private final Vector<Run<TokenType>> maRuns;
+ private int mnY;
+ private int mnWidth;
+ private int mnHeight;
+ private int mnStartOffset;
+ private int mnEndOffset;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/LineContainer.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/LineContainer.java
new file mode 100755
index 000000000000..c791fb201ec8
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/LineContainer.java
@@ -0,0 +1,194 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.util.Vector;
+
+public class LineContainer<TokenType>
+{
+ LineContainer ()
+ {
+ maLines = new Vector<>();
+ }
+
+
+
+
+ boolean IsLineInGroup (
+ final Line<TokenType> aLine,
+ final Run<TokenType> aGroup)
+ {
+ if (aGroup == null)
+ return false;
+
+ final Line<TokenType> aStartLine = aGroup.GetLine();
+ if (aLine.GetTop() < aStartLine.GetTop())
+ return false;
+ final Line<TokenType> aEndLine = aGroup.GetGroupEnd().GetLine();
+ if (aLine.GetTop() > aEndLine.GetTop())
+ return false;
+
+ return true;
+ }
+
+
+
+
+ Line<TokenType> GetLineForY (final int nY)
+ {
+ int nMin = 0;
+ int nMax = maLines.size()-1;
+ if (nMin <= nMax)
+ {
+ while (nMin < nMax-1)
+ {
+ final int nMed = (nMax+nMin)/2;
+ if (nY < maLines.get(nMed).GetTop())
+ nMax = nMed;
+ else
+ nMin = nMed;
+ }
+ for (int nIndex=nMin; nIndex<=nMax; ++nIndex)
+ if (maLines.get(nIndex).Contains(nY))
+ return maLines.get(nIndex);
+ }
+ return null;
+ }
+
+
+
+
+ public Line<TokenType> GetLineForOffset (final int nOffset)
+ {
+ final int nLineIndex = GetLineIndexForOffset(nOffset, 0);
+ if (nLineIndex < 0)
+ return null;
+ else
+ return maLines.get(nLineIndex);
+
+ }
+
+
+
+
+ public Iterable<Line<TokenType>> GetLinesForOffsets (
+ final int nStartOffset,
+ final int nEndOffset)
+ {
+ final Vector<Line<TokenType>> aLines = new Vector<>();
+
+ final int nStartLineIndex = GetLineIndexForOffset(nStartOffset, -1);
+ final int nEndLineIndex = GetLineIndexForOffset(nEndOffset, +1);
+ if (nStartLineIndex >= 0)
+ {
+ if (nEndLineIndex < 0)
+ aLines.add(maLines.get(nStartLineIndex));
+ else
+ for (int nIndex=nStartLineIndex; nIndex<=nEndLineIndex; ++nIndex)
+ aLines.add(maLines.get(nIndex));
+ }
+ return aLines;
+ }
+
+
+
+
+ public int GetLineCount()
+ {
+ return maLines.size();
+ }
+
+
+
+
+ public Line<TokenType> GetLine (final int nIndex)
+ {
+ return maLines.get(nIndex);
+ }
+
+
+
+
+ public Iterable<Line<TokenType>> GetLines ()
+ {
+ return maLines;
+ }
+
+
+
+
+ public void AddLine (final Line<TokenType> aLine)
+ {
+ maLines.add(aLine);
+ }
+
+
+
+
+ /** Return the index of the line that contains the given offset.
+ * When there is no line that contains the line that look at the bias
+ * to return the previous or next line.
+ */
+ private int GetLineIndexForOffset (
+ final int nOffset,
+ final int nBias)
+ {
+ int nMinIndex = 0;
+ int nMaxIndex = maLines.size()-1;
+ while (nMinIndex < nMaxIndex-1)
+ {
+ final int nMedIndex = (nMinIndex + nMaxIndex) / 2;
+ if (maLines.get(nMedIndex).GetEndOffset() <= nOffset)
+ nMinIndex = nMedIndex;
+ else
+ nMaxIndex = nMedIndex;
+ }
+ for (int nIndex=nMinIndex; nIndex<=nMaxIndex; ++nIndex)
+ {
+ if (maLines.get(nIndex).ContainsOffset(nOffset))
+ return nIndex;
+ }
+ if (nBias < 0)
+ {
+ for (int nIndex=nMinIndex; nIndex<=nMaxIndex; ++nIndex)
+ {
+ if (maLines.get(nIndex).GetStartOffset() > nOffset)
+ return nIndex;
+ }
+ }
+ else if (nBias > 0)
+ {
+ for (int nIndex=nMaxIndex; nIndex>=nMinIndex; ++nIndex)
+ {
+ if (maLines.get(nIndex).GetEndOffset() < nOffset)
+ return nIndex;
+ }
+ }
+
+ return -1;
+ }
+
+
+
+
+ private final Vector<Line<TokenType>> maLines;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Run.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Run.java
new file mode 100755
index 000000000000..ad2677efcb77
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Run.java
@@ -0,0 +1,249 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+
+public class Run<TokenType>
+{
+ Run (
+ final String sText,
+ final TokenType eTokenType,
+ final Style aStyle,
+ final int nOffset)
+ {
+ msText = sText;
+ meTokenType = eTokenType;
+ maStyle = aStyle!=null ? aStyle : Style.DefaultStyle;
+ mnStreamOffset = nOffset;
+
+ mnWidth = -1;
+ mnHeight = -1;
+ mnOffset = nOffset;
+ maParent = null;
+ maGroupEnd = null;
+ maLine = null;
+ }
+
+
+
+
+ public void Format (
+ final Graphics2D aG2)
+ {
+ final FontMetrics aMetrics = aG2.getFontMetrics(maStyle.GetFont());
+ mnWidth = aMetrics.stringWidth(msText);
+ mnHeight = aMetrics.getHeight();
+ mnOffset = -aMetrics.getDescent();
+ }
+
+
+
+
+ public void Paint (
+ final Graphics2D aG2,
+ final int nX,
+ final int nY,
+ final Color aBackgroundColor)
+ {
+ maStyle.Set(aG2);
+
+ if (mnWidth < 0)
+ {
+ mnWidth = aG2.getFontMetrics().stringWidth(msText);
+ mnHeight = aG2.getFontMetrics().getHeight();
+ }
+
+ if (aBackgroundColor != null)
+ {
+ final Color aSavedColor = aG2.getColor();
+ aG2.setColor(aBackgroundColor);
+ aG2.fillRect(nX,nY-mnHeight, mnWidth, mnHeight);
+ aG2.setColor(aSavedColor);
+ }
+ aG2.drawString(msText, nX, nY+mnOffset);
+
+ if (msToolTipText != null)
+ {
+ aG2.drawLine(nX, nY-1, nX+mnWidth, nY-1);
+ }
+ }
+
+
+
+
+ public String GetText()
+ {
+ return msText;
+ }
+
+
+
+
+ public Style GetStyle ()
+ {
+ return maStyle;
+ }
+
+
+
+
+ public int GetStreamOffset ()
+ {
+ return mnStreamOffset;
+ }
+
+
+
+
+ public int GetStreamEndOffset ()
+ {
+ return mnStreamOffset + msText.length();
+ }
+
+
+
+
+ public int GetWidth()
+ {
+ return mnWidth;
+ }
+
+
+
+
+ public int GetHeight ()
+ {
+ return mnHeight;
+ }
+
+
+
+
+ public void SetGroupParent (final Run<TokenType> aParent)
+ {
+ maParent = aParent;
+ }
+
+
+
+
+ public void SetGroupEnd (final Run<TokenType> aRun)
+ {
+ maGroupEnd = aRun;
+ }
+
+
+
+
+ public Run<TokenType> GetGroupEnd()
+ {
+ return maGroupEnd;
+ }
+
+
+
+
+ public boolean IsGroup ()
+ {
+ if (maGroupEnd == null)
+ return false;
+ else if (maLine == maGroupEnd.maLine)
+ return true;
+ else
+ return true;
+ }
+
+
+
+
+ public Run<TokenType> GetParent ()
+ {
+ return maParent;
+ }
+
+
+
+
+ public Line<TokenType> GetLine ()
+ {
+ return maLine;
+ }
+
+
+
+
+ public void SetLine (final Line<TokenType> aLine)
+ {
+ maLine = aLine;
+ }
+
+
+
+
+ public void SetToolTipText (final String sText)
+ {
+ msToolTipText = sText;
+ }
+
+
+
+
+ public String GetToolTipText ()
+ {
+ return msToolTipText;
+ }
+
+
+
+
+ public TokenType GetTokenType ()
+ {
+ return meTokenType;
+ }
+
+
+
+
+ @Override
+ public String toString ()
+ {
+ return "run '"+msText+"' @ "+mnOffset;
+ }
+
+
+
+
+ private final String msText;
+ private final TokenType meTokenType;
+ private final Style maStyle;
+ private final int mnStreamOffset;
+ private int mnWidth;
+ private int mnHeight;
+ private int mnOffset;
+ private Run<TokenType> maParent;
+ private Run<TokenType> maGroupEnd;
+ private Line<TokenType> maLine;
+ private String msToolTipText;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/RunRange.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/RunRange.java
new file mode 100755
index 000000000000..2c980a92dd76
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/RunRange.java
@@ -0,0 +1,87 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.util.Vector;
+
+public class RunRange<TokenType>
+{
+ RunRange (final Vector<Run<TokenType>> aRuns)
+ {
+ maRuns = aRuns;
+ }
+
+
+
+
+ public int FindTokens (
+ @SuppressWarnings("unchecked")
+ final TokenType ... eTypeList)
+ {
+ return FindTokens(0, eTypeList);
+ }
+
+
+
+
+ public int FindTokens (
+ final int nFirstIndex,
+ @SuppressWarnings("unchecked")
+ final TokenType ... eTypeList)
+ {
+ for (int nIndex=nFirstIndex; nIndex<maRuns.size()-eTypeList.length; ++nIndex)
+ {
+ boolean bMatches = true;
+ for (int nInnerIndex=0; nInnerIndex<eTypeList.length && bMatches; ++nInnerIndex)
+ if (maRuns.get(nIndex+nInnerIndex).GetTokenType()
+ != eTypeList[nInnerIndex])
+ {
+ bMatches = false;
+ }
+ if (bMatches)
+ return nIndex;
+ }
+
+ return -1;
+ }
+
+
+
+
+ public boolean IsEmpty ()
+ {
+ return maRuns.isEmpty();
+ }
+
+
+
+
+ public Run<TokenType> Get (final int nIndex)
+ {
+ return maRuns.get(nIndex);
+ }
+
+
+
+
+ private final Vector<Run<TokenType>> maRuns;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Style.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Style.java
new file mode 100755
index 000000000000..3f81cd8fb76b
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/Style.java
@@ -0,0 +1,109 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+
+import javax.swing.UIManager;
+
+public class Style
+{
+ public Style ()
+ {
+ maForegroundColor = Color.BLACK;
+ if (DefaultFont == null)
+ DefaultFont = UIManager.getDefaults().getFont("TextField.font");
+ maFont = DefaultFont;
+ }
+
+
+
+
+ public void Set(Graphics2D aG2)
+ {
+ aG2.setColor(maForegroundColor);
+ aG2.setFont(maFont);
+ }
+
+
+
+
+ public Style SetForegroundColor (final Color aColor)
+ {
+ maForegroundColor = aColor;
+ return this;
+ }
+
+
+
+
+ public Color GetForegroundColor()
+ {
+ return maForegroundColor;
+ }
+
+
+
+
+ public Style SetBackgroundColor (final Color aColor)
+ {
+ maBackgroundColor = aColor;
+ return this;
+ }
+
+
+
+
+ public Color GetBackgroundColor()
+ {
+ return maBackgroundColor;
+ }
+
+
+
+
+ public Style SetBold()
+ {
+ maFont = maFont.deriveFont(Font.BOLD);
+ return this;
+ }
+
+
+
+
+ public Font GetFont()
+ {
+ return maFont;
+ }
+
+
+
+
+ public static final Style DefaultStyle = new Style();
+ public static Font DefaultFont = null;
+
+ private Color maBackgroundColor;
+ private Color maForegroundColor;
+ private Font maFont;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/TokenView.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/TokenView.java
new file mode 100755
index 000000000000..961524f382b0
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/tokenview/TokenView.java
@@ -0,0 +1,406 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.tokenview;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.UIManager;
+
+/** A simple view of tokenized content.
+ *
+ * Create the content by calling GetDocumentFactory() and using the returned
+ * factory to add tokenized text.
+ */
+@SuppressWarnings("serial")
+public class TokenView<TokenType>
+ extends JPanel
+ implements MouseMotionListener, DocumentFactory.IRepaintTarget, ComponentListener
+{
+ public TokenView ()
+ {
+ maLines = new LineContainer<TokenType>();
+ maFormatter = new Formatter<TokenType>();
+
+ addMouseMotionListener(this);
+ addComponentListener(this);
+ }
+
+
+
+
+ @Override
+ public void paintComponent (final Graphics aGraphics)
+ {
+ super.paintComponent(aGraphics);
+
+ final Graphics2D aG2 = (Graphics2D)aGraphics;
+ aG2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+
+ final FormatState<TokenType> aState;
+ synchronized(maLines)
+ {
+ aState = maFormatter.FormatText(aG2, maLines);
+ }
+ setPreferredSize(aState.GetTextBoundingSize());
+
+ for (final Line<TokenType> aLine : aState)
+ {
+ PaintLineHighlight(aG2, aLine);
+ PaintLineNumber(aG2, aLine);
+
+ int nX = mnTextStart;
+ for (final Run<TokenType> aRun : aLine)
+ {
+ final Color aRunColor;
+ if (aRun == maRunUnderMouse)
+ aRunColor = maRunUnderMouseColor;
+ else if (aRun == maHighlightedErrorRun)
+ aRunColor = maErrorHighlightColor;
+ else
+ aRunColor = null;
+ aRun.Paint(
+ (Graphics2D)aGraphics,
+ nX,
+ aLine.GetBottom(),
+ aRunColor);
+
+ nX += aRun.GetWidth();
+ }
+ }
+
+ aGraphics.setColor(maSeparatorColor);
+
+ final int nTop = aGraphics.getClipBounds().y;
+ final int nBottom = aGraphics.getClipBounds().y+aGraphics.getClipBounds().height;
+ aGraphics.drawLine(
+ mnBarPosition0,
+ nTop,
+ mnBarPosition0,
+ nBottom);
+ aGraphics.drawLine(
+ mnBarPosition1,
+ nTop,
+ mnBarPosition1,
+ nBottom);
+ }
+
+
+
+
+ /** Paint a line with a highlight.
+ * There are different kinds of highlight:
+ * - the current line
+ * - one of three groups of enclosing parent elements
+ */
+ private void PaintLineHighlight (
+ final Graphics2D aG2,
+ final Line<TokenType> aLine)
+ {
+ final Color aBackgroundColor;
+ if (aLine == maHighlightedLine)
+ aBackgroundColor = maHighlightColor;
+ else
+ aBackgroundColor = maBackgroundColor;
+
+ final Color aBarColor;
+ if (maLines.IsLineInGroup(aLine, maHighlightedGroup0))
+ aBarColor = maGroupHighlightColor0;
+ else if (maLines.IsLineInGroup(aLine, maHighlightedGroup1))
+ aBarColor = maGroupHighlightColor1;
+ else if (maLines.IsLineInGroup(aLine, maHighlightedGroup2))
+ aBarColor = maGroupHighlightColor2;
+ else
+ aBarColor = maBackgroundColor;
+
+ aG2.setColor(aBarColor);
+ aG2.fillRect(
+ 0,
+ aLine.GetTop(),
+ mnLeftBarWidth,
+ aLine.GetHeight());
+
+ aG2.setColor(aBackgroundColor);
+ aG2.fillRect(
+ mnLeftBarWidth,
+ aLine.GetTop(),
+ getWidth() - mnLeftBarWidth,
+ aLine.GetHeight());
+ }
+
+
+
+
+ private void PaintLineNumber (
+ final Graphics2D aG2,
+ final Line<TokenType> aLine)
+ {
+ final String sNumber = Integer.toString(aLine.GetStartOffset());
+ final FontMetrics aMetrics = aG2.getFontMetrics();
+ final int nWidth = aMetrics.stringWidth(sNumber);
+ final int nHeight = aMetrics.getHeight();
+
+ aG2.setColor(maLineNumberColor);
+ aG2.setFont(maLineNumberFont);
+ aG2.drawString(
+ sNumber,
+ mnBarPosition0+1 + mnNumberBarWidth-nWidth,
+ aLine.GetBottom() - (aLine.GetHeight()-nHeight)/2 - aMetrics.getDescent());
+ }
+
+
+
+
+ @Override
+ public void mouseDragged (final MouseEvent aEvent)
+ {
+ }
+
+
+
+
+ @Override
+ public void mouseMoved (final MouseEvent aEvent)
+ {
+ final Line<TokenType> aLine = maLines.GetLineForY(aEvent.getY());
+ if (aLine != null)
+ {
+ UpdateHighlightedLine(aLine);
+ final Run<TokenType> aRun = aLine.GetRunForX(aEvent.getX() - mnTextStart);
+ SetRunUnderMouse(aRun);
+ }
+ }
+
+
+
+
+ private void UpdateHighlightedLine (final Line<TokenType> aLine)
+ {
+ HighlightLine(aLine);
+
+ final Iterator<Run<TokenType>> aRunIterator = aLine.iterator();
+ if (aRunIterator.hasNext())
+ {
+ final Run<TokenType> aRun = aRunIterator.next();
+ if (aRun.IsGroup())
+ HighlightGroup(aRun);
+ else
+ HighlightGroup(aRun.GetParent());
+ }
+ }
+
+
+
+
+ @Override
+ public void RequestRepaint()
+ {
+ repaint();
+ }
+
+
+
+
+ public DocumentFactory<TokenType> GetDocumentFactory()
+ {
+ return new DocumentFactory<TokenType>(maLines, this);
+ }
+
+
+
+
+ private void HighlightLine (final Line<TokenType> aLine)
+ {
+ if (aLine != maHighlightedLine)
+ {
+ maHighlightedLine = aLine;
+ repaint();
+ }
+ }
+
+
+
+
+ private void HighlightGroup (final Run<TokenType> aRun)
+ {
+ if (maHighlightedGroup0 != aRun)
+ {
+ maHighlightedGroup0 = aRun;
+
+ if (aRun != null)
+ {
+ final Run<TokenType> aGroup1 = aRun.GetParent();
+ maHighlightedGroup1 = aGroup1;
+
+ if (aGroup1 != null)
+ {
+ final Run<TokenType> aGroup2 = aGroup1.GetParent();
+ maHighlightedGroup2 = aGroup2;
+ }
+ }
+ repaint();
+ }
+ }
+
+
+
+
+ @Override
+ public void componentHidden(ComponentEvent e)
+ {
+ }
+
+
+
+
+ @Override
+ public void componentMoved (final ComponentEvent aEvent)
+ {
+ final Point aPoint = getMousePosition();
+ if (aPoint != null)
+ UpdateHighlightedLine(maLines.GetLineForY(aPoint.y));
+ }
+
+
+
+
+ @Override
+ public void componentResized(ComponentEvent e)
+ {
+ }
+
+
+
+
+ @Override
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+
+
+
+ public Run<TokenType> GetRun (final int nOffset)
+ {
+ final Line<TokenType> aLine = maLines.GetLineForOffset(nOffset);
+ if (aLine != null)
+ return aLine.GetRunForOffset(nOffset);
+ else
+ return null;
+ }
+
+
+
+
+ /** Return all runs that completely or partially lie in the range from
+ * start offset (including) and end offset (excluding).
+ */
+ public RunRange<TokenType> GetRuns (final int nStartOffset, final int nEndOffset)
+ {
+ final Vector<Run<TokenType>> aRuns = new Vector<>();
+
+ for (final Line<TokenType> aLine : maLines.GetLinesForOffsets(nStartOffset, nEndOffset))
+ for (final Run<TokenType> aRun : aLine.GetRunsForOffsets(nStartOffset, nEndOffset))
+ aRuns.add(aRun);
+
+ return new RunRange<TokenType>(aRuns);
+ }
+
+
+
+
+ public void MarkError (final Run<TokenType> aRun)
+ {
+ maHighlightedErrorRun = aRun;
+ repaint();
+ }
+
+
+
+
+ public void ShowRun (final Run<TokenType> aRun)
+ {
+ final Container aComponent = getParent().getParent();
+ if (aComponent instanceof JScrollPane)
+ ((JScrollPane)aComponent).getVerticalScrollBar().setValue(
+ aRun.GetLine().GetTop());
+ }
+
+
+
+
+ private void SetRunUnderMouse (final Run<TokenType> aRun)
+ {
+ if (maRunUnderMouse != aRun)
+ {
+ maRunUnderMouse = aRun;
+ if (maRunUnderMouse != null)
+ setToolTipText(maRunUnderMouse.GetToolTipText());
+ else
+ setToolTipText(null);
+ repaint();
+ }
+ }
+
+
+
+
+ private final LineContainer<TokenType> maLines;
+ private final Formatter<TokenType> maFormatter;
+ private Line<TokenType> maHighlightedLine;
+ private Run<TokenType> maHighlightedGroup0;
+ private Run<TokenType> maHighlightedGroup1;
+ private Run<TokenType> maHighlightedGroup2;
+ private Run<TokenType> maHighlightedErrorRun;
+ private Run<TokenType> maRunUnderMouse;
+
+ private final static int mnLeftBarWidth = 10;
+ private final static int mnNumberBarWidth = 30;
+ private final static int mnBarPosition0 = mnLeftBarWidth;
+ private final static int mnBarPosition1 = mnBarPosition0 + mnNumberBarWidth ;
+ private final static int mnTextStart = mnBarPosition1 + 2;
+ private final static Color maSeparatorColor = Color.GRAY;
+ private final static Color maBackgroundColor = Color.WHITE;
+ private final static Color maHighlightColor = new Color(0xB0E0E6); // Powder Blue
+ private final static Color maGroupHighlightColor0 = new Color(0x32CD32); // Lime Green
+ private final static Color maGroupHighlightColor1 = new Color(0x90EE90); // Light Green
+ private final static Color maGroupHighlightColor2 = new Color(0xbbFfbb);
+ private final static Color maErrorHighlightColor = new Color(0xff3020);
+ private final static Color maLineNumberColor = new Color(0x808080);
+ private final static Color maRunUnderMouseColor = maGroupHighlightColor2;
+ private final static Font maLineNumberFont = UIManager.getDefaults().getFont("TextField.font").deriveFont(9.0f);
+
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/DocumentTokenFormatter.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/DocumentTokenFormatter.java
new file mode 100755
index 000000000000..e01f78afcac0
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/DocumentTokenFormatter.java
@@ -0,0 +1,399 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xml;
+
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.openoffice.ooxml.viewer.tokenview.DocumentFactory;
+import org.apache.openoffice.ooxml.viewer.tokenview.Style;
+import org.apache.openoffice.ooxml.viewer.tokenview.TokenView;
+
+public class DocumentTokenFormatter
+{
+ DocumentTokenFormatter (
+ final XMLScanner aScanner,
+ final TokenView<TokenType> aView)
+ {
+ maScanner = aScanner;
+ maView = aView.GetDocumentFactory();
+
+ maTagStartEndStyle = new Style().SetForegroundColor(new Color(0x87CEFA)); // Light Sky Blue
+ maNamespaceNameStyle = new Style().SetForegroundColor(new Color(0x7B68EE)); // Medium Slate Blue
+ maIdentifierStyle = new Style()
+ .SetForegroundColor(new Color(0x7B68EE)) // Medium Slate Blue
+ .SetBold();
+ maTextStyle = new Style().SetForegroundColor(new Color(0xF08080)); // Light Coral
+ maAttributeValueStyle = new Style().SetForegroundColor(new Color(0xFFA07A)); // Light Salmon
+
+ msIndentation = "";
+
+ maNamespaceMap = new HashMap<String,String>();
+ }
+
+
+
+
+ public void Parse ()
+ {
+ try
+ {
+ ParseIntro();
+ AppendText("\n", TokenType.WHITESPACE, null, -1);
+ while (true)
+ {
+ switch (maScanner.Peek().Type)
+ {
+ case EOF:
+ return;
+
+ case TAG_START:
+ case END_TAG_START:
+ ParseTag();
+ AppendText("\n", TokenType.WHITESPACE, null, -1);
+ break;
+
+ default:
+ ParseText();
+ }
+ }
+ }
+ catch(final Exception aException)
+ {
+ aException.printStackTrace();
+ }
+ maView.FinishText();
+ }
+
+
+
+
+ Map<String,String> GetNamespaceMap ()
+ {
+ return maNamespaceMap;
+ }
+
+
+
+
+ private void ParseIntro ()
+ {
+ final Token aStartToken = maScanner.Next();
+ ExpectToken(aStartToken, TokenType.INTRO_START);
+ ShowToken(aStartToken);
+
+ ParseTagContent();
+
+ final Token aEndToken = maScanner.Next();
+ ExpectToken(aEndToken, TokenType.INTRO_END);
+ ShowToken(aEndToken);
+ }
+
+
+
+
+ private void ParseTag ()
+ {
+ final Token aStartToken = maScanner.Next();
+ ExpectToken(aStartToken, TokenType.TAG_START, TokenType.END_TAG_START);
+ if (aStartToken.Type == TokenType.TAG_START)
+ maView.BeginGroup();
+ if (aStartToken.Type == TokenType.END_TAG_START)
+ DecreaseIndentation();
+ ShowToken(aStartToken);
+
+ ParseTagContent();
+
+ final Token aEndToken = maScanner.Next();
+ if (aStartToken.Type == TokenType.TAG_START)
+ ExpectToken(aEndToken, TokenType.TAG_END, TokenType.ELEMENT_END);
+ else
+ ExpectToken(aEndToken, TokenType.TAG_END);
+ ShowToken(aEndToken);
+
+ if (aStartToken.Type != TokenType.END_TAG_START
+ && aEndToken.Type != TokenType.ELEMENT_END)
+ {
+ IncreaseIndentation();
+ }
+ else
+ {
+ maView.EndGroup();
+ }
+ }
+
+
+
+
+ private void ParseTagContent ()
+ {
+ ParseQualifiedName();
+
+ if (maScanner.Peek().Type != TokenType.IDENTIFIER)
+ return;
+
+ IncreaseIndentation();
+ while (true)
+ {
+ final Token aToken = maScanner.Peek();
+ if (aToken.Type != TokenType.IDENTIFIER)
+ break;
+
+ if (mbStartNewLineBeforeEachAttribute
+ || mbStartNewLineBeforeNamespaceDefinition && aToken.Text.startsWith("xmlns"))
+ {
+ AppendText("\n", TokenType.WHITESPACE, null, -1);
+ AppendText(" ", TokenType.WHITESPACE, null, -1);
+ }
+ else
+ {
+ AppendText(" ", TokenType.WHITESPACE, null, -1);
+ }
+
+ ParseQualifiedName();
+ final Token aAssignToken = maScanner.Next();
+ ExpectToken(aAssignToken, TokenType.ATTRIBUTE_DEFINE);
+ ShowToken(aAssignToken);
+
+ final Token aValueToken = maScanner.Next();
+ ExpectToken(aValueToken, TokenType.ATTRIBUTE_VALUE);
+ ShowToken(aValueToken, maAttributeValueStyle);
+
+ if (msLastNamespaceName.equals("xmlns"))
+ SaveNamespaceDefinition(msLastName, StripValueQuotes(aValueToken.Text));
+ }
+ DecreaseIndentation();
+ }
+
+
+
+
+ private void ParseQualifiedName ()
+ {
+ final Token aNameToken = maScanner.Next();
+ ExpectToken(aNameToken, TokenType.IDENTIFIER);
+ if (maScanner.Peek().Type == TokenType.COLON)
+ {
+ final Token aSeparatorToken = maScanner.Next();
+ final Token aSecondNameToken = maScanner.Next();
+ ExpectToken(aSecondNameToken, TokenType.IDENTIFIER);
+ ShowToken(aNameToken, maNamespaceNameStyle);
+ ShowToken(aSeparatorToken);
+ ShowToken(aSecondNameToken, maIdentifierStyle);
+
+ msLastNamespaceName = aNameToken.Text;
+ msLastName = aSecondNameToken.Text;
+ }
+ else
+ {
+ ShowToken(aNameToken, maIdentifierStyle);
+
+ msLastNamespaceName = "";
+ msLastName = aNameToken.Text;
+ }
+ }
+
+
+
+
+ private void ParseText ()
+ {
+ final Token aTextToken = maScanner.Next();
+ ExpectToken(aTextToken, TokenType.TEXT);
+ ShowToken(aTextToken, maTextStyle);
+ AppendText("\n", TokenType.WHITESPACE, null, -1);
+ }
+
+
+
+
+ private TokenType ExpectToken (final Token aToken, final TokenType ... aExcpectedTypes)
+ {
+ for (final TokenType eType : aExcpectedTypes)
+ if (aToken.Type == eType)
+ return eType;
+
+ if (aExcpectedTypes.length == 1)
+ {
+ throw new RuntimeException(
+ String.format(
+ "expected '%s' but got %s",
+ aExcpectedTypes[0].toString(),
+ aToken.toString()));
+ }
+ else
+ {
+ String sList = null;
+ for (final TokenType eType : aExcpectedTypes)
+ {
+ if (sList != null)
+ sList += String.format(", '%s'", eType.toString());
+ else
+ sList = String.format("'%s'", eType.toString());
+ }
+ throw new RuntimeException(
+ String.format(
+ "expected one of %s but got %s",
+ sList,
+ aToken.toString()));
+ }
+ }
+
+
+
+
+ private void ShowToken (final Token aToken)
+ {
+ AppendText(aToken.Text, aToken.Type, GetStyle(aToken.Type), aToken.Offset);
+ }
+
+
+
+
+ private void ShowToken (
+ final Token aToken,
+ final Style aStyle)
+ {
+ AppendText(aToken.Text, aToken.Type, aStyle, aToken.Offset);
+ }
+
+
+
+
+ private void AppendText (
+ final String sText,
+ final TokenType eTokenType,
+ final Style aStyle,
+ final int nOffset)
+ {
+ try
+ {
+ if (mbIsAtBeginningOfLine)
+ {
+ AddText(msIndentation, TokenType.WHITESPACE, aStyle, -1);
+ mbIsAtBeginningOfLine = false;
+ }
+ AddText(sText, eTokenType, aStyle, nOffset);
+ mbIsAtBeginningOfLine = sText.endsWith("\n");
+ }
+ catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+
+
+ private void AddText (
+ final String sText,
+ final TokenType eTokenType,
+ final Style aStyle,
+ final int nOffset)
+ {
+ maView.AddText(sText, eTokenType, aStyle, nOffset);
+ }
+
+
+
+
+ private void IncreaseIndentation ()
+ {
+ msIndentation += " ";
+ }
+
+
+
+
+ private void DecreaseIndentation ()
+ {
+ if ( ! msIndentation.isEmpty())
+ msIndentation = msIndentation.substring(4);
+ }
+
+
+
+
+ private Style GetStyle (final TokenType eType)
+ {
+ switch(eType)
+ {
+ case TAG_START:
+ case TAG_END:
+ case END_TAG_START:
+ case INTRO_START:
+ case INTRO_END:
+ case ELEMENT_END:
+ return maTagStartEndStyle;
+
+ case IDENTIFIER:
+ return maIdentifierStyle;
+
+ case TEXT:
+ return maTextStyle;
+
+ case ATTRIBUTE_VALUE:
+ return maAttributeValueStyle;
+
+ default:
+ return null;
+ }
+ }
+
+
+
+
+ private String StripValueQuotes (final String sQuotedValue)
+ {
+ final String sValue = sQuotedValue.substring(1, sQuotedValue.length()-1);
+ return sValue;
+ }
+
+
+
+
+ private void SaveNamespaceDefinition (final String sShortName, final String sLongName)
+ {
+ maNamespaceMap.put(sShortName, sLongName);
+ }
+
+
+
+
+ private final XMLScanner maScanner;
+ private final DocumentFactory<TokenType> maView;
+ private final Style maTagStartEndStyle;
+ private final Style maNamespaceNameStyle;
+ private final Style maIdentifierStyle;
+ private final Style maTextStyle;
+ private final Style maAttributeValueStyle;
+ private String msIndentation;
+ private boolean mbIsAtBeginningOfLine;
+
+ private String msLastNamespaceName;
+ private String msLastName;
+ private Map<String,String> maNamespaceMap;
+
+ private final boolean mbStartNewLineBeforeEachAttribute = false;
+ private final boolean mbStartNewLineBeforeNamespaceDefinition = true;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/Token.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/Token.java
new file mode 100755
index 000000000000..6919e8d0957b
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/Token.java
@@ -0,0 +1,51 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xml;
+
+public class Token
+{
+ Token (
+ final TokenType eType,
+ final String sText,
+ final int nOffset)
+ {
+ Type = eType;
+ Text = sText;
+ Offset = nOffset;
+ }
+
+
+
+
+ @Override
+ public String toString ()
+ {
+ return String.format("%s(%s)", Type.toString(), Text);
+ }
+
+
+
+
+ public final TokenType Type;
+ public final String Text;
+ public final int Offset;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/TokenType.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/TokenType.java
new file mode 100755
index 000000000000..ea2c82277dde
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/TokenType.java
@@ -0,0 +1,41 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xml;
+
+public enum TokenType
+{
+ TAG_START,
+ TAG_END,
+ END_TAG_START,
+ INTRO_START,
+ INTRO_END,
+ IDENTIFIER,
+ ELEMENT_END,
+ ATTRIBUTE_DEFINE,
+ ATTRIBUTE_VALUE,
+ COLON,
+ COMMENT_START,
+ COMMENT_END,
+ TEXT,
+ WHITESPACE,
+ EOF
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLScanner.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLScanner.java
new file mode 100755
index 000000000000..7e83c2258492
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLScanner.java
@@ -0,0 +1,438 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Vector;
+
+public class XMLScanner
+{
+ XMLScanner (final InputStream aIn)
+ {
+ Reader aReader = null;
+ try
+ {
+ aReader = new InputStreamReader(aIn, "UTF8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ }
+ maIn = aReader;
+ mnNextCharacter = 0;
+ maTokens = new Vector<Token>();
+ mnTokensReadIndex = 0;
+ mbIsInsideTag = false;
+ maTextBuffer = new int[1024];
+ }
+
+
+
+
+ public Token Next ()
+ {
+ while (maTokens.isEmpty())
+ ProvideToken();
+
+ final Token aToken = maTokens.get(mnTokensReadIndex);
+ ++mnTokensReadIndex;
+ if (mnTokensReadIndex >= maTokens.size())
+ {
+ maTokens.clear();
+ mnTokensReadIndex = 0;
+ }
+ return aToken;
+ }
+
+
+
+
+ public Token Peek()
+ {
+ while (maTokens.isEmpty())
+ ProvideToken();
+
+ return maTokens.get(mnTokensReadIndex);
+ }
+
+
+
+
+ private void ProvideToken ()
+ {
+ final int nC = PeekCharacter();
+ if (nC == -1)
+ {
+ AddToken(TokenType.EOF, "", mnOffset);
+ }
+ else if (mbIsInsideTag)
+ {
+ switch (Character.getType(nC))
+ {
+ case Character.DIRECTIONALITY_WHITESPACE:
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+ ScanWhitespace();
+ break;
+
+ default:
+ switch(nC)
+ {
+ case '?':
+ case '/':
+ case '>':
+ case '=':
+ case ':':
+ case '-':
+ switch(ScanSymbol())
+ {
+ case TAG_END:
+ case INTRO_END:
+ case ELEMENT_END:
+ mbIsInsideTag = false;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '"':
+ ScanQuotedValue();
+ break;
+
+ default:
+ ScanIdentifier();
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (Character.getType(PeekCharacter()))
+ {
+ case Character.DIRECTIONALITY_WHITESPACE:
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+ ScanWhitespace();
+ break;
+
+ default:
+ if (nC == '<')
+ {
+ mbIsInsideTag = true;
+ ScanSymbol();
+ }
+ else
+ {
+ ScanText();
+ }
+ break;
+ }
+ }
+ }
+
+
+
+
+ Token NextNonWhitespaceToken ()
+ {
+ while(true)
+ {
+ final Token aToken = Next();
+ if (aToken.Type != TokenType.WHITESPACE)
+ return aToken;
+ }
+ }
+
+
+
+
+ private TokenType ScanSymbol ()
+ {
+ final int nStartOffset = mnOffset;
+
+ switch (PeekCharacter())
+ {
+ case -1:
+ AddToken(TokenType.EOF, "", nStartOffset);
+ return TokenType.EOF;
+
+ case '<':
+ GetNextCharacter();
+ switch(PeekCharacter())
+ {
+ case '/':
+ GetNextCharacter();
+ AddToken(TokenType.END_TAG_START, "</", nStartOffset);
+ break;
+
+ case '?':
+ GetNextCharacter();
+ AddToken(TokenType.INTRO_START, "<?", nStartOffset);
+ break;
+
+ case '!':
+ GetNextCharacter();
+ if (GetNextCharacter() != '-')
+ throw new RuntimeException("expected '-' after '<!'");
+ if (GetNextCharacter() != '-')
+ throw new RuntimeException("expected '-' after '<!-'");
+ AddToken(TokenType.COMMENT_START, "<!--", nStartOffset);
+ break;
+
+ default:
+ AddToken(TokenType.TAG_START, "<", nStartOffset);
+ break;
+ }
+ return maTokens.lastElement().Type;
+
+ case '>':
+ GetNextCharacter();
+ AddToken(TokenType.TAG_END, ">", nStartOffset);
+ return TokenType.TAG_END;
+
+ case '/':
+ GetNextCharacter();
+ if (GetNextCharacter() != '>')
+ throw new RuntimeException("expected '>' after '/'");
+ AddToken(TokenType.ELEMENT_END, "/>", nStartOffset);
+ return TokenType.ELEMENT_END;
+
+ case '?':
+ GetNextCharacter();
+ if (GetNextCharacter() != '>')
+ throw new RuntimeException("expected '>' after '?'");
+ AddToken(TokenType.INTRO_END, "?>", nStartOffset);
+ return TokenType.INTRO_END;
+
+ case '-':
+ GetNextCharacter();
+ if (GetNextCharacter() != '-')
+ throw new RuntimeException("expected '-' after '-'");
+ if (GetNextCharacter() != '>')
+ throw new RuntimeException("expected '>' after '--'");
+ AddToken(TokenType.COMMENT_END, "-->", nStartOffset);
+ return TokenType.COMMENT_END;
+
+ case '=':
+ GetNextCharacter();
+ AddToken(TokenType.ATTRIBUTE_DEFINE, "=", nStartOffset);
+ return TokenType.ATTRIBUTE_DEFINE;
+
+ case ':':
+ GetNextCharacter();
+ AddToken(TokenType.COLON, ":", nStartOffset);
+ return TokenType.COLON;
+
+ default:
+ throw new RuntimeException(String.format(
+ "unexpected character '%c' of type %d",
+ PeekCharacter(),
+ Character.getType(PeekCharacter())));
+ }
+ }
+
+
+
+
+ private boolean ScanIdentifier ()
+ {
+ final int nStartOffset = mnOffset;
+ int nBufferWriteIndex = 0;
+
+ while (true)
+ {
+ switch(Character.getType(PeekCharacter()))
+ {
+ default:
+ case -1:
+ if (nBufferWriteIndex == 0)
+ throw new RuntimeException(
+ String.format(
+ "missing identifier, got '%c' of type %d",
+ PeekCharacter(),
+ Character.getType(PeekCharacter())));
+ AddToken(
+ TokenType.IDENTIFIER,
+ new String(maTextBuffer, 0, nBufferWriteIndex),
+ nStartOffset);
+ return true;
+
+ case Character.LOWERCASE_LETTER:
+ case Character.UPPERCASE_LETTER:
+ case Character.DECIMAL_DIGIT_NUMBER:
+ if (nBufferWriteIndex >= maTextBuffer.length)
+ maTextBuffer = Arrays.copyOf(maTextBuffer, maTextBuffer.length*2);
+ maTextBuffer[nBufferWriteIndex] = GetNextCharacter();
+ ++nBufferWriteIndex;
+ break;
+ }
+ }
+ }
+
+
+
+
+ private void ScanWhitespace ()
+ {
+ final StringBuffer aBuffer = new StringBuffer();
+ final int nStartOffset = mnOffset;
+
+ while (true)
+ {
+ switch(Character.getType(PeekCharacter()))
+ {
+ default:
+ if (aBuffer.length() > 0)
+ AddToken(TokenType.WHITESPACE, aBuffer.toString(), nStartOffset);
+ return;
+
+ case -1:
+ AddToken(TokenType.WHITESPACE, aBuffer.toString(), nStartOffset);
+ AddToken(TokenType.EOF, "", nStartOffset);
+ return;
+
+ case Character.DIRECTIONALITY_WHITESPACE:
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+ aBuffer.append((char)GetNextCharacter());
+ break;
+ }
+ }
+ }
+
+
+
+
+ private void ScanQuotedValue ()
+ {
+ if (PeekCharacter() == '"')
+ {
+ final int nStartOffset = mnOffset;
+ int nBufferWriteIndex = 0;
+ maTextBuffer[nBufferWriteIndex++] = GetNextCharacter();
+
+ while (PeekCharacter() != '"')
+ {
+ // Make sure that there is enough space for this character and the end quote.
+ if (nBufferWriteIndex >= maTextBuffer.length-1)
+ maTextBuffer = Arrays.copyOf(maTextBuffer, maTextBuffer.length*2);
+ maTextBuffer[nBufferWriteIndex++] = GetNextCharacter();
+ }
+
+ maTextBuffer[nBufferWriteIndex++] = GetNextCharacter();
+
+ AddToken(TokenType.ATTRIBUTE_VALUE, new String(maTextBuffer, 0, nBufferWriteIndex), nStartOffset);
+ }
+ }
+
+
+
+
+ private void ScanText ()
+ {
+ final int nStartOffset = mnOffset;
+ int nBufferWriteIndex = 0;
+ maTextBuffer[nBufferWriteIndex++] = GetNextCharacter();
+
+ while (PeekCharacter() != '<')
+ {
+ if (nBufferWriteIndex >= maTextBuffer.length)
+ maTextBuffer = Arrays.copyOf(maTextBuffer, maTextBuffer.length*2);
+ maTextBuffer[nBufferWriteIndex++] = GetNextCharacter();
+ }
+
+ AddToken(TokenType.TEXT, new String(maTextBuffer, 0, nBufferWriteIndex), nStartOffset);
+ }
+
+
+
+
+ private int GetNextCharacter ()
+ {
+ final int nC;
+ if (mnNextCharacter != 0)
+ {
+ nC = mnNextCharacter;
+ mnNextCharacter = 0;
+ }
+ else
+ {
+ try
+ {
+ nC = maIn.read();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+ ++mnOffset;
+ return nC;
+ }
+
+
+
+
+ private int PeekCharacter ()
+ {
+ if (mnNextCharacter == 0)
+ {
+ try
+ {
+ mnNextCharacter = maIn.read();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ mnNextCharacter = -1;
+ }
+ }
+ return mnNextCharacter;
+ }
+
+
+
+
+ private void AddToken (
+ final TokenType eType,
+ final String sText,
+ final int nOffset)
+ {
+ if (eType != TokenType.WHITESPACE)
+ maTokens.add(new Token(eType, sText, nOffset));
+ }
+
+
+
+
+ private final Reader maIn;
+ private int mnNextCharacter;
+ private Vector<Token> maTokens;
+ private int mnTokensReadIndex;
+ private boolean mbIsInsideTag;
+ private int[] maTextBuffer;
+ private int mnOffset;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLTokenViewFactory.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLTokenViewFactory.java
new file mode 100755
index 000000000000..cfa6d8478e58
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xml/XMLTokenViewFactory.java
@@ -0,0 +1,106 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xml;
+
+import java.io.InputStream;
+
+import org.apache.openoffice.ooxml.viewer.KeyListener;
+import org.apache.openoffice.ooxml.viewer.tokenview.TokenView;
+
+public class XMLTokenViewFactory
+ extends Thread
+{
+ public XMLTokenViewFactory ()
+ {
+ maIn = null;
+ start();
+ }
+
+
+
+
+ public TokenView<TokenType> Create (final InputStream aIn)
+ {
+ TokenView<TokenType> aView = null;
+ synchronized(this)
+ {
+ maIn = aIn;
+ if (maIn != null)
+ {
+ aView = new TokenView<TokenType>();
+ aView.addKeyListener(new KeyListener());
+ maCurrentView = aView;
+
+ FillDocument();
+ //notify();
+ }
+ }
+
+ return aView;
+ }
+
+
+
+
+ @Override
+ public void run ()
+ {
+ while(true)
+ {
+ FillDocument();
+
+ synchronized(this)
+ {
+ if (maIn == null)
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+ private void FillDocument ()
+ {
+ final InputStream aIn = maIn;
+ maIn = null;
+ if (aIn != null)
+ {
+ new DocumentTokenFormatter(new XMLScanner(aIn), maCurrentView).Parse();
+ }
+ }
+
+
+
+
+ private InputStream maIn;
+ private TokenView<TokenType> maCurrentView;
+}
diff --git a/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xmltokenview/XMLViewFactory.java b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xmltokenview/XMLViewFactory.java
new file mode 100755
index 000000000000..3ca361b2ad0e
--- /dev/null
+++ b/ooxml/source/framework/OOXMLViewer/src/org/apache/openoffice/ooxml/viewer/xmltokenview/XMLViewFactory.java
@@ -0,0 +1,143 @@
+/**************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+package org.apache.openoffice.ooxml.viewer.xmltokenview;
+
+import java.util.Vector;
+
+import javax.xml.stream.Location;
+
+import org.apache.openoffice.ooxml.parser.ElementContext;
+import org.apache.openoffice.ooxml.parser.ParseException;
+import org.apache.openoffice.ooxml.parser.Parser;
+import org.apache.openoffice.ooxml.parser.action.ActionTrigger;
+import org.apache.openoffice.ooxml.parser.action.IAction;
+import org.apache.openoffice.ooxml.viewer.tokenview.Run;
+import org.apache.openoffice.ooxml.viewer.tokenview.RunRange;
+import org.apache.openoffice.ooxml.viewer.tokenview.TokenView;
+import org.apache.openoffice.ooxml.viewer.xml.TokenType;
+
+public class XMLViewFactory
+{
+ public static void AddSemanticInformation(
+ final TokenView<TokenType> aView,
+ final Parser aParser,
+ final Vector<String> aErrorsAndWarnings)
+ {
+ aParser.GetActionManager().AddElementStartAction(
+ "*",
+ new IAction()
+ {
+ public void Run (
+ final ActionTrigger eTrigger,
+ final ElementContext aContext,
+ final String sText,
+ final Location aStartLocation,
+ final Location aEndLocation)
+ {
+ final RunRange<TokenType> aRuns = aView.GetRuns(
+ aStartLocation.getCharacterOffset(),
+ aEndLocation.getCharacterOffset());
+ if (aRuns.IsEmpty())
+ aView.GetRuns(
+ aStartLocation.getCharacterOffset(),
+ aEndLocation.getCharacterOffset());
+
+ // Search for the name (including namespace prefix) of the element.
+ int nIndex = aRuns.FindTokens(
+ TokenType.TAG_START,
+ TokenType.IDENTIFIER,
+ TokenType.COLON,
+ TokenType.IDENTIFIER);
+ if (nIndex < 0)
+ return;
+
+ aRuns.Get(nIndex+1).SetToolTipText(aContext.GetTypeName());
+ aRuns.Get(nIndex+2).SetToolTipText(aContext.GetTypeName());
+ aRuns.Get(nIndex+3).SetToolTipText(aContext.GetTypeName());
+ nIndex += 4;
+
+ // Process the attributes.
+ while (true)
+ {
+ final int nStartIndex = nIndex;
+ nIndex = aRuns.FindTokens(
+ nStartIndex,
+ TokenType.IDENTIFIER,
+ TokenType.COLON,
+ TokenType.IDENTIFIER,
+ TokenType.ATTRIBUTE_DEFINE);
+ if (nIndex >= 0)
+ {
+ final String sAttributeName = aRuns.Get(nIndex+2).GetText();
+ aRuns.Get(nIndex+0).SetToolTipText("attribute define of "+sAttributeName);
+ aRuns.Get(nIndex+1).SetToolTipText("attribute define of "+sAttributeName);
+ aRuns.Get(nIndex+2).SetToolTipText("attribute define of "+sAttributeName);
+ nIndex += 5;
+ }
+ else
+ {
+ // Try the variant without namespace.
+ nIndex = aRuns.FindTokens(
+ nStartIndex,
+ TokenType.IDENTIFIER,
+ TokenType.ATTRIBUTE_DEFINE);
+ if (nIndex >= 0)
+ {
+ final String sAttributeName = aRuns.Get(nIndex).GetText();
+ aRuns.Get(nIndex).SetToolTipText("attribute define of "+sAttributeName);
+ nIndex += 3;
+ }
+ else
+ {
+ // No more attributes.
+ break;
+ }
+ }
+ }
+ }
+ });
+ try
+ {
+ aParser.Parse();
+ }
+ catch (final ParseException aException)
+ {
+ System.err.printf("caught exception when parsing %d,%d/%d\n",
+ aException.Location.getLineNumber(),
+ aException.Location.getColumnNumber(),
+ aException.Location.getCharacterOffset());
+
+ final Run<TokenType> aRun = aView.GetRun(aException.Location.getCharacterOffset());
+ if (aRun != null)
+ {
+ aView.MarkError(aRun);
+ aRun.SetToolTipText(
+ String.format(
+ "parse error at %d,%d/%d\n",
+ aException.Location.getLineNumber(),
+ aException.Location.getColumnNumber(),
+ aException.Location.getCharacterOffset()));
+ aView.ShowRun(aRun);
+ }
+ }
+ }
+}