diff options
Diffstat (limited to 'ooxml/source/framework/OOXMLViewer/src/org')
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); + } + } + } +} |