001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library is distributed in the hope that it will be useful,
011   but WITHOUT ANY WARRANTY; without even the implied warranty of
012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: DocumentBrowserView.java,v $
023   Revision 1.6  2004/05/31 07:48:58  markl
024   rewritten to use new kiwi.ui.model package.
025
026   Revision 1.5  2003/01/19 09:46:47  markl
027   replaced JScrollPane instances with KScrollPane.
028
029   Revision 1.4  2001/03/12 09:27:54  markl
030   Source code and Javadoc cleanup.
031
032   Revision 1.3  2000/07/31 02:02:35  markl
033   Made root node invisible.
034
035   Revision 1.2  1999/01/10 02:05:37  markl
036   added GPL header & RCS tag
037   ----------------------------------------------------------------------------
038*/
039
040package kiwi.ui;
041
042import java.awt.*;
043import java.util.*;
044import javax.swing.*;
045import javax.swing.event.*;
046import javax.swing.text.*;
047import javax.swing.tree.*;
048import java.net.URL;
049
050import kiwi.ui.model.*;
051
052/** This class represents a general-purpose browser component for viewing a
053  * hierarchically-organized collection of documents. The interface consists of
054  * a split pane with a tree component in the left pane and an HTML component
055  * in the right pane.
056  *
057  * <p><center>
058  * <img src="snapshot/DocumentBrowserView.gif"><br>
059  * <i>An example DocumentBrowserView.</i>
060  * </center>
061  *
062  * @see kiwi.ui.DocumentBrowserFrame
063  *
064  * @author Mark Lindner
065  */
066
067public class DocumentBrowserView extends KPanel
068  {
069  private JTree tree = null;
070  private JEditorPane html = null;
071  private KTreeModelTreeAdapter adapter;
072  private KTreeModel model;
073  
074  /** Construct a new <code>DocumentBrowserView</code>.
075    *
076    * @param model The tree data model for this browser.
077    */
078
079  public DocumentBrowserView(KTreeModel model)
080    {
081    this.model = model;
082    setLayout(new GridLayout(1, 0));
083    JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
084    split.setOpaque(false);
085    add(split);
086
087    tree = new JTree();
088    tree.setBackground(Color.white);
089    tree.setRootVisible(false);
090    KScrollPane scroll = new KScrollPane(tree);
091
092    adapter = new KTreeModelTreeAdapter(tree);
093    adapter.setTreeModel(model);
094
095    tree.setModel(adapter);
096    tree.setCellRenderer(new KTreeModelTreeCellRenderer(model));
097    
098
099    split.setLeftComponent(scroll);
100
101    html = new JEditorPane();
102    html.setBackground(Color.white);
103    html.setEditable(false);
104
105    html.addHyperlinkListener(new HyperlinkListener()
106      {
107      public void hyperlinkUpdate(HyperlinkEvent evt)
108        {
109        if(evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
110          {
111          Object nodes[] = nodesForPath(evt.getURL().getFile());
112          if(nodes != null)
113            {
114            expandNodes(nodes);
115            showNode((DocumentDataSource.DocumentNode)nodes[nodes.length - 1]);
116            }
117          }
118        }
119      });
120
121    scroll = new KScrollPane(html);
122    scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants
123                                        .HORIZONTAL_SCROLLBAR_AS_NEEDED);
124    split.setRightComponent(scroll);
125
126    split.setDividerLocation(150);
127    
128    DefaultTreeSelectionModel ts = new DefaultTreeSelectionModel();
129    ts.setSelectionMode(ts.SINGLE_TREE_SELECTION);
130
131    tree.addTreeSelectionListener(new TreeSelectionListener()
132      {
133      public void valueChanged(TreeSelectionEvent evt)
134        {
135        Object item = evt.getPath().getLastPathComponent();
136        if(item instanceof DocumentDataSource.DocumentNode)
137          {
138          DocumentDataSource.DocumentNode helpNode
139            = (DocumentDataSource.DocumentNode)item;
140          if(! helpNode.isExpandable())
141            showNode(helpNode);
142          }
143        }
144      });
145    }
146  
147  /** Display a specific page in the browser.
148    *
149    * @param page The URL of the page to display.
150    */
151
152  private void showNode(DocumentDataSource.DocumentNode node)
153    {
154    try
155      {
156      html.setPage(node.getURL());
157      }
158    catch(java.io.IOException ex)
159      {
160      // more graceful way to handle this?
161      ex.printStackTrace();
162      }
163    }
164
165  /*
166   */
167  
168  private void expandNodes(Object nodes[])
169    {
170    TreePath path = adapter.getPathForNode(nodes[nodes.length - 1]);
171    if(path != null)
172      {
173      tree.scrollPathToVisible(path);
174      tree.setSelectionPath(path);
175      }
176    }
177
178  /*
179   */
180
181  private Object[] nodesForPath(String path)
182    {
183    System.out.println("nodesForPath: " + path);
184    
185    StringTokenizer st = new StringTokenizer(path, "/");
186    Object curNode = model.getRoot();
187    Vector v = new Vector();
188
189LOOP:
190
191    for(;;)
192      {
193      v.addElement(curNode);
194
195      if(! model.isExpandable(curNode))
196         break;
197      
198      if(!st.hasMoreTokens())
199        break;
200
201      String s = st.nextToken();
202
203      model.preloadChildren(curNode);
204      Iterator iter = model.getChildren(curNode);
205      while(iter.hasNext())
206        {
207        Object node = iter.next();
208        
209        String file = ((DocumentDataSource.DocumentNode)node).getFile();
210
211        if(s.equals(file))
212          {
213          curNode = node;
214          continue LOOP;
215          }
216        }
217
218      return(null);
219      }
220
221    if(st.hasMoreTokens())
222      return(null);
223    
224    Object n[] = new Object[v.size()];
225    v.copyInto(n);
226
227    return(n);
228    }
229  
230  }
231
232/* end of source file */