KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ui > TreeView


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package ui;
59                     
60
61 import java.awt.BorderLayout JavaDoc;
62 import java.awt.Color JavaDoc;
63 import java.awt.Component JavaDoc;
64 import java.awt.Dimension JavaDoc;
65 import java.awt.Font JavaDoc;
66 import java.awt.Image JavaDoc;
67 import java.awt.event.ActionEvent JavaDoc;
68 import java.awt.event.ActionListener JavaDoc;
69 import java.awt.event.TextEvent JavaDoc;
70 import java.awt.event.TextListener JavaDoc;
71 import java.io.BufferedReader JavaDoc;
72 import java.io.File JavaDoc;
73 import java.io.IOException JavaDoc;
74 import java.io.InputStream JavaDoc;
75 import java.io.InputStreamReader JavaDoc;
76 import java.io.UnsupportedEncodingException JavaDoc;
77 import java.net.MalformedURLException JavaDoc;
78 import java.net.URL JavaDoc;
79 import java.util.Enumeration JavaDoc;
80 import java.util.EventObject JavaDoc;
81 import java.util.Hashtable JavaDoc;
82 import java.util.Vector JavaDoc;
83
84 import javax.swing.BorderFactory JavaDoc;
85 import javax.swing.ImageIcon JavaDoc;
86 import javax.swing.JButton JavaDoc;
87 import javax.swing.JComponent JavaDoc;
88 import javax.swing.JFrame JavaDoc;
89 import javax.swing.JLabel JavaDoc;
90 import javax.swing.JMenu JavaDoc;
91 import javax.swing.JMenuBar JavaDoc;
92 import javax.swing.JMenuItem JavaDoc;
93 import javax.swing.JPanel JavaDoc;
94 import javax.swing.JScrollPane JavaDoc;
95 import javax.swing.JSplitPane JavaDoc;
96 import javax.swing.JTextArea JavaDoc;
97 import javax.swing.JTextField JavaDoc;
98 import javax.swing.JTree JavaDoc;
99 import javax.swing.event.TreeSelectionEvent JavaDoc;
100 import javax.swing.event.TreeSelectionListener JavaDoc;
101 import javax.swing.tree.DefaultTreeCellRenderer JavaDoc;
102 import javax.swing.tree.TreeNode JavaDoc;
103 import javax.swing.tree.TreeSelectionModel JavaDoc;
104
105 import org.w3c.dom.Attr JavaDoc;
106 import org.w3c.dom.Document JavaDoc;
107 import org.w3c.dom.Element JavaDoc;
108 import org.w3c.dom.Node JavaDoc;
109 import org.xml.sax.ErrorHandler JavaDoc;
110 import org.xml.sax.SAXException JavaDoc;
111 import org.xml.sax.SAXParseException JavaDoc;
112
113
114
115 /**
116  * A sample DOM Tree Viewer. This sample program illustrates how to
117  * traverse a DOM tree and display it in a Swing JTree View.
118  *
119  * @version
120  */

