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