001: package it.stefanochizzolini.clown.samples.gui;
002:
003: import it.stefanochizzolini.clown.documents.Page;
004: import it.stefanochizzolini.clown.documents.contents.Contents;
005: import it.stefanochizzolini.clown.documents.contents.objects.ContentObject;
006: import it.stefanochizzolini.clown.documents.contents.objects.CompositeObject;
007: import it.stefanochizzolini.clown.documents.contents.objects.SetFont;
008: import it.stefanochizzolini.clown.documents.contents.objects.Operation;
009: import it.stefanochizzolini.clown.files.File;
010: import it.stefanochizzolini.clown.objects.PdfArray;
011: import it.stefanochizzolini.clown.objects.PdfDictionary;
012: import it.stefanochizzolini.clown.objects.PdfDirectObject;
013: import it.stefanochizzolini.clown.objects.PdfName;
014: import it.stefanochizzolini.clown.tokens.FileFormatException;
015:
016: import java.awt.Dimension;
017: import java.awt.GridLayout;
018: import java.util.List;
019: import java.util.Map;
020:
021: import javax.swing.JFrame;
022: import javax.swing.JPanel;
023: import javax.swing.JScrollPane;
024: import javax.swing.JSplitPane;
025: import javax.swing.JTable;
026: import javax.swing.table.DefaultTableModel;
027: import javax.swing.JTree;
028: import javax.swing.tree.DefaultMutableTreeNode;
029: import javax.swing.tree.DefaultTreeModel;
030: import javax.swing.tree.TreeSelectionModel;
031: import javax.swing.event.TreeSelectionEvent;
032: import javax.swing.event.TreeSelectionListener;
033:
034: /**
035: PDF content stream's object model inspector.
036: <p>This is a proof of concept that exploits the object-oriented content stream model
037: implemented by PDF Clown since version 0.0.4.</p>
038: */
039: public class PdfInspectorSample extends JPanel implements
040: TreeSelectionListener {
041: // <class>
042: // <classes>
043: private class ContentNodeValue {
044: private ContentObject content;
045: private String name;
046:
047: public ContentNodeValue(ContentObject content) {
048: this .content = content;
049:
050: name = content.getClass().getSimpleName();
051: if (name.equals("Operation")) {
052: name = ((Operation) content).getOperator();
053: }
054: }
055:
056: public ContentObject getContent() {
057: return content;
058: }
059:
060: public String getName() {
061: return name;
062: }
063:
064: @Override
065: public String toString() {
066: return name;
067: }
068: }
069:
070: // </classes>
071:
072: // <fields>
073: private File file;
074:
075: private final JTable table;
076: private final JTree tree;
077:
078: // </fields>
079:
080: // <constructors>
081: public PdfInspectorSample() {
082: super (new GridLayout(1, 0));
083:
084: tree = new JTree();
085: tree.setModel(new DefaultTreeModel(null));
086: tree.getSelectionModel().setSelectionMode(
087: TreeSelectionModel.SINGLE_TREE_SELECTION);
088:
089: tree.addTreeSelectionListener(this );
090:
091: JScrollPane treeView = new JScrollPane(tree);
092:
093: String[] columnNames = { "Attribute", "Value" };
094:
095: table = new JTable(new DefaultTableModel(null, columnNames));
096: JScrollPane tableScrollPane = new JScrollPane(table);
097:
098: JSplitPane splitPane = new JSplitPane(
099: JSplitPane.HORIZONTAL_SPLIT);
100: splitPane.setLeftComponent(treeView);
101: splitPane.setRightComponent(tableScrollPane);
102:
103: Dimension minimumSize = new Dimension(200, 100);
104: tableScrollPane.setMinimumSize(minimumSize);
105: treeView.setMinimumSize(minimumSize);
106:
107: add(splitPane);
108: }
109:
110: // </constructors>
111:
112: // <interface>
113: // <public>
114: public void open(java.io.File file) {
115: try {
116: // Open the PDF file!
117: this .file = new File(file.getAbsolutePath());
118: } catch (FileFormatException e) {
119: throw new RuntimeException(file.getAbsolutePath()
120: + " file has a bad file format.", e);
121: } catch (Exception e) {
122: throw new RuntimeException(file.getAbsolutePath()
123: + " file access error.", e);
124: }
125:
126: DefaultMutableTreeNode fileNode = new DefaultMutableTreeNode(
127: file.getName());
128: ((DefaultTreeModel) tree.getModel()).setRoot(fileNode);
129:
130: createNodes(fileNode);
131:
132: tree.expandPath(new javax.swing.tree.TreePath(fileNode));
133: }
134:
135: // <TreeSelectionListener>
136: public void valueChanged(TreeSelectionEvent e) {
137: DefaultTableModel model = ((DefaultTableModel) table.getModel());
138: model.setRowCount(0);
139:
140: DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
141: .getLastSelectedPathComponent();
142: if (node == null)
143: return;
144:
145: Object nodeValue = node.getUserObject();
146: if (nodeValue instanceof ContentNodeValue) {
147: ContentObject content = ((ContentNodeValue) nodeValue)
148: .getContent();
149: if (content instanceof Operation) {
150: Operation operation = (Operation) content;
151: model.addRow(new Object[] { "(operator)",
152: operation.getOperator() });
153: if (operation instanceof SetFont) {
154: SetFont setFont = (SetFont) operation;
155: model.addRow(new Object[] { "Font name",
156: setFont.getName().toString() });
157: model.addRow(new Object[] { "Font size",
158: setFont.getSize() });
159: } else {
160: List<PdfDirectObject> operands = operation
161: .getOperands();
162: if (operands != null) {
163: for (int index = 0, length = operands.size(); index < length; index++) {
164: PdfDirectObject operand = operands
165: .get(index);
166: if (operand instanceof PdfArray) {
167: PdfArray array = (PdfArray) operand;
168: for (int arrayIndex = 0, arrayLength = array
169: .size(); arrayIndex < arrayLength; arrayIndex++) {
170: model.addRow(new Object[] {
171: "(operand " + index + "."
172: + arrayIndex + ")",
173: array.get(arrayIndex)
174: .toString() });
175: }
176: } else if (operand instanceof PdfDictionary) {
177: PdfDictionary dictionary = (PdfDictionary) operand;
178: int dictionaryIndex = 0;
179: for (Map.Entry<PdfName, PdfDirectObject> entry : dictionary
180: .entrySet()) {
181: model
182: .addRow(new Object[] {
183: "(operand "
184: + index
185: + "."
186: + dictionaryIndex
187: + ") "
188: + entry
189: .getKey()
190: .toString(),
191: entry.getValue()
192: .toString() });
193: dictionaryIndex++;
194: }
195: } else {
196: model.addRow(new Object[] {
197: "(operand " + index + ")",
198: operand.toString() });
199: }
200: }
201: }
202: }
203: }
204: }
205: }
206:
207: // </TreeSelectionListener>
208: // </public>
209:
210: // <private>
211: private void createNodes(DefaultMutableTreeNode fileNode) {
212: int pageIndex = 0;
213: for (Page page : file.getDocument().getPages()) {
214: DefaultMutableTreeNode pageNode = new DefaultMutableTreeNode(
215: "Page " + (++pageIndex));
216: fileNode.add(pageNode);
217:
218: createSubNodes(page.getContents(), pageNode);
219: }
220: }
221:
222: private void createSubNodes(List<ContentObject> contents,
223: DefaultMutableTreeNode parentNode) {
224: for (ContentObject content : contents) {
225: DefaultMutableTreeNode contentNode = new DefaultMutableTreeNode(
226: new ContentNodeValue(content));
227: parentNode.add(contentNode);
228:
229: if (content instanceof CompositeObject) {
230: createSubNodes(
231: (List<ContentObject>) ((CompositeObject) content)
232: .getObjects(), contentNode);
233: }
234: }
235: }
236: // </private>
237: // </interface>
238: // </class>
239: }
|