121 public class TreeView extends JFrame JavaDoc implements ActionListener JavaDoc, TextListener JavaDoc {
122
123     //
124
// Constants
125
//
126

127     static final boolean DEBUG = true;
128   
129     /** Default parser name. */
130     static final String JavaDoc
131         DEFAULT_PARSER_NAME = "org.enhydra.apache.xerces.parsers.DOMParser";
132     static int WARNING = 0;
133     static int ERROR=1;
134     static int FATAL_ERROR=2;
135         
136
137     static final String JavaDoc title = "TreeViewer";
138     static final String JavaDoc openString = "Open";
139     static final String JavaDoc quitString = "Quit";
140     static final String JavaDoc reloadString = "Reload current XML file";
141     static final String JavaDoc expandString = "Expand Tree";
142     static final String JavaDoc collapseString = "Collapse Tree";
143
144     //
145
// Data
146
//
147

148     ErrorStorer ef;
149     String JavaDoc fname;
150     DOMTree m_tree;
151     JTextArea JavaDoc sourceText, messageText;
152     Vector JavaDoc textLine;
153     FileNameInput fni;
154     DOMParserSaveEncoding parser;
155     Image JavaDoc openFolder;
156     Image JavaDoc closedFolder;
157     Image JavaDoc leafImage;
158
159     /**
160      * Constructor
161      */

162     public TreeView() {
163         this(null);
164     }
165
166     /**
167      * Constructor
168      */

169     public TreeView(String JavaDoc uri) {
170         super(uri);
171         openFolder = DefaultImages.createOpenFolderImage();
172         closedFolder = DefaultImages.createClosedFolderImage();
173         leafImage = DefaultImages.createLeafImage();
174         parser = new DOMParserSaveEncoding();
175         ef = new ErrorStorer();
176         fname = uri;
177         JMenuBar JavaDoc jmb = new JMenuBar JavaDoc();
178         JMenu JavaDoc fileMenu = new JMenu JavaDoc("File");
179         JMenuItem JavaDoc item;
180
181         item = new JMenuItem JavaDoc(openString);
182         fileMenu.add(item);
183         item.addActionListener(this);
184
185         item = new JMenuItem JavaDoc(quitString);
186         fileMenu.add(item);
187         item.addActionListener(this);
188
189         JMenu JavaDoc shortcutMenu = new JMenu JavaDoc("Shortcuts");
190
191         item = new JMenuItem JavaDoc(expandString);
192         shortcutMenu.add(item);
193         item.addActionListener(this);
194
195         item = new JMenuItem JavaDoc(collapseString);
196         shortcutMenu.add(item);
197         item.addActionListener(this);
198
199         item = new JMenuItem JavaDoc(reloadString);
200         shortcutMenu.add(item);
201         item.addActionListener(this);
202
203         jmb.add(fileMenu);
204         jmb.add(shortcutMenu);
205         setJMenuBar(jmb);
206
207         getContentPane().add(createUI(fname));
208         
209     }
210
211     /** create and return the entire UI from the root TreeNode
212      */

213     JComponent JavaDoc createUI(String JavaDoc filename) {
214         if (DEBUG) System.out.println("START createUI:"+filename);
215
216         // create the message panel first so we can send messages to it...
217
messageText = new JTextArea JavaDoc(3,40);
218         messageText.setFont(new Font JavaDoc("dialog", Font.PLAIN, 12));
219         JPanel JavaDoc messagePanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
220         messagePanel.add(new JScrollPane JavaDoc(messageText) {
221             public Dimension JavaDoc getPreferredSize(){
222                 Dimension JavaDoc size = TreeView.this.getSize();
223                 return new Dimension JavaDoc(size.width, size.height / 4);
224                 }
225             public Dimension JavaDoc getMinimumSize(){
226                 return new Dimension JavaDoc(100, 100);
227                 }
228             },
229             BorderLayout.CENTER);
230         messagePanel.setBorder(BorderFactory.createCompoundBorder(
231             BorderFactory.createTitledBorder("Messages"),
232             BorderFactory.createEmptyBorder(4, 4, 4, 4)
233             ));
234
235         // create the TextArea for XML source
236
sourceText = new JTextArea JavaDoc();
237         sourceText.setFont(new Font JavaDoc("monospaced", Font.PLAIN, 12));
238         sourceText.setBackground(Color.white);
239         sourceText.setForeground(Color.black);
240         sourceText.setSelectedTextColor(Color.black);
241         sourceText.setSelectionColor(Color.red);
242         sourceText.setEditable(false);
243         JPanel JavaDoc sourcePanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
244         sourcePanel.add(new JScrollPane JavaDoc(sourceText){
245             public Dimension JavaDoc getPreferredSize(){
246                 Dimension JavaDoc size = TreeView.this.getSize();
247                 return new Dimension JavaDoc(size.width / 2, size.height * 3 / 5);
248                 }
249             public Dimension JavaDoc getMinimumSize(){
250                 return new Dimension JavaDoc(100, 100);
251                 }
252             },
253             BorderLayout.CENTER);
254         sourcePanel.setBorder(BorderFactory.createCompoundBorder(
255             BorderFactory.createTitledBorder("Source View"),
256             BorderFactory.createEmptyBorder(4, 4, 4, 4)
257             ));
258
259         // create the JTree and scroll pane.
260
JPanel JavaDoc treePanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
261         m_tree = new DOMTree();
262         m_tree.setCellRenderer(new XMLTreeCellRenderer());
263         m_tree.getSelectionModel().setSelectionMode
264             (TreeSelectionModel.SINGLE_TREE_SELECTION);
265
266         // Listen for when the selection changes, call nodeSelected(node)
267
m_tree.addTreeSelectionListener(
268             new TreeSelectionListener JavaDoc() {
269                 public void valueChanged(TreeSelectionEvent JavaDoc e) {
270                     TreeNode JavaDoc node = (TreeNode JavaDoc)
271                         (e.getPath().getLastPathComponent());
272
273                     nodeSelected(node);
274                 }
275             }
276         );
277         m_tree.setRowHeight(18);
278         m_tree.setFont(new Font JavaDoc("dialog", Font.PLAIN, 12));
279
280         treePanel.add(new JScrollPane JavaDoc(m_tree) {
281             public Dimension JavaDoc getPreferredSize(){
282                 Dimension JavaDoc size = TreeView.this.getSize();
283                 return new Dimension JavaDoc(size.width / 2, size.height * 3 / 5);
284                 }
285             public Dimension JavaDoc getMinimumSize(){
286                 return new Dimension JavaDoc(100, 100);
287                 }
288             },
289             BorderLayout.CENTER);
290
291         treePanel.setBorder(BorderFactory.createCompoundBorder(
292             BorderFactory.createTitledBorder("Tree View"),
293             BorderFactory.createEmptyBorder(4, 4, 4, 4)
294             ));
295
296         // refreshUI loads everthything!
297
refreshUI(filename);
298
299         // use the new JSplitPane to dynamically resize...
300
JComponent JavaDoc split = new JSplitPane JavaDoc(JSplitPane.HORIZONTAL_SPLIT,
301             true, treePanel, sourcePanel);
302
303         JComponent JavaDoc mainSplitPane =
304             new JSplitPane JavaDoc(JSplitPane.VERTICAL_SPLIT,
305                            true, split, messagePanel);
306
307         if (DEBUG) System.out.println("END createUI:"+filename);
308         return mainSplitPane;
309     }
310
311     /** refreshUI is called when we have a new filename to parse.
312      */

313     void refreshUI(String JavaDoc filename) {
314         if (DEBUG) System.out.println("START refreshUI:"+filename);
315
316         messageText.selectAll();
317         messageText.cut();
318
319         if (filename == null || filename.equals("")) {
320             messageText.setForeground(Color.red);
321             messageText.append("No input XML filename specified:"+filename+"\n");
322             return;
323         }
324
325         fname = filename;
326         Document JavaDoc newRoot = getRoot(filename);
327         if (newRoot == null) {
328             messageText.setForeground(Color.red);
329             messageText.append("Unable to get new DOM Tree for:"+filename+"\n");
330             return;
331         }
332         m_tree.setDocument(newRoot);
333
334         // new Source
335
sourceText.selectAll();
336         sourceText.cut();
337         readXMLFile(fname, sourceText);
338
339         setTitle(title+": "+filename);
340
341         if (m_tree!= null)
342             expandTree();
343
344
345         if (ef != null && ef.getErrorNodes()!=null
346                     && ef.getErrorNodes().size() > 0 ) {
347             messageText.setForeground(Color.red);
348             messageText.append("XML source, "+fname+" has errors.\n");
349             messageText.append("Please click on red Tree View items for details.\n");
350             /***/
351             Hashtable JavaDoc errors = ef.getErrorNodes();
352             Enumeration JavaDoc keys = errors.keys();
353             while (keys.hasMoreElements()) {
354                 Node JavaDoc node = (Node JavaDoc)keys.nextElement();
355                 messageText.append("node="+node.getNodeName()
356                 +", error="+((ParseError)errors.get(node)).getMsg()+"\n");
357             }
358         }
359         if (DEBUG) System.out.println("END refreshUI:"+filename);
360     }
361
362     /**
363      * Invoke the Parser on fname and return the root TreeNode.
364      */

365     public Document JavaDoc getRoot(String JavaDoc filename) {
366         if (DEBUG) System.out.println("START getRoot:"+filename);
367
368         if (filename == null || filename.equals(""))
369         return null;
370
371         try {
372             //
373
// Reset the Error Storage and handling
374
//
375

376             ef.resetErrors();
377             parser.setErrorHandler(ef);
378             parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false); // otherwise parser.getCurrentNode() == null
379
parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
380             parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
381             parser.parse(filename);
382             Document JavaDoc document = parser.getDocument();
383             /***/
384             return document;
385         } catch (Exception JavaDoc e) {
386              System.err.println( "Error: Invalid XML document could not get ROOT" );
387              System.exit( 1 );
388             //e.printStackTrace(System.err);
389
}
390         return null;
391     }
392
393     /** read the xml file from filename and append it to the JTextArea
394      */

