PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/help/HelpTOCPanel.java

#
Java | 435 lines | 301 code | 57 blank | 77 comment | 36 complexity | f1584178180ef5daffa855fd10ea9608 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * HelpTOCPanel.java - Help table of contents
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2004 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.help;
  23. //{{{ Imports
  24. import javax.swing.*;
  25. import javax.swing.border.*;
  26. import javax.swing.tree.*;
  27. import java.awt.*;
  28. import java.awt.event.*;
  29. import java.io.*;
  30. import java.net.*;
  31. import java.util.*;
  32. import org.xml.sax.Attributes;
  33. import org.xml.sax.InputSource;
  34. import org.xml.sax.helpers.DefaultHandler;
  35. import org.gjt.sp.jedit.browser.FileCellRenderer; // for icons
  36. import org.gjt.sp.jedit.io.VFSManager;
  37. import org.gjt.sp.jedit.*;
  38. import org.gjt.sp.util.Log;
  39. //}}}
  40. public class HelpTOCPanel extends JPanel
  41. {
  42. //{{{ HelpTOCPanel constructor
  43. public HelpTOCPanel(HelpViewerInterface helpViewer)
  44. {
  45. super(new BorderLayout());
  46. this.helpViewer = helpViewer;
  47. nodes = new Hashtable();
  48. toc = new TOCTree();
  49. // looks bad with the OS X L&F, apparently...
  50. if(!OperatingSystem.isMacOSLF())
  51. toc.putClientProperty("JTree.lineStyle", "Angled");
  52. toc.setCellRenderer(new TOCCellRenderer());
  53. toc.setEditable(false);
  54. toc.setShowsRootHandles(true);
  55. add(BorderLayout.CENTER,new JScrollPane(toc));
  56. load();
  57. } //}}}
  58. //{{{ selectNode() method
  59. public void selectNode(String shortURL)
  60. {
  61. if(tocModel == null)
  62. return;
  63. DefaultMutableTreeNode node = (DefaultMutableTreeNode)nodes.get(shortURL);
  64. if(node == null)
  65. return;
  66. TreePath path = new TreePath(tocModel.getPathToRoot(node));
  67. toc.expandPath(path);
  68. toc.setSelectionPath(path);
  69. toc.scrollPathToVisible(path);
  70. } //}}}
  71. //{{{ load() method
  72. public void load()
  73. {
  74. DefaultTreeModel empty = new DefaultTreeModel(
  75. new DefaultMutableTreeNode(
  76. jEdit.getProperty("helpviewer.toc.loading")));
  77. toc.setModel(empty);
  78. toc.setRootVisible(true);
  79. VFSManager.runInWorkThread(new Runnable()
  80. {
  81. public void run()
  82. {
  83. createTOC();
  84. tocModel.reload(tocRoot);
  85. toc.setModel(tocModel);
  86. toc.setRootVisible(false);
  87. for(int i = 0; i <tocRoot.getChildCount(); i++)
  88. {
  89. DefaultMutableTreeNode node =
  90. (DefaultMutableTreeNode)
  91. tocRoot.getChildAt(i);
  92. toc.expandPath(new TreePath(
  93. node.getPath()));
  94. }
  95. if(helpViewer.getShortURL() != null)
  96. selectNode(helpViewer.getShortURL());
  97. }
  98. });
  99. } //}}}
  100. //{{{ Private members
  101. private HelpViewerInterface helpViewer;
  102. private DefaultTreeModel tocModel;
  103. private DefaultMutableTreeNode tocRoot;
  104. private JTree toc;
  105. private Hashtable nodes;
  106. //{{{ createNode() method
  107. private DefaultMutableTreeNode createNode(String href, String title)
  108. {
  109. DefaultMutableTreeNode node = new DefaultMutableTreeNode(
  110. new HelpNode(href,title),true);
  111. nodes.put(href,node);
  112. return node;
  113. } //}}}
  114. //{{{ createTOC() method
  115. private void createTOC()
  116. {
  117. EditPlugin[] plugins = jEdit.getPlugins();
  118. Arrays.sort(plugins,new PluginCompare());
  119. tocRoot = new DefaultMutableTreeNode();
  120. tocRoot.add(createNode("welcome.html",
  121. jEdit.getProperty("helpviewer.toc.welcome")));
  122. tocRoot.add(createNode("README.txt",
  123. jEdit.getProperty("helpviewer.toc.readme")));
  124. tocRoot.add(createNode("CHANGES.txt",
  125. jEdit.getProperty("helpviewer.toc.changes")));
  126. tocRoot.add(createNode("TODO.txt",
  127. jEdit.getProperty("helpviewer.toc.todo")));
  128. tocRoot.add(createNode("COPYING.txt",
  129. jEdit.getProperty("helpviewer.toc.copying")));
  130. tocRoot.add(createNode("COPYING.DOC.txt",
  131. jEdit.getProperty("helpviewer.toc.copying-doc")));
  132. tocRoot.add(createNode("Apache.LICENSE.txt",
  133. jEdit.getProperty("helpviewer.toc.copying-apache")));
  134. tocRoot.add(createNode("COPYING.PLUGINS.txt",
  135. jEdit.getProperty("helpviewer.toc.copying-plugins")));
  136. loadTOC(tocRoot,"news42/toc.xml");
  137. loadTOC(tocRoot,"users-guide/toc.xml");
  138. loadTOC(tocRoot,"FAQ/toc.xml");
  139. loadTOC(tocRoot,"api/toc.xml");
  140. DefaultMutableTreeNode pluginTree = new DefaultMutableTreeNode(
  141. jEdit.getProperty("helpviewer.toc.plugins"),true);
  142. for(int i = 0; i < plugins.length; i++)
  143. {
  144. EditPlugin plugin = plugins[i];
  145. String name = plugin.getClassName();
  146. String docs = jEdit.getProperty("plugin." + name + ".docs");
  147. String label = jEdit.getProperty("plugin." + name + ".name");
  148. if(docs != null)
  149. {
  150. if(label != null && docs != null)
  151. {
  152. String path = plugin.getPluginJAR()
  153. .getClassLoader()
  154. .getResourceAsPath(docs);
  155. pluginTree.add(createNode(
  156. path,label));
  157. }
  158. }
  159. }
  160. if(pluginTree.getChildCount() != 0)
  161. tocRoot.add(pluginTree);
  162. else
  163. {
  164. // so that HelpViewer constructor doesn't try to expand
  165. pluginTree = null;
  166. }
  167. tocModel = new DefaultTreeModel(tocRoot);
  168. } //}}}
  169. //{{{ loadTOC() method
  170. private void loadTOC(DefaultMutableTreeNode root, String path)
  171. {
  172. TOCHandler h = new TOCHandler(root,MiscUtilities.getParentOfPath(path));
  173. try
  174. {
  175. MiscUtilities.parseXML(
  176. new URL(helpViewer.getBaseURL()
  177. + '/' + path).openStream(), h);
  178. }
  179. catch(IOException e)
  180. {
  181. Log.log(Log.ERROR,this,e);
  182. }
  183. } //}}}
  184. //}}}
  185. //{{{ HelpNode class
  186. static class HelpNode
  187. {
  188. String href, title;
  189. //{{{ HelpNode constructor
  190. HelpNode(String href, String title)
  191. {
  192. this.href = href;
  193. this.title = title;
  194. } //}}}
  195. //{{{ toString() method
  196. public String toString()
  197. {
  198. return title;
  199. } //}}}
  200. } //}}}
  201. //{{{ TOCHandler class
  202. class TOCHandler extends DefaultHandler
  203. {
  204. String dir;
  205. //{{{ TOCHandler constructor
  206. TOCHandler(DefaultMutableTreeNode root, String dir)
  207. {
  208. nodes = new Stack();
  209. node = root;
  210. this.dir = dir;
  211. } //}}}
  212. //{{{ characters() method
  213. public void characters(char[] c, int off, int len)
  214. {
  215. if(tag.equals("TITLE"))
  216. {
  217. boolean firstNonWhitespace = false;
  218. for(int i = 0; i < len; i++)
  219. {
  220. char ch = c[off + i];
  221. if (!firstNonWhitespace && Character.isWhitespace(ch)) continue;
  222. firstNonWhitespace = true;
  223. title.append(ch);
  224. }
  225. }
  226. } //}}}
  227. //{{{ startElement() method
  228. public void startElement(String uri, String localName,
  229. String name, Attributes attrs)
  230. {
  231. tag = name;
  232. if (name.equals("ENTRY"))
  233. href = attrs.getValue("HREF");
  234. } //}}}
  235. //{{{ endElement() method
  236. public void endElement(String uri, String localName, String name)
  237. {
  238. if(name == null)
  239. return;
  240. if(name.equals("TITLE"))
  241. {
  242. DefaultMutableTreeNode newNode = createNode(
  243. dir + href,title.toString());
  244. node.add(newNode);
  245. nodes.push(node);
  246. node = newNode;
  247. title.setLength(0);
  248. }
  249. else if(name.equals("ENTRY"))
  250. {
  251. node = (DefaultMutableTreeNode)nodes.pop();
  252. href = null;
  253. }
  254. } //}}}
  255. //{{{ Private members
  256. private String tag;
  257. private StringBuffer title = new StringBuffer();
  258. private String href;
  259. private DefaultMutableTreeNode node;
  260. private Stack nodes;
  261. //}}}
  262. } //}}}
  263. //{{{ TOCTree class
  264. class TOCTree extends JTree
  265. {
  266. //{{{ TOCTree constructor
  267. TOCTree()
  268. {
  269. ToolTipManager.sharedInstance().registerComponent(this);
  270. } //}}}
  271. //{{{ getToolTipText() method
  272. public final String getToolTipText(MouseEvent evt)
  273. {
  274. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  275. if(path != null)
  276. {
  277. Rectangle cellRect = getPathBounds(path);
  278. if(cellRect != null && !cellRectIsVisible(cellRect))
  279. return path.getLastPathComponent().toString();
  280. }
  281. return null;
  282. } //}}}
  283. //{{{ getToolTipLocation() method
  284. /* public final Point getToolTipLocation(MouseEvent evt)
  285. {
  286. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  287. if(path != null)
  288. {
  289. Rectangle cellRect = getPathBounds(path);
  290. if(cellRect != null && !cellRectIsVisible(cellRect))
  291. {
  292. return new Point(cellRect.x + 14, cellRect.y);
  293. }
  294. }
  295. return null;
  296. } */ //}}}
  297. //{{{ processMouseEvent() method
  298. protected void processMouseEvent(MouseEvent evt)
  299. {
  300. //ToolTipManager ttm = ToolTipManager.sharedInstance();
  301. switch(evt.getID())
  302. {
  303. /* case MouseEvent.MOUSE_ENTERED:
  304. toolTipInitialDelay = ttm.getInitialDelay();
  305. toolTipReshowDelay = ttm.getReshowDelay();
  306. ttm.setInitialDelay(200);
  307. ttm.setReshowDelay(0);
  308. super.processMouseEvent(evt);
  309. break;
  310. case MouseEvent.MOUSE_EXITED:
  311. ttm.setInitialDelay(toolTipInitialDelay);
  312. ttm.setReshowDelay(toolTipReshowDelay);
  313. super.processMouseEvent(evt);
  314. break; */
  315. case MouseEvent.MOUSE_CLICKED:
  316. TreePath path = getPathForLocation(evt.getX(),evt.getY());
  317. if(path != null)
  318. {
  319. if(!isPathSelected(path))
  320. setSelectionPath(path);
  321. Object obj = ((DefaultMutableTreeNode)
  322. path.getLastPathComponent())
  323. .getUserObject();
  324. if(!(obj instanceof HelpNode))
  325. {
  326. this.expandPath(path);
  327. return;
  328. }
  329. HelpNode node = (HelpNode)obj;
  330. helpViewer.gotoURL(node.href,true,0);
  331. }
  332. super.processMouseEvent(evt);
  333. break;
  334. default:
  335. super.processMouseEvent(evt);
  336. break;
  337. }
  338. } //}}}
  339. //{{{ cellRectIsVisible() method
  340. private boolean cellRectIsVisible(Rectangle cellRect)
  341. {
  342. Rectangle vr = TOCTree.this.getVisibleRect();
  343. return vr.contains(cellRect.x,cellRect.y) &&
  344. vr.contains(cellRect.x + cellRect.width,
  345. cellRect.y + cellRect.height);
  346. } //}}}
  347. } //}}}
  348. //{{{ TOCCellRenderer class
  349. class TOCCellRenderer extends DefaultTreeCellRenderer
  350. {
  351. EmptyBorder border = new EmptyBorder(1,0,1,1);
  352. public Component getTreeCellRendererComponent(JTree tree,
  353. Object value, boolean sel, boolean expanded,
  354. boolean leaf, int row, boolean focus)
  355. {
  356. super.getTreeCellRendererComponent(tree,value,sel,
  357. expanded,leaf,row,focus);
  358. setIcon(leaf ? FileCellRenderer.fileIcon
  359. : (expanded ? FileCellRenderer.openDirIcon
  360. : FileCellRenderer.dirIcon));
  361. setBorder(border);
  362. return this;
  363. }
  364. } //}}}
  365. //{{{ PluginCompare class
  366. static class PluginCompare implements Comparator
  367. {
  368. public int compare(Object o1, Object o2)
  369. {
  370. EditPlugin p1 = (EditPlugin)o1;
  371. EditPlugin p2 = (EditPlugin)o2;
  372. return MiscUtilities.compareStrings(
  373. jEdit.getProperty("plugin." + p1.getClassName() + ".name"),
  374. jEdit.getProperty("plugin." + p2.getClassName() + ".name"),
  375. true);
  376. }
  377. } //}}}
  378. }