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: DocumentDataSource.java,v $ 023 Revision 1.7 2004/05/31 07:30:26 markl 024 Final cleanup and bugfixes of kiwi.ui.model. 025 026 Revision 1.6 2004/03/23 06:49:44 markl 027 Use Boolean.valueOf(), not new Boolean() 028 029 Revision 1.5 2003/01/19 09:33:06 markl 030 Javadoc & comment header updates. 031 032 Revision 1.4 2001/03/12 04:11:41 markl 033 Source code cleanup. 034 035 Revision 1.3 2000/07/31 02:02:13 markl 036 Modified to use a document icon for non-expandable nodes. 037 038 Revision 1.2 1999/01/10 03:12:19 markl 039 added GPL header & RCS tag 040 ---------------------------------------------------------------------------- 041*/ 042 043package kiwi.ui.model; 044 045import java.io.*; 046import java.net.*; 047import java.util.*; 048import javax.swing.*; 049 050import kiwi.util.*; 051 052/** This class is an implementation of <code>TreeDataSource</code> 053 * in which tree nodes represent HTML documents that are loaded as system 054 * resources. 055 * <p> 056 * Documents are loaded using the provided <code>ResourceManager</code>. The 057 * default base path for the documents is "docs/", and since they are loaded 058 * as URL resources, they should be located relative to "html/docs/" which in 059 * turn will be relative to the <code>ResourceManager</code>'s resource anchor 060 * class. One form of the constructor allows an alternate base path to be 061 * specified. 062 * <p> 063 * Documents may be organized in a hierarchy; each expandable node in the 064 * hierarchy corresponds to a directory in the resource file tree. Each 065 * directory (including the root directory, "docs/") is expected to contain 066 * an index file named "_index.txt" describing the child nodes of that 067 * directory. Nodes are listed in this file, one per line. Each line should 068 * include the following fields, delimited by vertical bar characters (|): 069 * <p> 070 * <dl> 071 * <dt>Icon name 072 * <dd>The name of the icon for this node. If an asterisk (*) is specified 073 * for the name, a default icon will be used. 074 * <dt>Alternate Icon name 075 * <dd>The name of an alternate icon for this node. This is the icon that 076 * is used to display expanded nodes. If an asterisk (*) is specified for the 077 * name, a default icon will be used. If a dash (-) is specified for the name, 078 * the alternate icon will be the same as the normal icon (above). 079 * <dt>Expandability flag 080 * <dd>One of the characters '+' or '-', denoting expandable and 081 * non-expandable, respectively. 082 * <dt>Node label 083 * <dd>A human-readable, brief textual description of the node. 084 * <dt>File 085 * <dd>The file corresponding to this resource--either a directory name if 086 * this is an expandable node, or a filename if this is a leaf (document) 087 * node. 088 * </dl> 089 * <p> 090 * Here is an example entry: 091 * <p> 092 * <tt>book-closed.gif|book-open.gif|+|API Specification|api</tt> 093 * 094 * @see kiwi.util.ResourceManager 095 * @see kiwi.ui.DocumentBrowserView 096 * @see kiwi.ui.DocumentBrowserFrame 097 * 098 * @author Mark Lindner 099 */ 100 101public class DocumentDataSource implements TreeDataSource 102 { 103 private ResourceManager resmgr; 104 private String basePath; 105 private DocumentNode root; 106 private static Icon DOCUMENT_ICON = KiwiUtils.getResourceManager() 107 .getIcon("document.gif"); 108 private static Icon BOOKS_ICON = KiwiUtils.getResourceManager() 109 .getIcon("books.gif"); 110 private static Icon UNKNOWN_ICON = KiwiUtils.getResourceManager() 111 .getIcon("document-unknown.gif"); 112 private static Icon BOOK_OPEN_ICON = KiwiUtils.getResourceManager() 113 .getIcon("book-open.gif"); 114 private static Icon BOOK_CLOSED_ICON = KiwiUtils.getResourceManager() 115 .getIcon("book-closed.gif"); 116 private static final String INDEX_FILE = "_index.txt"; 117 /** The default description of this set of documents. */ 118 public static final String DEFAULT_DESCRIPTION = "Help Topics"; 119 /** The default relative document base path. */ 120 public static final String DEFAULT_BASEPATH = "docs/"; 121 122 /** Construct a new <code>DocumentDataSource</code> with a default 123 * description and base path. 124 * 125 * @param manager the <code>ResourceManager</code> that will be used to load 126 * index files for the tree. 127 */ 128 129 public DocumentDataSource(ResourceManager manager) 130 { 131 this(manager, DEFAULT_DESCRIPTION, DEFAULT_BASEPATH); 132 } 133 134 /** Construct a new <code>DocumentDataSource</code> with the specified 135 * description and base path. 136 * 137 * @param manager The <code>ResourceManager</code> that will be used to load 138 * index files for the tree. 139 * @param description A brief description of this set of documents; this 140 * becomes the label for the root node in the tree. 141 */ 142 143 public DocumentDataSource(ResourceManager manager, String description, 144 String basePath) 145 { 146 this.resmgr = manager; 147 if(! basePath.endsWith("/")) 148 basePath += "/"; 149 this.basePath = basePath; 150 151 URL rootURL = resmgr.getURL(basePath + INDEX_FILE); 152 root = new DocumentNode(null, description, BOOKS_ICON, null, rootURL, 153 true, ""); 154 } 155 156 /** Get the root object. */ 157 158 public Object getRoot() 159 { 160 return(root); 161 } 162 163 /** Get the children of a given node. */ 164 165 public Object[] getChildren(Object node) 166 { 167 DocumentNode n = (DocumentNode)node; 168 Vector children = new Vector(); 169 170 try 171 { 172 String s; 173 DocumentNode sect; 174 175 InputStream is = n.getURL().openStream(); 176 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 177 178 while((s = reader.readLine()) != null) 179 { 180 if((sect = parseLine(n, s)) != null) 181 children.addElement(sect); 182 } 183 reader.close(); 184 is.close(); 185 } 186 catch(IOException ex) 187 { 188 } 189 190 Object childlist[] = new Object[children.size()]; 191 children.copyInto(childlist); 192 193 return(childlist); 194 } 195 196 public boolean isExpandable(Object node) 197 { 198 DocumentNode doc = (DocumentNode)node; 199 200 return(doc.isExpandable()); 201 } 202 203 public Icon getIcon(Object node, boolean isExpanded) 204 { 205 DocumentNode doc = (DocumentNode)node; 206 207 return(isExpanded ? doc.getAltIcon() : doc.getIcon()); 208 } 209 210 public String getLabel(Object node) 211 { 212 DocumentNode doc = (DocumentNode)node; 213 214 return(doc.getLabel()); 215 } 216 217 /** Get the value for a given property. */ 218 219 public Object getValueForProperty(Object node, String property) 220 { 221 return(null); 222 } 223 224 /* parse a line of an index file */ 225 226 private DocumentNode parseLine(DocumentNode parent, String line) 227 { 228 StringTokenizer st = new StringTokenizer(line, "|"); 229 if(st.countTokens() != 5) return(null); 230 231 String file; 232 String iconName = st.nextToken(); 233 String altIconName = st.nextToken(); 234 boolean expandable = st.nextToken().equals("+"); 235 URL url; 236 237 Icon icon = null, alticon = null; 238 239 if(iconName.equals("*")) 240 icon = (expandable ? BOOK_CLOSED_ICON : DOCUMENT_ICON); 241 else 242 icon = resmgr.getIcon(iconName); 243 244 if(altIconName.equals("*")) 245 alticon = (expandable ? BOOK_OPEN_ICON : DOCUMENT_ICON); 246 else if(!altIconName.equals("-")) 247 alticon = resmgr.getIcon(altIconName); 248 249 String label = st.nextToken(); 250 251 try 252 { 253 String parentURL = parent.getURL().toString(); 254 int idx = parentURL.lastIndexOf("/"); 255 file = st.nextToken(); 256 String temp = parentURL.substring(0, idx) + "/" + file; 257 if(expandable) 258 temp += "/" + INDEX_FILE; 259 url = new URL(temp); 260 } 261 catch(MalformedURLException ex) 262 { 263 return(null); 264 } 265 266 return(new DocumentNode(parent, label, icon, alticon, url, expandable, 267 file)); 268 } 269 270 /* Internal class for managing help nodes. */ 271 272 public class DocumentNode 273 { 274 private String label, file; 275 private Icon icon, alticon; 276 private URL url; 277 private boolean expandable; 278 private DocumentNode parent = null; 279 280 DocumentNode(DocumentNode parent, String label, Icon icon, Icon alticon, 281 URL url, boolean expandable, String file) 282 { 283 this.label = label; 284 this.icon = ((icon != null) ? icon : UNKNOWN_ICON); 285 this.alticon = ((alticon != null) ? alticon : this.icon); 286 this.url = url; 287 this.expandable = expandable; 288 this.file = file; 289 } 290 291 public DocumentNode getParent() 292 { 293 return(parent); 294 } 295 296 public String getFile() 297 { 298 return(file); 299 } 300 301 public boolean isExpandable() 302 { 303 return(expandable); 304 } 305 306 public String getLabel() 307 { 308 return(label); 309 } 310 311 public Icon getIcon() 312 { 313 return(icon); 314 } 315 316 public Icon getAltIcon() 317 { 318 return(alticon); 319 } 320 321 public URL getURL() 322 { 323 return(url); 324 } 325 } 326 327 } 328 329/* end of source file */