395     synchronized void readXMLFile(String JavaDoc filename, JTextArea JavaDoc ta) {
396
397         if (DEBUG) System.out.println("START readXMLFile"+filename);
398         if (filename == null || filename.equals(""))
399             return;
400         InputStream JavaDoc fis = null;
401         BufferedReader JavaDoc dis = null;
402         try {
403             java.net.URL JavaDoc file = createURL(filename);
404             fis = file.openStream();
405
406             String JavaDoc javaEncoding = parser.getJavaEncoding(); // get saved java encoding
407
try
408             {
409             dis = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(fis, javaEncoding ));
410             }
411             catch( UnsupportedEncodingException JavaDoc ex )
412             {
413             dis = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(fis ));
414             }
415         } catch (Exception JavaDoc ex) {
416             System.err.println("ERROR: Xerces.readXMLFile: "+ex);
417             return;
418         }
419
420         String JavaDoc line;
421         int i = 0;
422
423         int len = 0;
424         textLine = new Vector JavaDoc();
425         String JavaDoc nl = "\n";
426         int nllen = nl.length();
427         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
428
429         try{
430             readline: while ((line = dis.readLine()) != null) {
431                 sb.append(line+nl);
432                 textLine.addElement(new Integer JavaDoc(len));
433                 len += line.length()+nllen;
434             }
435             ta.append(sb.toString());
436         } catch (IOException JavaDoc io) {
437             System.err.println(io);
438             return;
439         }
440
441         // relayout because contents have changed
442
//ta.revalidate();
443

