PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/help/HelpViewer.java

#
Java | 412 lines | 291 code | 46 blank | 75 comment | 40 complexity | 3aeb5733af8b1e41b8d28d8d815fd5af 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. * HelpViewer.java - HTML Help viewer
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 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 javax.swing.*;
  25. import javax.swing.border.*;
  26. import javax.swing.event.*;
  27. import javax.swing.text.html.*;
  28. import java.awt.*;
  29. import java.awt.event.*;
  30. import java.beans.*;
  31. import java.io.*;
  32. import java.net.*;
  33. import org.gjt.sp.jedit.gui.RolloverButton;
  34. import org.gjt.sp.jedit.msg.PluginUpdate;
  35. import org.gjt.sp.jedit.*;
  36. import org.gjt.sp.util.Log;
  37. //}}}
  38. /**
  39. * jEdit's searchable help viewer. It uses a Swing JEditorPane to display the HTML,
  40. * and implements a URL history.
  41. * @author Slava Pestov
  42. * @version $Id: HelpViewer.java 5053 2004-05-29 01:55:26Z spestov $
  43. */
  44. public class HelpViewer extends JFrame implements EBComponent
  45. {
  46. //{{{ HelpViewer constructor
  47. /**
  48. * Creates a new help viewer with the default help page.
  49. * @since jEdit 4.0pre4
  50. */
  51. public HelpViewer()
  52. {
  53. this("welcome.html");
  54. } //}}}
  55. //{{{ HelpViewer constructor
  56. /**
  57. * Creates a new help viewer for the specified URL.
  58. * @param url The URL
  59. */
  60. public HelpViewer(URL url)
  61. {
  62. this(url.toString());
  63. } //}}}
  64. //{{{ HelpViewer constructor
  65. /**
  66. * Creates a new help viewer for the specified URL.
  67. * @param url The URL
  68. */
  69. public HelpViewer(String url)
  70. {
  71. super(jEdit.getProperty("helpviewer.title"));
  72. setIconImage(GUIUtilities.getEditorIcon());
  73. try
  74. {
  75. baseURL = new File(MiscUtilities.constructPath(
  76. jEdit.getJEditHome(),"doc")).toURL().toString();
  77. }
  78. catch(MalformedURLException mu)
  79. {
  80. Log.log(Log.ERROR,this,mu);
  81. // what to do?
  82. }
  83. history = new String[25];
  84. ActionHandler actionListener = new ActionHandler();
  85. JTabbedPane tabs = new JTabbedPane();
  86. tabs.addTab(jEdit.getProperty("helpviewer.toc.label"),
  87. toc = new HelpTOCPanel(this));
  88. tabs.addTab(jEdit.getProperty("helpviewer.search.label"),
  89. new HelpSearchPanel(this));
  90. tabs.setMinimumSize(new Dimension(0,0));
  91. JPanel rightPanel = new JPanel(new BorderLayout());
  92. JToolBar toolBar = new JToolBar();
  93. toolBar.setFloatable(false);
  94. toolBar.add(title = new JLabel());
  95. toolBar.add(Box.createGlue());
  96. JPanel buttons = new JPanel();
  97. buttons.setLayout(new BoxLayout(buttons,BoxLayout.X_AXIS));
  98. buttons.setBorder(new EmptyBorder(0,12,0,0));
  99. back = new RolloverButton(GUIUtilities.loadIcon(
  100. jEdit.getProperty("helpviewer.back.icon")));
  101. back.setToolTipText(jEdit.getProperty("helpviewer.back.label"));
  102. back.addActionListener(actionListener);
  103. toolBar.add(back);
  104. forward = new RolloverButton(GUIUtilities.loadIcon(
  105. jEdit.getProperty("helpviewer.forward.icon")));
  106. forward.addActionListener(actionListener);
  107. forward.setToolTipText(jEdit.getProperty("helpviewer.forward.label"));
  108. toolBar.add(forward);
  109. back.setPreferredSize(forward.getPreferredSize());
  110. rightPanel.add(BorderLayout.NORTH,toolBar);
  111. viewer = new JEditorPane();
  112. viewer.setEditable(false);
  113. viewer.addHyperlinkListener(new LinkHandler());
  114. viewer.setFont(new Font("Monospaced",Font.PLAIN,12));
  115. viewer.addPropertyChangeListener(new PropertyChangeHandler());
  116. rightPanel.add(BorderLayout.CENTER,new JScrollPane(viewer));
  117. splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
  118. tabs,rightPanel);
  119. splitter.setBorder(null);
  120. getContentPane().add(BorderLayout.CENTER,splitter);
  121. gotoURL(url,true);
  122. setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  123. getRootPane().setPreferredSize(new Dimension(750,500));
  124. pack();
  125. GUIUtilities.loadGeometry(this,"helpviewer");
  126. EditBus.addToBus(this);
  127. show();
  128. SwingUtilities.invokeLater(new Runnable()
  129. {
  130. public void run()
  131. {
  132. splitter.setDividerLocation(jEdit.getIntegerProperty(
  133. "helpviewer.splitter",250));
  134. viewer.requestFocus();
  135. }
  136. });
  137. } //}}}
  138. //{{{ gotoURL() method
  139. /**
  140. * Displays the specified URL in the HTML component.
  141. * @param url The URL
  142. * @param addToHistory Should the URL be added to the back/forward
  143. * history?
  144. */
  145. public void gotoURL(String url, boolean addToHistory)
  146. {
  147. // the TOC pane looks up user's guide URLs relative to the
  148. // doc directory...
  149. String shortURL;
  150. if(MiscUtilities.isURL(url))
  151. {
  152. if(url.startsWith(baseURL))
  153. {
  154. shortURL = url.substring(baseURL.length());
  155. if(shortURL.startsWith("/"))
  156. shortURL = shortURL.substring(1);
  157. }
  158. else
  159. {
  160. shortURL = url;
  161. }
  162. }
  163. else
  164. {
  165. shortURL = url;
  166. if(baseURL.endsWith("/"))
  167. url = baseURL + url;
  168. else
  169. url = baseURL + '/' + url;
  170. }
  171. // reset default cursor so that the hand cursor doesn't
  172. // stick around
  173. viewer.setCursor(Cursor.getDefaultCursor());
  174. URL _url = null;
  175. try
  176. {
  177. _url = new URL(url);
  178. if(!_url.equals(viewer.getPage()))
  179. title.setText(jEdit.getProperty("helpviewer.loading"));
  180. else
  181. {
  182. /* don't show loading msg because we won't
  183. receive a propertyChanged */
  184. }
  185. viewer.setPage(_url);
  186. if(addToHistory)
  187. {
  188. history[historyPos] = url;
  189. if(historyPos + 1 == history.length)
  190. {
  191. System.arraycopy(history,1,history,
  192. 0,history.length - 1);
  193. history[historyPos] = null;
  194. }
  195. else
  196. historyPos++;
  197. }
  198. }
  199. catch(MalformedURLException mf)
  200. {
  201. Log.log(Log.ERROR,this,mf);
  202. String[] args = { url, mf.getMessage() };
  203. GUIUtilities.error(this,"badurl",args);
  204. return;
  205. }
  206. catch(IOException io)
  207. {
  208. Log.log(Log.ERROR,this,io);
  209. String[] args = { url, io.toString() };
  210. GUIUtilities.error(this,"read-error",args);
  211. return;
  212. }
  213. this.shortURL = shortURL;
  214. // select the appropriate tree node.
  215. if(shortURL != null)
  216. toc.selectNode(shortURL);
  217. } //}}}
  218. //{{{ dispose() method
  219. public void dispose()
  220. {
  221. EditBus.removeFromBus(this);
  222. jEdit.setIntegerProperty("helpviewer.splitter",
  223. splitter.getDividerLocation());
  224. GUIUtilities.saveGeometry(this,"helpviewer");
  225. super.dispose();
  226. } //}}}
  227. //{{{ handleMessage() method
  228. public void handleMessage(EBMessage msg)
  229. {
  230. if(msg instanceof PluginUpdate)
  231. {
  232. PluginUpdate pmsg = (PluginUpdate)msg;
  233. if(pmsg.getWhat() == PluginUpdate.LOADED
  234. || pmsg.getWhat() == PluginUpdate.UNLOADED)
  235. {
  236. if(!pmsg.isExiting())
  237. {
  238. if(!queuedTOCReload)
  239. queueTOCReload();
  240. queuedTOCReload = true;
  241. }
  242. }
  243. }
  244. } //}}}
  245. //{{{ getBaseURL() method
  246. public String getBaseURL()
  247. {
  248. return baseURL;
  249. } //}}}
  250. //{{{ getShortURL() method
  251. String getShortURL()
  252. {
  253. return shortURL;
  254. } //}}}
  255. //{{{ Private members
  256. //{{{ Instance members
  257. private String baseURL;
  258. private String shortURL;
  259. private JButton back;
  260. private JButton forward;
  261. private JEditorPane viewer;
  262. private JLabel title;
  263. private JSplitPane splitter;
  264. private String[] history;
  265. private int historyPos;
  266. private HelpTOCPanel toc;
  267. private boolean queuedTOCReload;
  268. //}}}
  269. //{{{ queueTOCReload() method
  270. public void queueTOCReload()
  271. {
  272. SwingUtilities.invokeLater(new Runnable()
  273. {
  274. public void run()
  275. {
  276. queuedTOCReload = false;
  277. toc.load();
  278. }
  279. });
  280. } //}}}
  281. //}}}
  282. //{{{ Inner classes
  283. //{{{ ActionHandler class
  284. class ActionHandler implements ActionListener
  285. {
  286. //{{{ actionPerformed() class
  287. public void actionPerformed(ActionEvent evt)
  288. {
  289. Object source = evt.getSource();
  290. if(source == back)
  291. {
  292. if(historyPos <= 1)
  293. getToolkit().beep();
  294. else
  295. {
  296. String url = history[--historyPos - 1];
  297. gotoURL(url,false);
  298. }
  299. }
  300. else if(source == forward)
  301. {
  302. if(history.length - historyPos <= 1)
  303. getToolkit().beep();
  304. else
  305. {
  306. String url = history[historyPos];
  307. if(url == null)
  308. getToolkit().beep();
  309. else
  310. {
  311. historyPos++;
  312. gotoURL(url,false);
  313. }
  314. }
  315. }
  316. } //}}}
  317. } //}}}
  318. //{{{ LinkHandler class
  319. class LinkHandler implements HyperlinkListener
  320. {
  321. //{{{ hyperlinkUpdate() method
  322. public void hyperlinkUpdate(HyperlinkEvent evt)
  323. {
  324. if(evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
  325. {
  326. if(evt instanceof HTMLFrameHyperlinkEvent)
  327. {
  328. ((HTMLDocument)viewer.getDocument())
  329. .processHTMLFrameHyperlinkEvent(
  330. (HTMLFrameHyperlinkEvent)evt);
  331. }
  332. else
  333. {
  334. URL url = evt.getURL();
  335. if(url != null)
  336. gotoURL(url.toString(),true);
  337. }
  338. }
  339. else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
  340. viewer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
  341. }
  342. else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
  343. viewer.setCursor(Cursor.getDefaultCursor());
  344. }
  345. } //}}}
  346. } //}}}
  347. //{{{ PropertyChangeHandler class
  348. class PropertyChangeHandler implements PropertyChangeListener
  349. {
  350. public void propertyChange(PropertyChangeEvent evt)
  351. {
  352. if("page".equals(evt.getPropertyName()))
  353. {
  354. String titleStr = (String)viewer.getDocument()
  355. .getProperty("title");
  356. if(titleStr == null)
  357. {
  358. titleStr = MiscUtilities.getFileName(
  359. viewer.getPage().toString());
  360. }
  361. title.setText(titleStr);
  362. }
  363. }
  364. } //}}}
  365. //}}}
  366. }