PageRenderTime 151ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/help/HelpTOCPanel.java

#
Java | 457 lines | 320 code | 57 blank | 80 comment | 39 complexity | b1fcd885610101d4c060d3223647b0be 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, 2000, 2001, 2002 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 com.microstar.xml.*;
  25. import javax.swing.*;
  26. import javax.swing.border.*;
  27. import javax.swing.tree.*;
  28. import java.awt.*;
  29. import java.awt.event.*;
  30. import java.io.*;
  31. import java.net.*;
  32. import java.util.*;
  33. import org.gjt.sp.jedit.browser.FileCellRenderer; // for icons
  34. import org.gjt.sp.jedit.io.VFSManager;
  35. import org.gjt.sp.jedit.*;
  36. import org.gjt.sp.util.Log;
  37. //}}}
  38. class HelpTOCPanel extends JPanel
  39. {
  40. //{{{ HelpTOCPanel constructor
  41. HelpTOCPanel(HelpViewer helpViewer)
  42. {
  43. super(new BorderLayout());
  44. this.helpViewer = helpViewer;
  45. nodes = new Hashtable();
  46. toc = new TOCTree();
  47. // looks bad with the OS X L&F, apparently...
  48. if(!OperatingSystem.isMacOSLF())
  49. toc.putClientProperty("JTree.lineStyle", "Angled");
  50. toc.setCellRenderer(new TOCCellRenderer());
  51. toc.setEditable(false);
  52. toc.setShowsRootHandles(true);
  53. add(BorderLayout.CENTER,new JScrollPane(toc));
  54. load();
  55. } //}}}
  56. //{{{ selectNode() method
  57. void selectNode(String shortURL)
  58. {
  59. if(tocModel == null)
  60. return;
  61. DefaultMutableTreeNode node = (DefaultMutableTreeNode)nodes.get(shortURL);
  62. if(node == null)
  63. return;
  64. TreePath path = new TreePath(tocModel.getPathToRoot(node));
  65. toc.expandPath(path);
  66. toc.setSelectionPath(path);
  67. toc.scrollPathToVisible(path);
  68. } //}}}
  69. //{{{ load() method
  70. void load()
  71. {
  72. DefaultTreeModel empty = new DefaultTreeModel(
  73. new DefaultMutableTreeNode(
  74. jEdit.getProperty("helpviewer.toc.loading")));
  75. toc.setModel(empty);
  76. toc.setRootVisible(true);
  77. VFSManager.runInWorkThread(new Runnable()
  78. {
  79. public void run()
  80. {
  81. createTOC();
  82. tocModel.reload(tocRoot);
  83. toc.setModel(tocModel);
  84. toc.setRootVisible(false);
  85. for(int i = 0; i <tocRoot.getChildCount(); i++)
  86. {
  87. DefaultMutableTreeNode node =
  88. (DefaultMutableTreeNode)
  89. tocRoot.getChildAt(i);
  90. toc.expandPath(new TreePath(
  91. node.getPath()));
  92. }
  93. if(helpViewer.getShortURL() != null)
  94. selectNode(helpViewer.getShortURL());
  95. }
  96. });
  97. } //}}}
  98. //{{{ Private members
  99. private HelpViewer helpViewer;
  100. private DefaultTreeModel tocModel;
  101. private DefaultMutableTreeNode tocRoot;
  102. private JTree toc;
  103. private Hashtable nodes;
  104. //{{{ createNode() method
  105. private DefaultMutableTreeNode createNode(String href, String title)
  106. {
  107. DefaultMutableTreeNode node = new DefaultMutableTreeNode(
  108. new HelpNode(href,title),true);
  109. nodes.put(href,node);
  110. return node;
  111. } //}}}
  112. //{{{ createTOC() method
  113. private void createTOC()
  114. {
  115. EditPlugin[] plugins = jEdit.getPlugins();
  116. Arrays.sort(plugins,new PluginCompare());
  117. tocRoot = new DefaultMutableTreeNode();
  118. tocRoot.add(createNode("welcome.html",
  119. jEdit.getProperty("helpviewer.toc.welcome")));
  120. tocRoot.add(createNode("README.txt",
  121. jEdit.getProperty("helpviewer.toc.readme")));
  122. tocRoot.add(createNode("CHANGES.txt",
  123. jEdit.getProperty("helpviewer.toc.changes")));
  124. tocRoot.add(createNode("TODO.txt",
  125. jEdit.getProperty("helpviewer.toc.todo")));
  126. tocRoot.add(createNode("COPYING.txt",
  127. jEdit.getProperty("helpviewer.toc.copying")));
  128. tocRoot.add(createNode("COPYING.DOC.txt",
  129. jEdit.getProperty("helpviewer.toc.copying-doc")));
  130. tocRoot.add(createNode("Apache.LICENSE.txt",
  131. jEdit.getProperty("helpviewer.toc.copying-apache")));
  132. loadTOC(tocRoot,"news42/toc.xml");
  133. loadTOC(tocRoot,"users-guide/toc.xml");
  134. loadTOC(tocRoot,"FAQ/toc.xml");
  135. loadTOC(tocRoot,"api/toc.xml");
  136. DefaultMutableTreeNode pluginTree = new DefaultMutableTreeNode(
  137. jEdit.getProperty("helpviewer.toc.plugins"),true);
  138. for(int i = 0; i < plugins.length; i++)
  139. {
  140. EditPlugin plugin = plugins[i];
  141. String name = plugin.getClassName();
  142. String docs = jEdit.getProperty("plugin." + name + ".docs");
  143. String label = jEdit.getProperty("plugin." + name + ".name");
  144. if(docs != null)
  145. {
  146. if(label != null && docs != null)
  147. {
  148. String path = plugin.getPluginJAR()
  149. .getClassLoader()
  150. .getResourceAsPath(docs);
  151. pluginTree.add(createNode(
  152. path,label));
  153. }
  154. }
  155. }
  156. if(pluginTree.getChildCount() != 0)
  157. tocRoot.add(pluginTree);
  158. else
  159. {
  160. // so that HelpViewer constructor doesn't try to expand
  161. pluginTree = null;
  162. }
  163. tocModel = new DefaultTreeModel(tocRoot);
  164. } //}}}
  165. //{{{ loadTOC() method
  166. private void loadTOC(DefaultMutableTreeNode root, String path)
  167. {
  168. TOCHandler h = new TOCHandler(root,MiscUtilities.getParentOfPath(path));
  169. XmlParser parser = new XmlParser();
  170. Reader in = null;
  171. parser.setHandler(h);
  172. try
  173. {
  174. in = new InputStreamReader(
  175. new URL(helpViewer.getBaseURL()
  176. + '/' + path).openStream());
  177. parser.parse(null, null, in);
  178. }
  179. catch(XmlException xe)
  180. {
  181. int line = xe.getLine();
  182. String message = xe.getMessage();
  183. Log.log(Log.ERROR,this,path + ':' + line
  184. + ": " + message);
  185. }
  186. catch(Exception e)
  187. {
  188. Log.log(Log.ERROR,this,e);
  189. }
  190. finally
  191. {
  192. try
  193. {
  194. if(in != null)
  195. in.close();
  196. }
  197. catch(IOException io)
  198. {
  199. Log.log(Log.ERROR,this,io);
  200. }
  201. }
  202. } //}}}
  203. //}}}
  204. //{{{ HelpNode class
  205. static class HelpNode
  206. {
  207. String href, title;
  208. //{{{ HelpNode constructor
  209. HelpNode(String href, String title)
  210. {
  211. this.href = href;
  212. this.title = title;
  213. } //}}}
  214. //{{{ toString() method
  215. public String toString()
  216. {
  217. return title;
  218. } //}}}
  219. } //}}}
  220. //{{{ TOCHandler class
  221. class TOCHandler extends HandlerBase
  222. {
  223. String dir;
  224. //{{{ TOCHandler constructor
  225. TOCHandler(DefaultMutableTreeNode root, String dir)
  226. {
  227. nodes = new Stack();
  228. node = root;
  229. this.dir = dir;
  230. } //}}}
  231. //{{{ attribute() method
  232. public void attribute(String aname, String value, boolean isSpecified)
  233. {
  234. if(aname.equals("HREF"))
  235. href = value;
  236. } //}}}
  237. //{{{ charData() method
  238. public void charData(char[] c, int off, int len)
  239. {
  240. if(tag.equals("TITLE"))
  241. {
  242. StringBuffer buf = new StringBuffer();
  243. for(int i = 0; i < len; i++)
  244. {
  245. char ch = c[off + i];
  246. if(ch == ' ' || !Character.isWhitespace(ch))
  247. buf.append(ch);
  248. }
  249. title = buf.toString();
  250. }
  251. } //}}}
  252. //{{{ startElement() method
  253. public void startElement(String name)
  254. {
  255. tag = name;
  256. } //}}}
  257. //{{{ endElement() method
  258. public void endElement(String name)
  259. {
  260. if(name == null)
  261. return;
  262. if(name.equals("TITLE"))
  263. {
  264. DefaultMutableTreeNode newNode = createNode(
  265. dir + href,title);
  266. node.add(newNode);
  267. nodes.push(node);
  268. node = newNode;
  269. }
  270. else if(name.equals("ENTRY"))
  271. node = (DefaultMutableTreeNode)nodes.pop();
  272. } //}}}
  273. //{{{ Private members
  274. private String tag;
  275. private String title;
  276. private String href;
  277. private DefaultMutableTreeNode node;
  278. private Stack nodes;
  279. //}}}
  280. } //}}}
  281. //{{{ TOCTree class
  282. class TOCTree extends JTree
  283. {
  284. //{{{ TOCTree constructor
  285. TOCTree()
  286. {
  287. ToolTipManager.sharedInstance().registerComponent(this);
  288. } //}}}
  289. //{{{ getToolTipText() method
  290. public final String getToolTipText(MouseEvent evt)
  291. {
  292. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  293. if(path != null)
  294. {
  295. Rectangle cellRect = getPathBounds(path);
  296. if(cellRect != null && !cellRectIsVisible(cellRect))
  297. return path.getLastPathComponent().toString();
  298. }
  299. return null;
  300. } //}}}
  301. //{{{ getToolTipLocation() method
  302. /* public final Point getToolTipLocation(MouseEvent evt)
  303. {
  304. TreePath path = getPathForLocation(evt.getX(), evt.getY());
  305. if(path != null)
  306. {
  307. Rectangle cellRect = getPathBounds(path);
  308. if(cellRect != null && !cellRectIsVisible(cellRect))
  309. {
  310. return new Point(cellRect.x + 14, cellRect.y);
  311. }
  312. }
  313. return null;
  314. } */ //}}}
  315. //{{{ processMouseEvent() method
  316. protected void processMouseEvent(MouseEvent evt)
  317. {
  318. //ToolTipManager ttm = ToolTipManager.sharedInstance();
  319. switch(evt.getID())
  320. {
  321. /* case MouseEvent.MOUSE_ENTERED:
  322. toolTipInitialDelay = ttm.getInitialDelay();
  323. toolTipReshowDelay = ttm.getReshowDelay();
  324. ttm.setInitialDelay(200);
  325. ttm.setReshowDelay(0);
  326. super.processMouseEvent(evt);
  327. break;
  328. case MouseEvent.MOUSE_EXITED:
  329. ttm.setInitialDelay(toolTipInitialDelay);
  330. ttm.setReshowDelay(toolTipReshowDelay);
  331. super.processMouseEvent(evt);
  332. break; */
  333. case MouseEvent.MOUSE_CLICKED:
  334. TreePath path = getPathForLocation(evt.getX(),evt.getY());
  335. if(path != null)
  336. {
  337. if(!isPathSelected(path))
  338. setSelectionPath(path);
  339. Object obj = ((DefaultMutableTreeNode)
  340. path.getLastPathComponent())
  341. .getUserObject();
  342. if(!(obj instanceof HelpNode))
  343. {
  344. this.expandPath(path);
  345. return;
  346. }
  347. HelpNode node = (HelpNode)obj;
  348. helpViewer.gotoURL(node.href,true);
  349. }
  350. super.processMouseEvent(evt);
  351. break;
  352. default:
  353. super.processMouseEvent(evt);
  354. break;
  355. }
  356. } //}}}
  357. //{{{ Private members
  358. private int toolTipInitialDelay = -1;
  359. private int toolTipReshowDelay = -1;
  360. //{{{ cellRectIsVisible() method
  361. private boolean cellRectIsVisible(Rectangle cellRect)
  362. {
  363. Rectangle vr = TOCTree.this.getVisibleRect();
  364. return vr.contains(cellRect.x,cellRect.y) &&
  365. vr.contains(cellRect.x + cellRect.width,
  366. cellRect.y + cellRect.height);
  367. } //}}}
  368. //}}}
  369. } //}}}
  370. //{{{ TOCCellRenderer class
  371. class TOCCellRenderer extends DefaultTreeCellRenderer
  372. {
  373. EmptyBorder border = new EmptyBorder(1,0,1,1);
  374. public Component getTreeCellRendererComponent(JTree tree,
  375. Object value, boolean sel, boolean expanded,
  376. boolean leaf, int row, boolean focus)
  377. {
  378. super.getTreeCellRendererComponent(tree,value,sel,
  379. expanded,leaf,row,focus);
  380. setIcon(leaf ? FileCellRenderer.fileIcon
  381. : (expanded ? FileCellRenderer.openDirIcon
  382. : FileCellRenderer.dirIcon));
  383. setBorder(border);
  384. return this;
  385. }
  386. } //}}}
  387. //{{{ PluginCompare class
  388. static class PluginCompare implements Comparator
  389. {
  390. public int compare(Object o1, Object o2)
  391. {
  392. EditPlugin p1 = (EditPlugin)o1;
  393. EditPlugin p2 = (EditPlugin)o2;
  394. return MiscUtilities.compareStrings(
  395. jEdit.getProperty("plugin." + p1.getClassName() + ".name"),
  396. jEdit.getProperty("plugin." + p2.getClassName() + ".name"),
  397. true);
  398. }
  399. } //}}}
  400. }