444         if (DEBUG) System.out.println("END readXMLFile"+filename);
445         return;
446
447     }
448
449     /** called when our JTree's nodes are selected.
450      */

451     void nodeSelected(TreeNode JavaDoc treeNode) {
452
453         Node JavaDoc node = m_tree.getNode(treeNode);
454
455         if( node == null ) // It is possible to get a null node
456
return;
457
458         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
459         messageText.selectAll();
460         messageText.cut();
461
462
463         //fix
464

465        //JTextArea sourceText = sourceText;
466
Object JavaDoc errorObject = ef == null ? null : ef.getError(node);
467        if (errorObject != null) {
468            // There *is* an error in this node.
469
messageText.setForeground(Color.red);
470            ParseError eip = (ParseError)errorObject;
471            sb.append("Error: "+eip.getMsg()+"\n");
472            int lineNo = eip.getLineNo();
473            int pos = 0;
474            int next = 0;
475            int sizeOfTextLine = textLine.size();
476
477            if( lineNo < sizeOfTextLine )
478               {
479               pos = ((Integer JavaDoc)textLine.elementAt(lineNo-1)).intValue();
480               next = (lineNo == sizeOfTextLine ) ?
481                pos :
482                (((Integer JavaDoc)textLine.elementAt(lineNo)).intValue());
483               }
484            else
485               {
486               pos = (( Integer JavaDoc) textLine.elementAt( sizeOfTextLine - 1 )).intValue();
487               next = pos + 2;
488               }
489
490            sourceText.select(pos, next );
491            //m_textScrollPane.repaint();
492
} else {
493            messageText.setForeground(Color.black);
494            sourceText.select(0, 0 );
495        }
496         
497         //fix
498

499         
500         if (node.getNodeType() == Node.ELEMENT_NODE
501                     || node.getNodeType() == Node.TEXT_NODE
502                 || node.getNodeType() == Node.CDATA_SECTION_NODE )
503                  {
504                     sb.append(node.toString());
505             }
506        
507         messageText.append(sb.toString());
508     }
509
510     /** called when a the text value has changed in the FileNameInput.
511      * read in new XML file.
512      */

