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