1 18 package org.apache.batik.util.gui; 19 20 import java.awt.BorderLayout ; 21 import java.awt.Component ; 22 import java.awt.FlowLayout ; 23 import java.awt.GridLayout ; 24 import java.awt.event.ActionEvent ; 25 import java.awt.event.ItemEvent ; 26 import java.awt.event.ItemListener ; 27 28 import java.util.ArrayList ; 29 import java.util.Collections ; 30 import java.util.HashMap ; 31 import java.util.Locale ; 32 import java.util.Map ; 33 import java.util.ResourceBundle ; 34 35 import javax.swing.AbstractAction ; 36 import javax.swing.Action ; 37 import javax.swing.BorderFactory ; 38 import javax.swing.ImageIcon ; 39 import javax.swing.JCheckBox ; 40 import javax.swing.JFrame ; 41 import javax.swing.JPanel ; 42 import javax.swing.JScrollPane ; 43 import javax.swing.JSplitPane ; 44 import javax.swing.JTable ; 45 import javax.swing.JTextArea ; 46 import javax.swing.JTree ; 47 import javax.swing.event.TreeSelectionEvent ; 48 import javax.swing.event.TreeSelectionListener ; 49 import javax.swing.table.AbstractTableModel ; 50 import javax.swing.tree.DefaultMutableTreeNode ; 51 import javax.swing.tree.DefaultTreeCellRenderer ; 52 import javax.swing.tree.DefaultTreeModel ; 53 import javax.swing.tree.MutableTreeNode ; 54 import javax.swing.tree.TreeNode ; 55 56 import org.apache.batik.util.gui.resource.ActionMap; 57 import org.apache.batik.util.gui.resource.ButtonFactory; 58 import org.apache.batik.util.gui.resource.MissingListenerException; 59 import org.apache.batik.util.gui.resource.ResourceManager; 60 import org.w3c.dom.Document ; 61 import org.w3c.dom.Element ; 62 import org.w3c.dom.NamedNodeMap ; 63 import org.w3c.dom.Node ; 64 import org.w3c.dom.css.CSSStyleDeclaration; 65 import org.w3c.dom.css.ViewCSS; 66 67 73 public class DOMViewer extends JFrame implements ActionMap { 74 77 protected final static String RESOURCE = 78 "org.apache.batik.util.gui.resources.DOMViewerMessages"; 79 80 83 protected static ResourceBundle bundle; 84 85 88 protected static ResourceManager resources; 89 90 static { 91 bundle = ResourceBundle.getBundle(RESOURCE, Locale.getDefault()); 92 resources = new ResourceManager(bundle); 93 } 94 95 98 protected Map listeners = new HashMap (); 99 100 103 protected Panel panel = new Panel (); 104 105 protected boolean showWhitespace = true; 106 107 110 public DOMViewer() { 111 super(resources.getString("Frame.title")); 112 setSize(resources.getInteger("Frame.width"), 113 resources.getInteger("Frame.height")); 114 115 listeners.put("CloseButtonAction", new CloseButtonAction()); 116 117 getContentPane().add(panel); 118 119 JPanel p = new JPanel (new BorderLayout ()); 120 121 JCheckBox cb = new JCheckBox ("Show Whitespace Text Nodes"); 122 cb.setSelected(showWhitespace); 123 cb.addItemListener(new ItemListener () { 124 public void itemStateChanged(ItemEvent ie) { 125 setShowWhitespace 126 (ie.getStateChange() == ItemEvent.SELECTED); 127 } 128 }); 129 130 p.add(cb, BorderLayout.WEST); 131 132 133 ButtonFactory bf = new ButtonFactory(bundle, this); 134 p.add(bf.createJButton("CloseButton"), BorderLayout.EAST); 135 getContentPane().add("South", p); 136 } 137 138 public void setShowWhitespace(boolean state) { 139 showWhitespace = state; 140 if (panel.document != null) 141 panel.setDocument(panel.document); 142 } 143 144 147 public void setDocument(Document doc) { 148 panel.setDocument(doc); 149 } 150 151 154 public void setDocument(Document doc, ViewCSS view) { 155 panel.setDocument(doc, view); 156 } 157 158 164 public Action getAction(String key) throws MissingListenerException { 165 return (Action )listeners.get(key); 166 } 167 168 171 protected class CloseButtonAction extends AbstractAction { 172 public void actionPerformed(ActionEvent e) { 173 dispose(); 174 } 175 } 176 177 180 public class Panel extends JPanel { 181 184 protected Document document; 185 186 189 protected ViewCSS viewCSS; 190 191 194 protected JTree tree; 195 196 199 protected JSplitPane splitPane; 200 201 204 protected JPanel rightPanel = new JPanel (new BorderLayout ()); 205 206 209 protected JTable attributesTable = new JTable (); 210 211 214 protected JTable propertiesTable = new JTable (); 215 216 219 protected JPanel elementPanel = new JPanel (new GridLayout (2, 1)); 220 { 221 JScrollPane pane = new JScrollPane (); 222 pane.setBorder(BorderFactory.createCompoundBorder 223 (BorderFactory.createEmptyBorder(2, 0, 2, 2), 224 BorderFactory.createCompoundBorder 225 (BorderFactory.createTitledBorder 226 (BorderFactory.createEmptyBorder(), 227 resources.getString("AttributesPanel.title")), 228 BorderFactory.createLoweredBevelBorder()))); 229 pane.getViewport().add(attributesTable); 230 231 JScrollPane pane2 = new JScrollPane (); 232 pane2.setBorder(BorderFactory.createCompoundBorder 233 (BorderFactory.createEmptyBorder(2, 0, 2, 2), 234 BorderFactory.createCompoundBorder 235 (BorderFactory.createTitledBorder 236 (BorderFactory.createEmptyBorder(), 237 resources.getString("CSSValuesPanel.title")), 238 BorderFactory.createLoweredBevelBorder()))); 239 pane2.getViewport().add(propertiesTable); 240 241 elementPanel.add(pane); 242 elementPanel.add(pane2); 243 } 244 245 248 protected JTextArea characterData = new JTextArea (); 249 250 253 protected JPanel characterDataPanel = new JPanel (new BorderLayout ()); 254 { 255 characterDataPanel.setBorder 256 (BorderFactory.createCompoundBorder 257 (BorderFactory.createEmptyBorder(2, 0, 2, 2), 258 BorderFactory.createCompoundBorder 259 (BorderFactory.createTitledBorder 260 (BorderFactory.createEmptyBorder(), 261 resources.getString("CDataPanel.title")), 262 BorderFactory.createLoweredBevelBorder()))); 263 JScrollPane pane = new JScrollPane (); 264 pane.getViewport().add(characterData); 265 characterDataPanel.add(pane); 266 characterData.setEditable(false); 267 } 268 269 272 protected JTextArea documentInfo = new JTextArea (); 273 274 277 protected JPanel documentInfoPanel = new JPanel (new BorderLayout ()); 278 { 279 documentInfoPanel.setBorder 280 (BorderFactory.createCompoundBorder 281 (BorderFactory.createEmptyBorder(2, 0, 2, 2), 282 BorderFactory.createCompoundBorder 283 (BorderFactory.createTitledBorder 284 (BorderFactory.createEmptyBorder(), 285 resources.getString("DocumentInfoPanel.title")), 286 BorderFactory.createLoweredBevelBorder()))); 287 JScrollPane pane = new JScrollPane (); 288 pane.getViewport().add(documentInfo); 289 documentInfoPanel.add(pane); 290 documentInfo.setEditable(false); 291 } 292 293 296 public Panel() { 297 super(new BorderLayout ()); 298 setBorder(BorderFactory.createTitledBorder 299 (BorderFactory.createEmptyBorder(), 300 resources.getString("DOMViewerPanel.title"))); 301 302 TreeNode root; 303 root = new DefaultMutableTreeNode 304 (resources.getString("EmptyDocument.text")); 305 tree = new JTree (root); 306 tree.setCellRenderer(new NodeRenderer()); 307 tree.putClientProperty("JTree.lineStyle", "Angled"); 308 309 JScrollPane treePane = new JScrollPane (); 310 treePane.setBorder(BorderFactory.createCompoundBorder 311 (BorderFactory.createEmptyBorder(2, 2, 2, 0), 312 BorderFactory.createCompoundBorder 313 (BorderFactory.createTitledBorder 314 (BorderFactory.createEmptyBorder(), 315 resources.getString("DOMViewer.title")), 316 BorderFactory.createLoweredBevelBorder()))); 317 treePane.getViewport().add(tree); 318 splitPane = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, 319 true, treePane, 321 rightPanel); 322 int loc = resources.getInteger("SplitPane.dividerLocation"); 323 splitPane.setDividerLocation(loc); 324 add(splitPane); 325 326 tree.addTreeSelectionListener(new DOMTreeSelectionListener()); 327 } 328 329 332 public void setDocument(Document doc) { 333 setDocument(doc, null); 334 } 335 336 339 public void setDocument(Document doc, ViewCSS view) { 340 document = doc; 341 viewCSS = view; 342 TreeNode root = createTree(doc, showWhitespace); 343 ((DefaultTreeModel )tree.getModel()).setRoot(root); 344 if (rightPanel.getComponentCount() != 0) { 345 rightPanel.remove(0); 346 splitPane.revalidate(); 347 splitPane.repaint(); 348 } 349 } 350 351 354 protected MutableTreeNode createTree(Node node, 355 boolean showWhitespace) { 356 DefaultMutableTreeNode result; 357 result = new DefaultMutableTreeNode (new NodeInfo(node)); 358 for (Node n = node.getFirstChild(); 359 n != null; 360 n = n.getNextSibling()) { 361 if (!showWhitespace && (n instanceof org.w3c.dom.Text )) { 362 String txt = n.getNodeValue(); 363 if (txt.trim().length() == 0) 364 continue; 365 } 366 result.add(createTree(n, showWhitespace)); 367 } 368 return result; 369 } 370 371 374 protected class DOMTreeSelectionListener 375 implements TreeSelectionListener { 376 379 public void valueChanged(TreeSelectionEvent ev) { 380 DefaultMutableTreeNode mtn; 381 mtn = 382 (DefaultMutableTreeNode )tree.getLastSelectedPathComponent(); 383 if (mtn == null) { 384 return; 385 } 386 387 if (rightPanel.getComponentCount() != 0) { 388 rightPanel.remove(0); 389 } 390 391 Object nodeInfo = mtn.getUserObject(); 392 if (nodeInfo instanceof NodeInfo) { 393 Node node = ((NodeInfo)nodeInfo).getNode(); 394 switch (node.getNodeType()) { 395 case Node.DOCUMENT_NODE: 396 documentInfo.setText 397 (createDocumentText((Document )node)); 398 rightPanel.add(documentInfoPanel); 399 break; 400 case Node.ELEMENT_NODE: 401 attributesTable.setModel(new NodeAttributesModel(node)); 402 propertiesTable.setModel(new NodeCSSValuesModel(node)); 403 rightPanel.add(elementPanel); 404 break; 405 case Node.COMMENT_NODE: 406 case Node.TEXT_NODE: 407 case Node.CDATA_SECTION_NODE: 408 characterData.setText(node.getNodeValue()); 409 rightPanel.add(characterDataPanel); 410 } 411 } 412 splitPane.revalidate(); 413 splitPane.repaint(); 414 } 415 416 protected String createDocumentText(Document doc) { 417 StringBuffer sb = new StringBuffer (); 418 sb.append("Nodes: "); 419 sb.append(nodeCount(doc)); 420 return sb.toString(); 421 } 422 423 protected int nodeCount(Node node) { 424 int result = 1; 425 for (Node n = node.getFirstChild(); 426 n != null; 427 n = n.getNextSibling()) { 428 result += nodeCount(n); 429 } 430 return result; 431 } 432 } 433 434 437 protected class NodeRenderer extends DefaultTreeCellRenderer { 438 441 ImageIcon elementIcon; 442 443 446 ImageIcon commentIcon; 447 448 451 ImageIcon piIcon; 452 453 456 ImageIcon textIcon; 457 458 461 public NodeRenderer() { 462 String s; 463 s = resources.getString("Element.icon"); 464 elementIcon = new ImageIcon (getClass().getResource(s)); 465 s = resources.getString("Comment.icon"); 466 commentIcon = new ImageIcon (getClass().getResource(s)); 467 s = resources.getString("PI.icon"); 468 piIcon = new ImageIcon (getClass().getResource(s)); 469 s = resources.getString("Text.icon"); 470 textIcon = new ImageIcon (getClass().getResource(s)); 471 } 472 473 476 public Component getTreeCellRendererComponent(JTree tree, 477 Object value, 478 boolean sel, 479 boolean expanded, 480 boolean leaf, 481 int row, 482 boolean hasFocus) { 483 super.getTreeCellRendererComponent(tree, value, sel, expanded, 484 leaf, row, hasFocus); 485 switch (getNodeType(value)) { 486 case Node.ELEMENT_NODE: 487 setIcon(elementIcon); 488 break; 489 case Node.COMMENT_NODE: 490 setIcon(commentIcon); 491 break; 492 case Node.PROCESSING_INSTRUCTION_NODE: 493 setIcon(piIcon); 494 break; 495 case Node.TEXT_NODE: 496 case Node.CDATA_SECTION_NODE: 497 setIcon(textIcon); 498 break; 499 } 500 return this; 501 } 502 503 507 protected short getNodeType(Object value) { 508 DefaultMutableTreeNode mtn = (DefaultMutableTreeNode )value; 509 Object obj = mtn.getUserObject(); 510 if (obj instanceof NodeInfo) { 511 Node node = ((NodeInfo)obj).getNode(); 512 return node.getNodeType(); 513 } 514 return -1; 515 } 516 } 517 518 521 protected class NodeAttributesModel extends AbstractTableModel { 522 525 protected Node node; 526 527 530 public NodeAttributesModel(Node n) { 531 node = n; 532 } 533 534 537 public String getColumnName(int col) { 538 if (col == 0) { 539 return resources.getString("AttributesTable.column1"); 540 } else { 541 return resources.getString("AttributesTable.column2"); 542 } 543 } 544 545 548 public int getColumnCount() { 549 return 2; 550 } 551 552 555 public int getRowCount() { 556 return node.getAttributes().getLength(); 557 } 558 559 562 public boolean isCellEditable(int row, int col) { 563 return false; 564 } 565 566 569 public Object getValueAt(int row, int col) { 570 NamedNodeMap map = node.getAttributes(); 571 Node n = map.item(row); 572 if (col == 0) { 573 return n.getNodeName(); 574 } else { 575 return n.getNodeValue(); 576 } 577 } 578 } 579 580 583 protected class NodeCSSValuesModel extends AbstractTableModel { 584 587 protected Node node; 588 589 592 protected CSSStyleDeclaration style; 593 594 597 protected java.util.List propertyNames; 598 599 602 public NodeCSSValuesModel(Node n) { 603 node = n; 604 if (viewCSS != null) { 605 style = viewCSS.getComputedStyle((Element )n, null); 606 propertyNames = new ArrayList (); 607 if (style != null) { 608 for (int i = 0; i < style.getLength(); i++) { 609 propertyNames.add(style.item(i)); 610 } 611 Collections.sort(propertyNames); 612 } 613 } 614 } 615 616 619 public String getColumnName(int col) { 620 if (col == 0) { 621 return resources.getString("CSSValuesTable.column1"); 622 } else { 623 return resources.getString("CSSValuesTable.column2"); 624 } 625 } 626 627 630 public int getColumnCount() { 631 return 2; 632 } 633 634 637 public int getRowCount() { 638 if (style == null) { 639 return 0; 640 } 641 return style.getLength(); 642 } 643 644 647 public boolean isCellEditable(int row, int col) { 648 return false; 649 } 650 651 654 public Object getValueAt(int row, int col) { 655 String prop = (String )propertyNames.get(row); 656 if (col == 0) { 657 return prop; 658 } else { 659 return style.getPropertyValue(prop); 660 } 661 } 662 } 663 664 } 666 669 protected static class NodeInfo { 670 673 protected Node node; 674 675 678 public NodeInfo(Node n) { 679 node = n; 680 } 681 682 685 public Node getNode() { 686 return node; 687 } 688 689 692 public String toString() { 693 if (node instanceof Element ) { 694 String id = ((Element )node).getAttribute("id"); 695 if (id.length() != 0) { 696 return node.getNodeName() + " \""+id+"\""; 697 } 698 } 699 return node.getNodeName(); 700 } 701 } 702 } 703 | Popular Tags |