513     public void textValueChanged(TextEvent JavaDoc e) {
514         try {
515             if (fni != null)
516                 fni.setVisible(false);
517             fname = ((JTextField JavaDoc)e.getSource()).getText();
518             if (DEBUG) System.out.println("textValueChanged:"+fname);
519             refreshUI(fname);
520
521         } catch (Exception JavaDoc ex) {
522            System.err.println( "Error: while trying to refresh gui" );
523            System.exit( 1 );
524         // ex.printStackTrace();
525
}
526     }
527
528     /** called to handle menu actions.
529      */

530     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
531         if (DEBUG) System.err.println("ACTION: "+e.getActionCommand()+", "+e.paramString());
532
533         if (e.getActionCommand().equals(quitString)) {
534           System.exit(0);
535         }
536         else if (e.getActionCommand().equals(openString)) {
537
538             fni = new FileNameInput("Open File");
539             fni.addTextListener(this);
540             fni.setVisible(true);
541         }
542         else if (e.getActionCommand().equals(expandString)) {
543             expandTree();
544         }
545         else if (e.getActionCommand().equals(collapseString)) {
546             int rows = m_tree.getRowCount();
547             for (int i = 0; i < rows; i++) {
548                 m_tree.collapseRow(i);
549             }
550         }
551         else
552         //if (e.getActionCommand().equals(reloadString)) {
553
refreshUI(fname);
554         //}
555
}
556
557     void expandTree() {
558         int rows = 0;
559         for (int levels=0; levels <= 4; levels++) {
560             rows=m_tree.getRowCount();
561             for (int i = 0; i < rows; i++) {
562                 m_tree.expandRow(i);
563             }
564         }
565     }
566
567     /*
568      * The XMLTreeCellRenderer is an inner class which enables the
569      * highlighting of errors in the tree and shows the gender values
570      * as different icons.
571      */

