1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.xmlhammer.gui.help;
23
24 import java.awt.BorderLayout;
25 import java.awt.Dimension;
26 import java.awt.FlowLayout;
27 import java.awt.Font;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.awt.event.MouseEvent;
31 import java.net.URISyntaxException;
32 import java.net.URL;
33
34 import javax.help.DefaultHelpModel;
35 import javax.help.HelpSet;
36 import javax.help.IndexItem;
37 import javax.help.InvalidHelpSetContextException;
38 import javax.help.JHelpContentViewer;
39 import javax.help.JHelpIndexNavigator;
40 import javax.help.JHelpSearchNavigator;
41 import javax.help.JHelpTOCNavigator;
42 import javax.help.Map;
43 import javax.help.SearchTOCItem;
44 import javax.help.TOCItem;
45 import javax.help.TOCView;
46 import javax.help.Map.ID;
47 import javax.help.event.HelpModelEvent;
48 import javax.help.event.HelpModelListener;
49 import javax.help.plaf.basic.BasicContentViewerUI;
50 import javax.help.plaf.basic.BasicSearchCellRenderer;
51 import javax.help.plaf.basic.BasicTOCCellRenderer;
52 import javax.swing.Box;
53 import javax.swing.DefaultButtonModel;
54 import javax.swing.Icon;
55 import javax.swing.ImageIcon;
56 import javax.swing.JButton;
57 import javax.swing.JComponent;
58 import javax.swing.JLabel;
59 import javax.swing.JPanel;
60 import javax.swing.JToolBar;
61 import javax.swing.JTree;
62 import javax.swing.border.EmptyBorder;
63 import javax.swing.border.EtchedBorder;
64 import javax.swing.event.AncestorEvent;
65 import javax.swing.event.AncestorListener;
66 import javax.swing.tree.DefaultMutableTreeNode;
67 import javax.swing.tree.TreePath;
68
69 import org.apache.log4j.Logger;
70 import org.bounce.CardPanel;
71 import org.bounce.ResizingFlowLayout;
72 import org.bounce.RunnableAction;
73 import org.bounce.event.DoubleClickListener;
74 import org.bounce.image.ImageLoader;
75 import org.xmlhammer.gui.util.ExternalApplicationLauncher;
76 import org.xmlhammer.gui.util.HistoryList;
77
78 public class HelpPanel extends JPanel {
79 private static final long serialVersionUID = -2000362072449326907L;
80
81 private static final ImageIcon CLOSE_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/etool16/close.gif");
82 private static final ImageIcon CLOSE_OVER_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/etool16/close_over.gif");
83
84 private static final ImageIcon TOC_LEAF_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/obj16/searchhit_obj.gif");
85 private static final ImageIcon TOC_TOPIC_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/obj16/container_obj.gif");
86
87 private static final ImageIcon ALL_TOPICS_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/etool16/alltopics_co.gif");
88 private static final ImageIcon SEARCH_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/etool16/helpsearch_co.gif");
89 private static final ImageIcon HELP_VIEW_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/view16/help_view.gif");
90 private static final ImageIcon INDEX_ICON = ImageLoader.get().getImage("/org/xmlhammer/gui/icons/etool16/index_co.gif");
91
92 private HistoryList<HistoryItem> historyList = null;
93
94 private HelpSet helpset = null;
95
96 private JHelpContentViewer contextViewer = null;
97 private JHelpContentViewer basicViewer = null;
98
99 private JHelpSearchNavigator searchNavigator = null;
100 private JHelpTOCNavigator tocNavigator = null;
101 private JHelpIndexNavigator indexNavigator = null;
102
103 private CardPanel<JComponent> cardPanel = null;
104
105 private PreviousAction previousAction = null;
106 private NextAction nextAction = null;
107
108 private JButton closeButton = null;
109
110 public HelpPanel() {
111 super(new BorderLayout());
112
113 setMinimumSize(new Dimension(0, 0));
114 historyList = new HistoryList<HistoryItem>();
115 cardPanel = new CardPanel<JComponent>();
116 JToolBar toolbar = new JToolBar();
117 toolbar.setRollover( true);
118 toolbar.setFloatable( false);
119 JLabel label = new JLabel("Help", HELP_VIEW_ICON, JLabel.HORIZONTAL);
120 label.setFont(label.getFont().deriveFont(Font.PLAIN));
121 toolbar.add(label);
122 toolbar.add(Box.createHorizontalGlue());
123
124 nextAction = new NextAction();
125 previousAction = new PreviousAction();
126 toolbar.add(new HomeAction());
127 toolbar.addSeparator();
128 toolbar.add(previousAction);
129 toolbar.add(nextAction);
130 toolbar.addSeparator();
131 closeButton = toolbar.add(new CloseAction());
132 closeButton.setRolloverIcon(CLOSE_OVER_ICON);
133
134 HelpSet set = getHelpSet();
135
136 if (getHelpSet() != null) {
137 try {
138 contextViewer = new JHelpContentViewer(set);
139 contextViewer.setUI(new ContentViewerUI(contextViewer));
140 contextViewer.getModel().addHelpModelListener(new HelpModelListener() {
141 public void idChanged(HelpModelEvent event) {
142 putHistory(event.getID(), contextViewer);
143 }
144 });
145 cardPanel.add(contextViewer);
146 basicViewer = new JHelpContentViewer(set);
147 basicViewer.setUI(new ContentViewerUI(basicViewer));
148 basicViewer.getModel().addHelpModelListener(new HelpModelListener() {
149 public void idChanged(HelpModelEvent event) {
150 putHistory(event.getID(), basicViewer);
151 }
152 });
153 cardPanel.add(basicViewer);
154
155 searchNavigator = (JHelpSearchNavigator)set.getNavigatorView("Search").createNavigator(new DefaultHelpModel(set));
156 searchNavigator.updateUI();
157 JTree tree = getTree(searchNavigator);
158 tree.setCellRenderer(new BasicSearchCellRenderer(set.getCombinedMap()));
159 tree.updateUI();
160 tree.addMouseListener(new DoubleClickListener() {
161 public void doubleClicked(MouseEvent event) {
162 TreePath path = ((JTree)event.getSource()).getSelectionPath();
163
164 if (path != null) {
165 SearchTOCItem item = (SearchTOCItem)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
166
167 ID id = item.getID();
168
169 if (item.getID() == null && item.getURL() != null) {
170 Map map = getHelpSet().getLocalMap();
171 id = map.getClosestID(item.getURL());
172 }
173
174 if (id != null) {
175 putHistory(id, basicViewer);
176 historyList.setEnabled(false);
177
178 try {
179 basicViewer.setCurrentID(id);
180 cardPanel.show(basicViewer);
181 } catch (InvalidHelpSetContextException e) {
182 Logger.getLogger(getClass()).debug(null, e);
183 } finally {
184 historyList.setEnabled(true);
185 }
186
187 cardPanel.show(basicViewer);
188 }
189 }
190 }
191 });
192 cardPanel.add(searchNavigator);
193
194 indexNavigator = (JHelpIndexNavigator)set.getNavigatorView("Index").createNavigator(new DefaultHelpModel(set));
195 tree = getTree(indexNavigator);
196 tree.addMouseListener(new DoubleClickListener() {
197 public void doubleClicked(MouseEvent event) {
198 TreePath path = ((JTree)event.getSource()).getSelectionPath();
199
200 if (path != null) {
201 IndexItem item = (IndexItem)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
202
203 ID id = item.getID();
204
205 if (item.getID() == null && item.getURL() != null) {
206 Map map = getHelpSet().getLocalMap();
207 id = map.getClosestID(item.getURL());
208 }
209
210 if (id != null) {
211 putHistory(id, basicViewer);
212 historyList.setEnabled(false);
213
214 try {
215 basicViewer.setCurrentID(id);
216 } catch (InvalidHelpSetContextException e) {
217 Logger.getLogger(getClass()).debug(null, e);
218 } finally {
219 historyList.setEnabled(true);
220 }
221
222 cardPanel.show(basicViewer);
223 }
224 }
225 }
226 });
227 cardPanel.add(indexNavigator);
228
229 tocNavigator = (JHelpTOCNavigator)set.getNavigatorView("TOC").createNavigator(new DefaultHelpModel(set));
230 tree = getTree(tocNavigator);
231 tree.setCellRenderer(new TOCCellRenderer(getHelpSet().getCombinedMap()));
232 tree.addMouseListener(new DoubleClickListener() {
233 public void doubleClicked(MouseEvent event) {
234 TreePath path = ((JTree)event.getSource()).getSelectionPath();
235
236 if (path != null) {
237 TOCItem item = (TOCItem)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
238
239 putHistory(item.getID(), basicViewer);
240 historyList.setEnabled(false);
241
242 try {
243 basicViewer.setCurrentID(item.getID());
244 } catch (InvalidHelpSetContextException e) {
245 Logger.getLogger(getClass()).debug(null, e);
246 } finally {
247 historyList.setEnabled(true);
248 }
249
250 cardPanel.show(basicViewer);
251 }
252 }
253 });
254
255 cardPanel.add(tocNavigator);
256
257
258
259
260 JPanel main = new JPanel(new BorderLayout());
261 main.setBorder(new EmptyBorder(2, 5, 0, 5));
262 main.add(cardPanel, BorderLayout.CENTER);
263
264 JPanel panel = new JPanel(new BorderLayout());
265 setBorder(new EtchedBorder());
266
267
268
269
270 panel.add(main, BorderLayout.CENTER);
271
272 JPanel buttonPanel = new JPanel();
273 buttonPanel.setLayout(new ResizingFlowLayout(FlowLayout.LEFT));
274
275 buttonPanel.setBorder(new EmptyBorder(5, 0, 5, 0));
276 JButton tocButton = new JButton("TOC", ALL_TOPICS_ICON);
277 tocButton.addActionListener(new ActionListener() {
278 public void actionPerformed(ActionEvent event) {
279 showTOC();
280 }
281 });
282 tocButton.setFont(tocButton.getFont().deriveFont(Font.PLAIN));
283
284 buttonPanel.add(tocButton);
285 JButton searchButton = new JButton("Search", SEARCH_ICON);
286 searchButton.addActionListener(new ActionListener() {
287 public void actionPerformed(ActionEvent event) {
288 showSearch();
289 }
290 });
291 searchButton.setFont(searchButton.getFont().deriveFont(Font.PLAIN));
292 buttonPanel.add(searchButton);
293
294 JButton indexButton = new JButton("Index", INDEX_ICON);
295 indexButton.addActionListener(new ActionListener() {
296 public void actionPerformed(ActionEvent event) {
297 showIndex();
298 }
299 });
300 indexButton.setFont(indexButton.getFont().deriveFont(Font.PLAIN));
301 buttonPanel.add(indexButton);
302 panel.add(buttonPanel, BorderLayout.SOUTH);
303 main.add(toolbar, BorderLayout.NORTH);
304
305
306
307 add(panel, BorderLayout.CENTER);
308
309 historyList.reset();
310
311
312 putHistory(null, cardPanel.selected());
313 } catch (Exception e) {
314 Logger.getLogger(getClass()).debug(null, e);
315 }
316 }
317
318 this.addAncestorListener(new AncestorListener() {
319 public void ancestorAdded(AncestorEvent event) {}
320
321 public void ancestorMoved(AncestorEvent event) {}
322
323 public void ancestorRemoved(AncestorEvent event) {
324 ((DefaultButtonModel)closeButton.getModel()).setRollover(false);
325 }
326 });
327 }
328
329 public void showID(String id) {
330 showID(id, false);
331 }
332
333 public void addCloseActionListener(ActionListener listener) {
334 closeButton.addActionListener(listener);
335 }
336
337 public void removeCloseActionListener(ActionListener listener) {
338 closeButton.removeActionListener(listener);
339 }
340
341 public void showContext() {
342 if (!contextViewer.isVisible()) {
343 putHistory(contextViewer.getModel().getCurrentID(), contextViewer);
344 cardPanel.show(contextViewer);
345 }
346 }
347
348 public void showContents() {
349 Map.ID id = getHelpSet().getHomeID();
350
351 if (basicViewer.getModel().getCurrentID() == null || !basicViewer.getModel().getCurrentID().equals(id)) {
352 putHistory(id, basicViewer);
353 historyList.setEnabled(false);
354
355 try {
356 basicViewer.setCurrentID(id);
357 } catch (InvalidHelpSetContextException e) {
358 Logger.getLogger(getClass()).debug(null, e);
359 } finally {
360 historyList.setEnabled(true);
361 }
362 }
363
364 cardPanel.show(basicViewer);
365 }
366
367 public void showQuickStart() {
368 Map.ID id = Map.ID.create("quick-start", getHelpSet());
369
370 if (basicViewer.getModel().getCurrentID() == null || !basicViewer.getModel().getCurrentID().equals(id)) {
371 putHistory(id, basicViewer);
372 historyList.setEnabled(false);
373
374 try {
375 basicViewer.setCurrentID(id);
376 } catch (InvalidHelpSetContextException e) {
377 Logger.getLogger(getClass()).debug(null, e);
378 } finally {
379 historyList.setEnabled(true);
380 }
381 }
382
383 cardPanel.show(basicViewer);
384 }
385
386 public void showSearch() {
387 if (cardPanel.selected() != searchNavigator) {
388 putHistory(null, searchNavigator);
389 cardPanel.show(searchNavigator);
390 }
391 }
392
393 public void showIndex() {
394 if (cardPanel.selected() != indexNavigator) {
395 putHistory(null, indexNavigator);
396 cardPanel.show(indexNavigator);
397 }
398 }
399
400 public void showTOC() {
401 if (cardPanel.selected() != tocNavigator) {
402 putHistory(null, tocNavigator);
403 cardPanel.show(tocNavigator);
404 }
405 }
406
407 public void show(HistoryItem item) {
408 cardPanel.show(item.getCard());
409 historyList.setEnabled(false);
410
411 try {
412 if (item.getCard() == contextViewer) {
413 contextViewer.setCurrentID(item.getID());
414 } else if (item.getCard() == basicViewer) {
415 basicViewer.setCurrentID(item.getID());
416 }
417 } catch (InvalidHelpSetContextException e) {
418 Logger.getLogger(getClass()).debug(null, e);
419 } finally {
420 historyList.setEnabled(true);
421 }
422 }
423
424 private void updateActions() {
425 previousAction.setEnabled(historyList.hasPrevious());
426 nextAction.setEnabled(historyList.hasNext());
427 }
428
429 /***
430 * @param id the id for the
431 * @param showViewer
432 */
433 public void showID(String idString, boolean showViewer) {
434 ID id = Map.ID.create(idString, getHelpSet());
435
436 if (contextViewer != null) {
437 try {
438 historyList.setEnabled(false);
439 contextViewer.setCurrentID(id);
440
441 if (contextViewer.isVisible() && contextViewer.getModel().getCurrentID().equals(id)) {
442 putHistory(id, contextViewer);
443 }
444
445 if (showViewer) {
446 showContext();
447 }
448 } catch (InvalidHelpSetContextException e) {
449 Logger.getLogger(getClass()).debug("Cannot set ID", e);
450 } finally {
451 historyList.setEnabled(true);
452 }
453 }
454 }
455
456 private HelpSet getHelpSet() {
457 if (helpset == null) {
458 try {
459 URL url = getClass().getResource("/help/jhelpset.hs");
460
461 Logger.getLogger(getClass()).debug("HelpSet URL: " + url);
462
463 if (url != null) {
464 helpset = new HelpSet(getClass().getClassLoader(), url);
465 }
466 } catch (Exception e) {
467 Logger.getLogger(getClass()).debug(null, e);
468 }
469 }
470
471 return helpset;
472 }
473
474 private JTree getTree(JComponent comp) {
475 JTree tree = null;
476
477 if (comp instanceof JTree) {
478 tree = (JTree)comp;
479 }
480
481 for (int i = 0; i < comp.getComponentCount() && tree == null; i++) {
482 if (comp.getComponent(i) instanceof JComponent) {
483 tree = getTree((JComponent)comp.getComponent(i));
484 }
485 }
486
487 return tree;
488 }
489
490 private void putHistory(ID id, JComponent card) {
491 if (card != null && id != null) {
492 historyList.put(new HistoryItem(id, card));
493 updateActions();
494 }
495 }
496
497 private class HistoryItem {
498 private ID id = null;
499 private JComponent card = null;
500
501 public HistoryItem(ID id, JComponent card) {
502 this.id = id;
503 this.card = card;
504 }
505
506 public ID getID() {
507 return id;
508 }
509
510 public JComponent getCard() {
511 return card;
512 }
513
514 public String toString() {
515 return "["+card.getClass().getName()+"] "+id;
516 }
517 }
518
519 private class NextAction extends RunnableAction {
520 private static final long serialVersionUID = 3258134648029526321L;
521
522 public NextAction() {
523 super("Next");
524
525 putValue(SHORT_DESCRIPTION, "Next Help Item");
526 putValue(SMALL_ICON, new ImageIcon( getClass().getResource( "/org/xmlhammer/gui/icons/elcl16/forward_nav.gif")));
527 }
528
529 public void run() {
530 show(historyList.next());
531 updateActions();
532 }
533 }
534
535 private class PreviousAction extends RunnableAction {
536 private static final long serialVersionUID = 3258134648029526321L;
537
538 public PreviousAction() {
539 super("Previous");
540
541 putValue(SHORT_DESCRIPTION, "Next Help Item");
542 putValue(SMALL_ICON, new ImageIcon( getClass().getResource( "/org/xmlhammer/gui/icons/elcl16/backward_nav.gif")));
543 }
544
545 public void run() {
546 show(historyList.previous());
547 updateActions();
548 }
549 }
550
551 private class HomeAction extends RunnableAction {
552 private static final long serialVersionUID = 3258134648029526321L;
553
554 public HomeAction() {
555 super("Home");
556
557 putValue(SHORT_DESCRIPTION, "Index Page");
558 putValue(SMALL_ICON, new ImageIcon( getClass().getResource( "/org/xmlhammer/gui/icons/elcl16/home_nav.gif")));
559 }
560
561 public void run() {
562 showContents();
563 }
564 }
565
566 private class CloseAction extends RunnableAction {
567 private static final long serialVersionUID = 3258134648029526321L;
568
569 public CloseAction() {
570 super("Close");
571
572 putValue(SHORT_DESCRIPTION, "Close Help View");
573 putValue(SMALL_ICON, CLOSE_ICON);
574 }
575
576 public void run() {
577
578 }
579 }
580
581 private class TOCCellRenderer extends BasicTOCCellRenderer {
582 private static final long serialVersionUID = 6850877407883209757L;
583
584 public TOCCellRenderer(Map map1, TOCView tocview) {
585 super(map1, tocview);
586 }
587
588 public TOCCellRenderer(Map map1) {
589 super(map1);
590 }
591
592 public Icon getLeafIcon() {
593 return TOC_LEAF_ICON;
594 }
595
596 public Icon getOpenIcon() {
597 return TOC_TOPIC_ICON;
598 }
599
600 public Icon getClosedIcon() {
601 return TOC_TOPIC_ICON;
602 }
603 }
604
605 private class ContentViewerUI extends BasicContentViewerUI {
606 private static final long serialVersionUID = 535503569665566378L;
607
608 public ContentViewerUI(JHelpContentViewer jhelpcontentviewer) {
609 super(jhelpcontentviewer);
610 }
611
612 protected void linkActivated(URL url) {
613 Logger.getLogger(getClass()).debug("linkActivated("+url+")");
614 if (url.getProtocol().equals("http")) {
615 try {
616 ExternalApplicationLauncher.getInstance().browse(url.toURI());
617 } catch (URISyntaxException e) {
618 e.printStackTrace();
619 }
620 } else {
621 super.linkActivated(url);
622 }
623 }
624 }
625 }