1 22 23 package org.gjt.sp.jedit.help; 24 25 import javax.swing.*; 27 import javax.swing.border.*; 28 import javax.swing.tree.*; 29 import java.awt.*; 30 import java.awt.event.*; 31 import java.io.*; 32 import java.net.*; 33 import java.util.*; 34 35 import org.xml.sax.Attributes ; 36 import org.xml.sax.helpers.DefaultHandler ; 37 38 import org.gjt.sp.jedit.browser.FileCellRenderer; import org.gjt.sp.jedit.io.VFSManager; 40 import org.gjt.sp.jedit.*; 41 import org.gjt.sp.util.Log; 42 import org.gjt.sp.util.StandardUtilities; 43 import org.gjt.sp.util.XMLUtilities; 44 46 public class HelpTOCPanel extends JPanel 47 { 48 public HelpTOCPanel(HelpViewerInterface helpViewer) 50 { 51 super(new BorderLayout()); 52 53 this.helpViewer = helpViewer; 54 nodes = new Hashtable(); 55 56 toc = new TOCTree(); 57 58 if(!OperatingSystem.isMacOSLF()) 60 toc.putClientProperty("JTree.lineStyle", "Angled"); 61 62 toc.setCellRenderer(new TOCCellRenderer()); 63 toc.setEditable(false); 64 toc.setShowsRootHandles(true); 65 66 add(BorderLayout.CENTER,new JScrollPane(toc)); 67 68 load(); 69 } 71 public void selectNode(String shortURL) 73 { 74 if(tocModel == null) 75 return; 76 77 DefaultMutableTreeNode node = (DefaultMutableTreeNode)nodes.get(shortURL); 78 79 if(node == null) 80 return; 81 82 TreePath path = new TreePath(tocModel.getPathToRoot(node)); 83 toc.expandPath(path); 84 toc.setSelectionPath(path); 85 toc.scrollPathToVisible(path); 86 } 88 public void load() 90 { 91 DefaultTreeModel empty = new DefaultTreeModel( 92 new DefaultMutableTreeNode( 93 jEdit.getProperty("helpviewer.toc.loading"))); 94 toc.setModel(empty); 95 toc.setRootVisible(true); 96 97 VFSManager.runInWorkThread(new Runnable () 98 { 99 public void run() 100 { 101 createTOC(); 102 tocModel.reload(tocRoot); 103 toc.setModel(tocModel); 104 toc.setRootVisible(false); 105 for(int i = 0; i <tocRoot.getChildCount(); i++) 106 { 107 DefaultMutableTreeNode node = 108 (DefaultMutableTreeNode) 109 tocRoot.getChildAt(i); 110 toc.expandPath(new TreePath( 111 node.getPath())); 112 } 113 if(helpViewer.getShortURL() != null) 114 selectNode(helpViewer.getShortURL()); 115 } 116 }); 117 } 119 private HelpViewerInterface helpViewer; 121 private DefaultTreeModel tocModel; 122 private DefaultMutableTreeNode tocRoot; 123 private JTree toc; 124 private Hashtable nodes; 125 126 private DefaultMutableTreeNode createNode(String href, String title) 128 { 129 DefaultMutableTreeNode node = new DefaultMutableTreeNode( 130 new HelpNode(href,title),true); 131 nodes.put(href,node); 132 return node; 133 } 135 private void createTOC() 137 { 138 EditPlugin[] plugins = jEdit.getPlugins(); 139 Arrays.sort(plugins,new PluginCompare()); 140 tocRoot = new DefaultMutableTreeNode(); 141 142 tocRoot.add(createNode("welcome.html", 143 jEdit.getProperty("helpviewer.toc.welcome"))); 144 145 tocRoot.add(createNode("README.txt", 146 jEdit.getProperty("helpviewer.toc.readme"))); 147 tocRoot.add(createNode("CHANGES.txt", 148 jEdit.getProperty("helpviewer.toc.changes"))); 149 tocRoot.add(createNode("TODO.txt", 150 jEdit.getProperty("helpviewer.toc.todo"))); 151 tocRoot.add(createNode("COPYING.txt", 152 jEdit.getProperty("helpviewer.toc.copying"))); 153 tocRoot.add(createNode("COPYING.DOC.txt", 154 jEdit.getProperty("helpviewer.toc.copying-doc"))); 155 tocRoot.add(createNode("Apache.LICENSE.txt", 156 jEdit.getProperty("helpviewer.toc.copying-apache"))); 157 tocRoot.add(createNode("COPYING.PLUGINS.txt", 158 jEdit.getProperty("helpviewer.toc.copying-plugins"))); 159 160 loadTOC(tocRoot,"news43/toc.xml"); 161 loadTOC(tocRoot,"users-guide/toc.xml"); 162 loadTOC(tocRoot,"FAQ/toc.xml"); 163 loadTOC(tocRoot,"api/toc.xml"); 164 165 DefaultMutableTreeNode pluginTree = new DefaultMutableTreeNode( 166 jEdit.getProperty("helpviewer.toc.plugins"),true); 167 168 for(int i = 0; i < plugins.length; i++) 169 { 170 EditPlugin plugin = plugins[i]; 171 172 String name = plugin.getClassName(); 173 174 String docs = jEdit.getProperty("plugin." + name + ".docs"); 175 String label = jEdit.getProperty("plugin." + name + ".name"); 176 if(docs != null) 177 { 178 if(label != null && docs != null) 179 { 180 String path = plugin.getPluginJAR() 181 .getClassLoader() 182 .getResourceAsPath(docs); 183 pluginTree.add(createNode( 184 path,label)); 185 } 186 } 187 } 188 189 if(pluginTree.getChildCount() != 0) 190 tocRoot.add(pluginTree); 191 else 192 { 193 pluginTree = null; 195 } 196 197 tocModel = new DefaultTreeModel(tocRoot); 198 } 200 private void loadTOC(DefaultMutableTreeNode root, String path) 202 { 203 TOCHandler h = new TOCHandler(root,MiscUtilities.getParentOfPath(path)); 204 try 205 { 206 XMLUtilities.parseXML( 207 new URL(helpViewer.getBaseURL() 208 + '/' + path).openStream(), h); 209 } 210 catch(IOException e) 211 { 212 Log.log(Log.ERROR,this,e); 213 } 214 } 216 218 static class HelpNode 220 { 221 String href, title; 222 223 HelpNode(String href, String title) 225 { 226 this.href = href; 227 this.title = title; 228 } 230 public String toString() 232 { 233 return title; 234 } } 237 class TOCHandler extends DefaultHandler 239 { 240 String dir; 241 242 TOCHandler(DefaultMutableTreeNode root, String dir) 244 { 245 nodes = new Stack(); 246 node = root; 247 this.dir = dir; 248 } 250 public void characters(char[] c, int off, int len) 252 { 253 if(tag.equals("TITLE")) 254 { 255 boolean firstNonWhitespace = false; 256 for(int i = 0; i < len; i++) 257 { 258 char ch = c[off + i]; 259 if (!firstNonWhitespace && Character.isWhitespace(ch)) continue; 260 firstNonWhitespace = true; 261 title.append(ch); 262 } 263 } 264 265 266 } 268 public void startElement(String uri, String localName, 270 String name, Attributes attrs) 271 { 272 tag = name; 273 if (name.equals("ENTRY")) 274 href = attrs.getValue("HREF"); 275 } 277 public void endElement(String uri, String localName, String name) 279 { 280 if(name == null) 281 return; 282 283 if(name.equals("TITLE")) 284 { 285 DefaultMutableTreeNode newNode = createNode( 286 dir + href,title.toString()); 287 node.add(newNode); 288 nodes.push(node); 289 node = newNode; 290 title.setLength(0); 291 } 292 else if(name.equals("ENTRY")) 293 { 294 node = (DefaultMutableTreeNode)nodes.pop(); 295 href = null; 296 } 297 } 299 private String tag; 301 private StringBuffer title = new StringBuffer (); 302 private String href; 303 private DefaultMutableTreeNode node; 304 private Stack nodes; 305 } 308 class TOCTree extends JTree 310 { 311 TOCTree() 313 { 314 ToolTipManager.sharedInstance().registerComponent(this); 315 } 317 public final String getToolTipText(MouseEvent evt) 319 { 320 TreePath path = getPathForLocation(evt.getX(), evt.getY()); 321 if(path != null) 322 { 323 Rectangle cellRect = getPathBounds(path); 324 if(cellRect != null && !cellRectIsVisible(cellRect)) 325 return path.getLastPathComponent().toString(); 326 } 327 return null; 328 } 330 345 protected void processMouseEvent(MouseEvent evt) 347 { 348 350 switch(evt.getID()) 351 { 352 364 case MouseEvent.MOUSE_CLICKED: 365 TreePath path = getPathForLocation(evt.getX(),evt.getY()); 366 if(path != null) 367 { 368 if(!isPathSelected(path)) 369 setSelectionPath(path); 370 371 Object obj = ((DefaultMutableTreeNode) 372 path.getLastPathComponent()) 373 .getUserObject(); 374 if(!(obj instanceof HelpNode)) 375 { 376 this.expandPath(path); 377 return; 378 } 379 380 HelpNode node = (HelpNode)obj; 381 382 helpViewer.gotoURL(node.href,true,0); 383 } 384 385 super.processMouseEvent(evt); 386 break; 387 default: 388 super.processMouseEvent(evt); 389 break; 390 } 391 } 393 private boolean cellRectIsVisible(Rectangle cellRect) 395 { 396 Rectangle vr = TOCTree.this.getVisibleRect(); 397 return vr.contains(cellRect.x,cellRect.y) && 398 vr.contains(cellRect.x + cellRect.width, 399 cellRect.y + cellRect.height); 400 } } 403 class TOCCellRenderer extends DefaultTreeCellRenderer 405 { 406 EmptyBorder border = new EmptyBorder(1,0,1,1); 407 408 public Component getTreeCellRendererComponent(JTree tree, 409 Object value, boolean sel, boolean expanded, 410 boolean leaf, int row, boolean focus) 411 { 412 super.getTreeCellRendererComponent(tree,value,sel, 413 expanded,leaf,row,focus); 414 setIcon(leaf ? FileCellRenderer.fileIcon 415 : (expanded ? FileCellRenderer.openDirIcon 416 : FileCellRenderer.dirIcon)); 417 setBorder(border); 418 419 return this; 420 } 421 } 423 static class PluginCompare implements Comparator 425 { 426 public int compare(Object o1, Object o2) 427 { 428 EditPlugin p1 = (EditPlugin)o1; 429 EditPlugin p2 = (EditPlugin)o2; 430 return StandardUtilities.compareStrings( 431 jEdit.getProperty("plugin." + p1.getClassName() + ".name"), 432 jEdit.getProperty("plugin." + p2.getClassName() + ".name"), 433 true); 434 } 435 } } 437 | Popular Tags |