572     class XMLTreeCellRenderer extends DefaultTreeCellRenderer JavaDoc
573     {
574
575         public Component JavaDoc getTreeCellRendererComponent(JTree JavaDoc tree, Object JavaDoc value,
576                           boolean selected, boolean expanded,
577                           boolean leaf, int row,
578                               boolean hasFocus)
579         {
580             Node JavaDoc node = ((DOMTree)tree).getNode(value);
581             Component JavaDoc comp = super.getTreeCellRendererComponent(tree, value,
582                            selected, expanded, leaf, row, hasFocus);
583             if (selected) {
584                 comp.setBackground(Color.blue);
585             }
586             if (ef != null
587             && ef.getErrorNodes() != null
588             && value != null
589             && node != null
590             && ef.getErrorNodes().containsKey( node )) {
591                 comp.setForeground(Color.red);
592             }
593
594             if (node != null) {
595                 if (leaf) {
596                     setIcon(new ImageIcon JavaDoc(leafImage));
597                 } else if (expanded) {
598                     setIcon(new ImageIcon JavaDoc(openFolder));
599                 } else {
600                     setIcon(new ImageIcon JavaDoc(closedFolder));
601                 }
602             }
603             if (node != null && node instanceof Element JavaDoc) {
604                 
605                 Element JavaDoc txNode = (Element JavaDoc)node;
606                 Attr JavaDoc txAtt = (Attr JavaDoc)txNode.getAttributeNode("gender");
607                 if (txAtt != null) {
608                     if (txAtt.getValue().equals("male")) {
609                         setIcon(new ImageIcon JavaDoc("male.gif"));
610                     } else
611                     if (txAtt.getValue().equals("female")) {
612                         setIcon(new ImageIcon JavaDoc("female.gif"));
613                     }
614                 }
615             }
616
617             return comp;
618         }
619     }
620
621     /*
622      * The FileNameInput is an inner class which allows the user
623      * to enter a filename. It exists due to a Swing bug which
624      * has problems with the real file input panel.
625      */

626     class FileNameInput extends JFrame JavaDoc implements ActionListener JavaDoc {
627
628
629         JLabel JavaDoc fileLabel;
630         JTextField JavaDoc textField;
631         JButton JavaDoc ok;
632         JButton JavaDoc cancel;
633         Vector JavaDoc textListeners;
634
635         public FileNameInput() {
636             this("");
637         }
638
639         public FileNameInput(String JavaDoc title) {
640
641             super(title);
642
643             fileLabel = new JLabel JavaDoc("Enter XML file name:");
644             textField = new JTextField JavaDoc();
645             textField.addActionListener(this);
646             ok = new JButton JavaDoc("ok");
647             cancel = new JButton JavaDoc("cancel");
648             JPanel JavaDoc buttonPanel = new JPanel JavaDoc();
649             buttonPanel.add(ok);
650             buttonPanel.add(cancel);
651             ok.addActionListener(this);
652             cancel.addActionListener(this);
653             getContentPane().add(fileLabel, BorderLayout.NORTH);
654             getContentPane().add(textField, BorderLayout.CENTER);
655             getContentPane().add(buttonPanel, BorderLayout.SOUTH);
656             setSize(400,100);
657         }
658
659         public void actionPerformed(ActionEvent JavaDoc e) {
660
661             if (e.getSource() == ok || e.getSource() == textField) {
662                 System.out.println("FileNameInput: pressed OK");
663                     TextEvent JavaDoc event = new TextEvent JavaDoc(textField, TextEvent.TEXT_VALUE_CHANGED);
664                     deliverEvent(event);
665                     setVisible(false);
666             } else
667             if (e.getSource() == cancel) {
668                 System.out.println("FileNameInput: pressed cancel");
669                     setVisible(false);
670             }
671         }
672
673         /**
674          * Adds a TextListener event listener.
675          *
676          * @param listener The listener to add.
677          *
678          * @see #removeTextListener
679          */

680         public void addTextListener(TextListener JavaDoc listener) {
681
682             // is there anything to do?
683
if (listener == null)
684                 return;
685
686             if (textListeners == null)
687                textListeners = new Vector JavaDoc();
688
689             // add listener
690
textListeners.addElement(listener);
691             }
692
693         /**
694          * Removes a TextListener event listener.
695          *
696          * @param listener The listener to remove.
697          *
698          * @see #addTextListener
699          */

700         public void removeTextListener(TextListener JavaDoc listener) {
701
702             // is there anything to do?
703
if (listener == null || textListeners == null)
704                 return;
705
706             // add listener
707
textListeners.removeElement(listener);
708             }
709
710
711         /**
712          * This function delivers TextListener events, when the ok
713          * button is clicked.
714          *
715          * @param evt The event to deliver.
716          */

717         protected void deliverEvent(EventObject JavaDoc evt) {
718
719             if (evt instanceof TextEvent JavaDoc) {
720                 TextEvent JavaDoc event = (TextEvent JavaDoc)evt;
721
722                 Vector JavaDoc l;
723                 synchronized (textListeners) { l = (Vector JavaDoc)textListeners.clone(); }
724
725                 int size = l.size();
726                 for (int i = 0; i < size; i++)
727                     ((TextListener JavaDoc)l.elementAt(i)).textValueChanged(event);
728                 }
729             }
730     }
731
732     //
733
// Create a URL object from either a URL string or a plain file name.
734
//
735
static URL JavaDoc createURL(String JavaDoc name) throws Exception JavaDoc {
736         try {
737                 URL JavaDoc u = new URL JavaDoc(name);
738                 return u;
739         } catch (MalformedURLException JavaDoc ex) {
740         }
741         URL JavaDoc u = new URL JavaDoc("file:" + new File JavaDoc(name).getAbsolutePath());
742         return u;
743     }
744     
745     /**
746      * The ErrorStorer maps Nodes to errors. It receives a reference
747      * to the ErrorTreeFactory in the Constructor.
748      *
749      * When error is called, it asks the
750      * ErrorTreeFactory for the current node, and uses this as the
751      * "key" of a Hashtable, with the error as a value. The error
752      * value is wrapped up nicely in an ParseError object.
753      *
754      * It is used in the XML Tutorial to illustrate how to implement
755      * the ErrorListener to provide error storage for later reference.
756      *
757      */

758     class ErrorStorer
759         implements ErrorHandler JavaDoc
760         
761     {
762
763         //
764
// Data
765
//
766
Hashtable JavaDoc errorNodes = null;
767         
768         /**
769          * Constructor
770          */

771         public ErrorStorer() {
772         }
773
774         /**
775          * The client is is allowed to get a reference to the Hashtable,
776          * and so could corrupt it, or add to it...
777          */

778         public Hashtable JavaDoc getErrorNodes() {
779             return errorNodes;
780         }
781
782         /**
783          * The ParseError object for the node key is returned.
784          * If the node doesn't have errors, null is returned.
785          */

786         public Object JavaDoc getError(Node JavaDoc node) {
787             if (errorNodes == null)
788                 return null;
789             return errorNodes.get(node);
790         }
791         
792         /**
793          * Reset the error storage.
794          */

795         public void resetErrors() {
796             if (errorNodes != null)
797             errorNodes.clear();
798         }
799         
800         /***/
801         public void warning(SAXParseException JavaDoc ex) {
802             handleError(ex, WARNING);
803         }
804
805         public void error(SAXParseException JavaDoc ex) {
806             handleError(ex, ERROR);
807         }
808
809         public void fatalError(SAXParseException JavaDoc ex) throws SAXException JavaDoc {
810             handleError(ex, FATAL_ERROR);
811         }
812         
813         private void handleError(SAXParseException JavaDoc ex, int type) {
814             System.out.println("!!! handleError: "+ex.getMessage());
815
816             StringBuffer JavaDoc errorString = new StringBuffer JavaDoc();
817             errorString.append("at line number, ");
818             errorString.append(ex.getLineNumber());
819             errorString.append(": ");
820             errorString.append(ex.getMessage());
821
822             // Node current = parser.getCurrentNode();
823

824             Node JavaDoc current = null ;
825
826             try
827               {
828               current = ( Node JavaDoc ) parser.getProperty( "http://apache.org/xml/properties/dom/current-element-node" );
829               
830               }
831             catch( SAXException JavaDoc exception )
832               {
833                ;
834               }
835
836             if (current == null) {
837                 System.err.println("Error in handleError. getCurrentNode()==null!");
838                 return;
839             }
840             
841             if (errorNodes == null)
842                 errorNodes = new Hashtable JavaDoc();
843             ParseError previous = (ParseError) errorNodes.get(current);
844             ParseError eip = null;
845             // if a Node already has an error, we accumulate the text here...
846
if (previous != null) {
847                 eip = previous;
848                 errorString = new StringBuffer JavaDoc(previous.getMsg()+"\n"+errorString.toString());
849                 eip.setMsg(errorString.toString());
850             } else {
851                 eip = new
852                     ParseError(
853                         ex.getSystemId(),
854                         ex.getLineNumber(),
855                         ex.getColumnNumber(),
856                         "",
857                         errorString.toString());
858             }
859
860             // put it in the Hashtable.
861
errorNodes.put(current, eip);
862         }
863         
864     }
865     
866     /**
867      * The ParseError class wraps up all the error info from
868      * the ErrorStorer's error method.
869      *
870      * @see ErrorStorer
871      */

872     class ParseError extends Object JavaDoc {
873
874         //
875
// Data
876
//
877

878         String JavaDoc fileName;
879         int lineNo;
880         int charOffset;
881         Object JavaDoc key;
882         String JavaDoc msg;
883
884         /**
885          * Constructor
886          */

887         public ParseError(String JavaDoc fileName, int lineNo, int charOffset,
888                            Object JavaDoc key,
889                            String JavaDoc msg)
890         {
891             this. fileName=fileName;
892             this. lineNo=lineNo;
893             this. charOffset=charOffset;
894             this. key=key;
895             this. msg=msg;
896         }
897
898         //
899
// Getters...
900
//
901
public String JavaDoc getFileName() { return fileName; }
902         public int getLineNo() { return lineNo; }
903         public int getCharOffset() { return charOffset;}
904         public Object JavaDoc getKey() { return key; }
905         public String JavaDoc getMsg() { return msg; }
906         public void setMsg(String JavaDoc s) { msg = s; }
907     }
908
909
910     //
911
// Main
912
//
913

914     /** Main program entry point. */
915     public static void main(String JavaDoc argv[]) {
916         
917         // vars
918
int parserNameIndex = -1;
919         String JavaDoc parserName = DEFAULT_PARSER_NAME;
920
921         // check parameters
922
for (int i = 0; i < argv.length; i++) {
923             String JavaDoc arg = argv[i];
924
925             // options
926
if (arg.startsWith("-")) {
927                 if (arg.equals("-p")) {
928                     if (i == argv.length - 1) {
929                         System.err.println("error: missing parser class");
930                         System.exit(1);
931                     }
932                     parserName = argv[++i];
933                     parserNameIndex = i;
934                     continue;
935                 }
936
937                 if (arg.equals("-h")) {
938                     printUsage();
939                     System.exit(1);
940                 }
941             }
942
943             // print uri
944
System.err.println(arg+':');
945    
946             JFrame JavaDoc frame = null;
947             if (parserNameIndex == argv.length-1) {
948                 // null behaviour is blank screen - eg no JTree, or file dispalyed
949
frame = new TreeView("");
950             } else {
951                 frame = new TreeView(arg);
952             }
953             frame.addWindowListener(new java.awt.event.WindowAdapter JavaDoc() {
954              public void windowClosing(java.awt.event.WindowEvent JavaDoc e) {
955                  System.exit(0);
956              }
957             });
958             frame.setSize(790, 590);
959             frame.setVisible(true);
960         }
961     } // main(String[])
962

963     /** Prints the usage. */
964     private static void printUsage() {
965
966         System.err.println("usage: java ui.TreeViewer (options) uri ...");
967         System.err.println();
968         System.err.println("options:");
969         System.err.println(" -p name Specify DOM parser class by name.");
970         System.err.println(" Default parser: "+DEFAULT_PARSER_NAME);
971         System.err.println(" -h This help screen.");
972
973     } // printUsage()
974

975 } // class TreeViewer
976
Popular Tags