KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javahelp > JavaHelp


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.javahelp;
21
22 import java.awt.AWTEvent JavaDoc;
23 import java.awt.BorderLayout JavaDoc;
24 import java.awt.Dialog JavaDoc;
25 import java.awt.Dimension JavaDoc;
26 import java.awt.Frame JavaDoc;
27 import java.awt.Point JavaDoc;
28 import java.awt.Rectangle JavaDoc;
29 import java.awt.Toolkit JavaDoc;
30 import java.awt.Window JavaDoc;
31 import java.awt.event.AWTEventListener JavaDoc;
32 import java.awt.event.WindowEvent JavaDoc;
33 import java.lang.ref.Reference JavaDoc;
34 import java.lang.ref.SoftReference JavaDoc;
35 import java.lang.reflect.Method JavaDoc;
36 import java.net.MalformedURLException JavaDoc;
37 import java.net.URL JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Collection JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.Stack JavaDoc;
45 import java.util.logging.Level JavaDoc;
46 import javax.help.HelpSet;
47 import javax.help.HelpSetException;
48 import javax.help.JHelp;
49 import javax.swing.BorderFactory JavaDoc;
50 import javax.swing.BoundedRangeModel JavaDoc;
51 import javax.swing.DefaultBoundedRangeModel JavaDoc;
52 import javax.swing.JComponent JavaDoc;
53 import javax.swing.JDialog JavaDoc;
54 import javax.swing.JFrame JavaDoc;
55 import javax.swing.SwingUtilities JavaDoc;
56 import org.netbeans.api.progress.ProgressHandle;
57 import org.netbeans.api.progress.ProgressHandleFactory;
58 import org.openide.util.HelpCtx;
59 import org.openide.util.NbBundle;
60 import org.openide.util.RequestProcessor;
61 import org.openide.util.Task;
62 import org.openide.util.TaskListener;
63 import org.openide.util.Utilities;
64 import org.openide.windows.WindowManager;
65
66 // [PENDING] should event dispatch thread be used thruout?
67

68 /** Help implementation using the JavaHelp 1.x system.
69 * @author Jesse Glick, Richard Gregor
70 */

71 public final class JavaHelp extends AbstractHelp implements AWTEventListener JavaDoc {
72
73     /** Make a JavaHelp implementation of the Help.Impl interface.
74      *Or, use {@link #getDefaultJavaHelp}.
75      */

76     public JavaHelp() {
77         Installer.log.fine("JavaHelp created");
78         if (!isModalExcludedSupported()) {
79             Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.WINDOW_EVENT_MASK);
80         }
81     }
82     void deactivate() {
83         if (!isModalExcludedSupported()) {
84             Toolkit.getDefaultToolkit().removeAWTEventListener(this);
85         }
86     }
87
88     // [PENDING] hold help sets weakly? softly? try to conserve memory...
89
/** The master help set.
90      */

91     private HelpSet master = null;
92     /** map from help sets to (soft refs to) components showing them */
93     private Map JavaDoc<HelpSet,Reference JavaDoc<JHelp>> availableJHelps = new HashMap JavaDoc<HelpSet,Reference JavaDoc<JHelp>>();
94     /** viewer (may be invisible) showing help normally; null until first used; if invisible, is empty */
95     private JFrame JavaDoc frameViewer = null;
96     /** viewer showing help parented to current modal dialog; initially null */
97     private JDialog JavaDoc dialogViewer = null;
98     /** whether user explicitly closed dialog viewer.
99      * true - frame viewer was initially open, then reparented to dialog viewer,
100      * then user closes main dialog and we ought to reparent to frame viewer
101      * false - frame viewer not initially open anyway, or it was but the user
102      * explicitly closed it as a dialog viewer, we should leave it closed
103      */

104     private boolean reparentToFrameLater = false;
105     /** the modal dialog(s) currently in effect */
106     private Stack JavaDoc<Dialog JavaDoc> currentModalDialogs = new Stack JavaDoc<Dialog JavaDoc>();
107     /** modal dialogs stack has been used successfully */
108     private boolean currentModalDialogsReady = false;
109     /** last-displayed JHelp */
110     private JHelp lastJH = null;
111     
112     /** progress of merging help sets; max is # of sets to merge */
113     private static final BoundedRangeModel JavaDoc mergeModel = new DefaultBoundedRangeModel JavaDoc(0, 0, 0, 0);
114     
115     private ProgressHandle progressHandle = null;
116
117     /** Get the master help set that others will be merged into.
118      * @return the master help set
119      */

120     private synchronized HelpSet getMaster() {
121         if (master == null) {
122             ClassLoader JavaDoc loader = JavaHelp.class.getClassLoader();
123             try {
124                 master = new HelpSet(loader, new URL JavaDoc("nbresloc:/org/netbeans/modules/javahelp/resources/masterHelpSet.xml")); // NOI18N
125
Collection JavaDoc<? extends HelpSet> sets = getHelpSets();
126                 List JavaDoc<HelpSet> toMerge = new ArrayList JavaDoc<HelpSet>(Math.min(1, sets.size()));
127                 for (HelpSet hs: sets) {
128                     if (shouldMerge(hs)) {
129                         toMerge.add(hs);
130                     }
131                 }
132                 mergeModel.setValue(0);
133                 mergeModel.setMaximum(toMerge.size());
134                 for (HelpSet hs: toMerge) {
135                     master.add(hs);
136                     mergeModel.setValue(mergeModel.getValue() + 1);
137                 }
138             } catch (HelpSetException hse) {
139                 Installer.log.log(Level.WARNING, null, hse);
140                 master = new HelpSet();
141             } catch (MalformedURLException JavaDoc mfue) {
142                 mfue.printStackTrace();
143                 throw new IllegalStateException JavaDoc();
144             }
145         }
146         return master;
147     }
148     
149     /** Called when set of helpsets changes.
150      * Here, clear the master helpset, since it may
151      * need to have different contents (or a different
152      * order of contents) when next viewed.
153      */

154     protected void helpSetsChanged() {
155         synchronized (this) {
156             // XXX might be better to incrementally add/remove helpsets?
157
// Unfortunately the JavaHelp API does not provide a way to
158
// insert them except in last position, which prevents smart
159
// navigator ordering.
160
master = null;
161         }
162         mergeModel.setValue(0);
163         mergeModel.setMaximum(0);
164         super.helpSetsChanged();
165     }
166     
167     private Dialog JavaDoc currentModalDialog() {
168         if (currentModalDialogs.empty()) {
169             Window JavaDoc w = HelpAction.WindowActivatedDetector.getCurrentActivatedWindow();
170             if (!currentModalDialogsReady && (w instanceof Dialog JavaDoc) &&
171                     !(w instanceof ProgressDialog) && w != dialogViewer && ((Dialog JavaDoc)w).isModal()) {
172                 // #21286. A modal dialog was opened before JavaHelp was even created.
173
Installer.log.fine("Early-opened modal dialog: " + w.getName() + " [" + ((Dialog JavaDoc)w).getTitle() + "]");
174                 return (Dialog JavaDoc)w;
175             } else {
176                 return null;
177             }
178         } else {
179             return (Dialog JavaDoc)currentModalDialogs.peek();
180         }
181     }
182     
183     private void ensureFrameViewer() {
184         Installer.log.fine("ensureFrameViewer");
185         if (frameViewer == null) {
186             Installer.log.fine("\tcreating new");
187             frameViewer = new JFrame JavaDoc();
188             frameViewer.setIconImage(Utilities.loadImage("org/netbeans/modules/javahelp/resources/help.gif")); // NOI18N
189
frameViewer.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(JavaHelp.class, "ACSD_JavaHelp_viewer"));
190             
191             if (isModalExcludedSupported()) {
192                 setModalExcluded(frameViewer);
193                 frameViewer.getRootPane().putClientProperty("netbeans.helpframe", Boolean.TRUE); // NOI18N
194
}
195         }
196     }
197     private void ensureDialogViewer() {
198         Installer.log.fine("ensureDialogViewer");
199         Dialog JavaDoc parent = currentModalDialog();
200         if (dialogViewer != null && dialogViewer.getOwner() != parent) {
201             Installer.log.fine("\tdisposing old");
202             dialogViewer.setVisible(false);
203             dialogViewer.dispose();
204             dialogViewer = null;
205         }
206         if (dialogViewer == null) {
207             Installer.log.fine("\tcreating new");
208             dialogViewer = new JDialog JavaDoc(parent);
209             dialogViewer.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(JavaHelp.class, "ACSD_JavaHelp_viewer"));
210         }
211     }
212     private void displayHelpInFrame(JHelp jh) {
213         Installer.log.fine("displayHelpInFrame");
214         if (jh == null) jh = lastJH;
215         if (jh == null) throw new IllegalStateException JavaDoc();
216         boolean newFrameViewer = (frameViewer == null);
217         ensureFrameViewer();
218         if (dialogViewer != null) {
219             Installer.log.fine("\tdisposing old dialog");
220             dialogViewer.setVisible(false);
221             dialogViewer.getContentPane().removeAll();
222             dialogViewer.dispose();
223             dialogViewer = null;
224         }
225         if (frameViewer.getContentPane().getComponentCount() > 0 &&
226                 frameViewer.getContentPane().getComponent(0) != jh) {
227             Installer.log.fine("\treplacing content");
228             frameViewer.getContentPane().removeAll();
229         }
230         if (frameViewer.getContentPane().getComponentCount() == 0) {
231             Installer.log.fine("\tadding content");
232             frameViewer.getContentPane().add(jh, BorderLayout.CENTER);
233             frameViewer.setTitle(jh.getModel().getHelpSet().getTitle());
234             frameViewer.pack();
235         }
236         if (newFrameViewer) {
237             // #22445: only do this stuff once when frame is made.
238
// After that we need to remember the size and position.
239
Dimension JavaDoc screenSize = Utilities.getUsableScreenBounds().getSize();
240             Dimension JavaDoc frameSize = frameViewer.getSize();
241             // #11018: have mercy on little screens
242
if (frameSize.width > screenSize.width) {
243                 frameSize.width = screenSize.width;
244                 frameViewer.setSize(frameSize);
245             }
246             if (frameSize.height > screenSize.height) {
247                 frameSize.height = screenSize.height;
248                 frameViewer.setSize(frameSize);
249             }
250             //Put frame to top right
251
frameViewer.setLocation(new Point JavaDoc(screenSize.width - frameViewer.getSize().width, 0));
252         }
253         
254         frameViewer.setState(Frame.NORMAL);
255         if (frameViewer.isVisible()) {
256             frameViewer.repaint();
257             frameViewer.toFront(); // #20048
258
Installer.log.fine("\talready visible, just repainting");
259         } else {
260             frameViewer.setVisible(true);
261         }
262         //#29417: This call of requestFocus causes lost focus when Help window
263
//is reopened => removed.
264
//frameViewer.requestFocus();
265
lastJH = jh;
266     }
267     private void displayHelpInDialog(JHelp jh) {
268         Installer.log.fine("displayHelpInDialog");
269         if (jh == null) jh = lastJH;
270         if (jh == null) throw new IllegalStateException JavaDoc();
271         ensureDialogViewer();
272         Rectangle JavaDoc bounds = null;
273         if (frameViewer != null) {
274             Installer.log.fine("\thiding old frame viewer");
275             if (frameViewer.isVisible()) {
276                 bounds = frameViewer.getBounds();
277                 frameViewer.setVisible(false);
278             }
279             frameViewer.getContentPane().removeAll();
280         }
281         if (dialogViewer.getContentPane().getComponentCount() > 0 &&
282                 dialogViewer.getContentPane().getComponent(0) != jh) {
283             Installer.log.fine("\tchanging content");
284             dialogViewer.getContentPane().removeAll();
285         }
286         if (dialogViewer.getContentPane().getComponentCount() == 0) {
287             Installer.log.fine("\tadding content");
288             dialogViewer.getContentPane().add(jh, BorderLayout.CENTER);
289             dialogViewer.setTitle(jh.getModel().getHelpSet().getTitle());
290             dialogViewer.pack();
291         }
292         if (bounds != null) {
293             Installer.log.fine("\tcopying bounds from frame viewer: " + bounds);
294             dialogViewer.setBounds(bounds);
295         }
296         rearrange(currentModalDialog());
297         if (dialogViewer.isVisible()) {
298             Installer.log.fine("\talready visible, just repainting");
299             dialogViewer.repaint();
300         } else {
301             dialogViewer.setVisible(true);
302         }
303         lastJH = jh;
304     }
305     /*
306     private void closeFrameViewer() {
307         if (frameViewer == null || !frameViewer.isVisible()) throw new IllegalStateException();
308         Installer.log.fine("Closing frame viewer");
309         frameViewer.setVisible(false);
310         frameViewer.getContentPane().removeAll();
311     }
312     private void closeDialogViewer() {
313         if (dialogViewer == null || !dialogViewer.isVisible()) throw new IllegalStateException();
314         Installer.log.fine("Closing dialog viewer");
315         dialogViewer.setVisible(false);
316         dialogViewer.getContentPane().removeAll();
317         dialogViewer.dispose();
318         dialogViewer = null;
319     }
320      */

321     
322     /** Show some help.
323      *This is the basic call which should be used externally
324      *and is the result of {@link TopManager#showHelp}.
325      *Handles null contexts, missing or null help IDs, and null URLs.
326      *If there is any problem, shows the master set
327      *instead, or it may also create a new help window.
328      *Works correctly if invoked while a modal dialog is open--creates a new modal
329      *dialog with the help. Else creates a frame to view the help in.
330      * @param ctx the help context to display
331      * @param showmaster whether to show the master help set or not
332      */

333     public void showHelp(HelpCtx ctx, final boolean showmaster) {
334         final HelpCtx ctx2 = (ctx != null) ? ctx : HelpCtx.DEFAULT_HELP;
335         if (!SwingUtilities.isEventDispatchThread()) {
336             Installer.log.fine("showHelp later...");
337             SwingUtilities.invokeLater(new Runnable JavaDoc() {
338                 public void run() {
339                     showHelp(ctx2, showmaster);
340                 }
341             });
342             return;
343         }
344         Installer.log.fine("showing help: " + ctx2);
345         final HelpSet[] hs_ = new HelpSet[1];
346         Runnable JavaDoc run = new Runnable JavaDoc() {
347             public void run() {
348                 String JavaDoc id = ctx2.getHelpID();
349                 if (showmaster || ctx2.equals(HelpCtx.DEFAULT_HELP) || id == null) {
350                     Installer.log.fine("getting master...");
351                     hs_[0] = getMaster();
352                     Installer.log.fine("getting master...done");
353                 }
354                 if (hs_[0] == null ||
355                         /* #22670: if ID in hidden helpset, use that HS, even if showmaster */
356                         (id != null && !hs_[0].getCombinedMap().isValidID(id, hs_[0]))) {
357                     Installer.log.fine("finding help set for " + id + "...");
358                     hs_[0] = findHelpSetForID(id);
359                     Installer.log.fine("finding help set for " + id + "...done");
360                 }
361             }
362         };
363         if (master == null) {
364             // Computation required. Show the progress dialog and do the computation
365
// in a separate thread. When finished, the progress dialog will hide
366
// itself and control will return to event thread.
367
Installer.log.fine("showing progress dialog...");
368             progressHandle = ProgressHandleFactory.createHandle("");
369             createProgressDialog(run, currentModalDialog()).setVisible(true);
370             progressHandle.finish();
371             Installer.log.fine("dialog done.");
372         } else {
373             // Nothing much to do, run it synchronously in event thread.
374
run.run();
375         }
376         HelpSet hs = hs_[0];
377         if (hs == null) {
378             // Interrupted dialog?
379
return;
380         }
381         JHelp jh = createJHelp(hs);
382         if (jh == null) {
383             return;
384         }
385
386         if (isModalExcludedSupported()) {
387             displayHelpInFrame(jh);
388         } else {
389             if (currentModalDialog() == null) {
390                 Installer.log.fine("showing as non-dialog");
391                 displayHelpInFrame(jh);
392             } else {
393                 Installer.log.fine("showing as dialog");
394                 displayHelpInDialog(jh);
395             }
396         }
397         displayInJHelp(jh, ctx2.getHelpID(), ctx2.getHelp());
398     }
399
400     /** Handle modal dialogs opening and closing. Note reparentToFrameLater state = rTFL.
401      * Cases:
402      * 1. No viewer open. Dialog opened. Push it on stack. rTFL = false.
403      * 2. No viewer open, !rTFL. Top dialog closed. Pop it.
404      * 3. No viewer open, rTFL. Only top dialog closed. Pop it. Create frame viewer.
405      * 4. No viewer open, rTFL. Some top dialog closed. Pop it. Create dialog viewer.
406      * 5. Frame viewer open. Dialog opened. Push it. Close frame viewer. Create dialog viewer. rTFL = true.
407      * 6. Dialog viewer open. Dialog opened. Push it. Reparent dialog viewer.
408      * 7. Dialog viewer open. Viewer closed. rTFL = false.
409      * It cannot happen that the dialog viewer is still open when the top dialog has been
410      * closed, as AWT will automatically close the dialog viewer first. However in this case
411      * it sends only CLOSED for the dialog viewer. If the user closes it, CLOSING is sent at
412      * that time, and CLOSED also later when the main dialog is closed.
413      */

414     public void eventDispatched(AWTEvent JavaDoc awtev) {
415         WindowEvent JavaDoc ev = (WindowEvent JavaDoc)awtev;
416         int type = ev.getID();
417         Window JavaDoc w = ev.getWindow();
418         if (type == WindowEvent.WINDOW_CLOSING && w == dialogViewer) {
419             Installer.log.fine("7. Dialog viewer open. Viewer closed. rTFL = false.");
420             reparentToFrameLater = false;
421         }
422         if (type != WindowEvent.WINDOW_CLOSED && type != WindowEvent.WINDOW_OPENED) {
423             //Installer.log.fine("uninteresting window event: " + ev);
424
return;
425         }
426         if (w instanceof Dialog JavaDoc) {
427             Dialog JavaDoc d = (Dialog JavaDoc)w;
428             String JavaDoc dlgClass = d.getClass().getName();
429             if ((d.isModal() && !(d instanceof ProgressDialog)) || d == dialogViewer) {
430                 //#40950: Print and Page Setup dialogs was not displayed from java help window.
431
if ("sun.awt.windows.WPageDialog".equals(dlgClass) || // NOI18N
432
"sun.awt.windows.WPrintDialog".equals(dlgClass) || // NOI18N
433
"sun.print.ServiceDialog".equals(dlgClass) ||
434                     "apple.awt.CPrinterJobDialog".equals(dlgClass) ||
435                     "apple.awt.CPrinterPageDialog".equals(dlgClass)) { // NOI18N
436
//It is the print or print settings dialog for javahelp, do nothing
437
return;
438                 }
439                 
440                 //#47150: Race condition in toolkit if two dialogs are shown in a row
441
if (d instanceof JDialog JavaDoc) {
442                     if ("true".equals(((JDialog JavaDoc)d).getRootPane().getClientProperty("javahelp.ignore.modality"))) { //NOI18N
443
return;
444                     }
445                 }
446                 
447                 if (Installer.log.isLoggable(Level.FINE)) {
448                     Installer.log.fine("modal (or viewer) dialog event: " + ev + " [" + d.getTitle() + "]");
449                 }
450                 if (type == WindowEvent.WINDOW_CLOSED) {
451                     if (d == dialogViewer) {
452                         // ignore, expected
453
} else if (d == currentModalDialog()) {
454                         if (!currentModalDialogs.isEmpty()) {
455                             currentModalDialogs.pop();
456                             currentModalDialogsReady = true;
457                         } else {
458                             Installer.log.log(Level.WARNING, null, new IllegalStateException JavaDoc("Please see IZ #24993")); // NOI18N
459
}
460                         showDialogStack();
461                         if ((frameViewer == null || !frameViewer.isVisible() ||
462                              /* 14393 */frameViewer.getState() == Frame.ICONIFIED) &&
463                             (dialogViewer == null || !dialogViewer.isVisible())) {
464                             if (!reparentToFrameLater) {
465                                 Installer.log.fine("2. No viewer open, !rTFL. Top dialog closed. Pop it.");
466                             } else if (currentModalDialog() == null) {
467                                 Installer.log.fine("3. No viewer open, rTFL. Only top dialog closed. Pop it. Create frame viewer.");
468                                 //#47150 - reusing the old frame viewer can cause
469
//re-showing the frame viewer to re-show the dialog
470
if (frameViewer != null) {
471                                     frameViewer.dispose();
472                                     frameViewer = null;
473                                 }
474                                 displayHelpInFrame(null);
475                             } else {
476                                 Installer.log.fine("4. No viewer open, rTFL. Some top dialog closed. Pop it. Create dialog viewer.");
477                                 displayHelpInDialog(null);
478                             }
479                         } else if (dialogViewer != null && dialogViewer.isVisible()) {
480                             Installer.log.warning("dialogViewer should not still be open"); // NOI18N
481
} else {
482                             Installer.log.warning("frameViewer visible when a dialog was closing"); // NOI18N
483
}
484                     } else {
485                         Installer.log.fine("some random modal dialog closed: " + d.getName() + " [" + d.getTitle() + "]");
486                     }
487                 } else {
488                     // WINDOW_OPENED
489
if (d != dialogViewer) {
490                         currentModalDialogs.push(d);
491                         showDialogStack();
492                         if ((frameViewer == null || !frameViewer.isVisible() ||
493                              /* 14393 */frameViewer.getState() == Frame.ICONIFIED) &&
494                             (dialogViewer == null || !dialogViewer.isVisible())) {
495                             Installer.log.fine("1. No viewer open. Dialog opened. Push it on stack. rTFL = false.");
496                             reparentToFrameLater = false;
497                         } else if (frameViewer != null && frameViewer.isVisible()) {
498                             Installer.log.fine("5. Frame viewer open. Dialog opened. Push it. Close frame viewer. Create dialog viewer. rTFL = true.");
499                             displayHelpInDialog(null);
500                             reparentToFrameLater = true;
501                         } else if (dialogViewer != null && dialogViewer.isVisible()) {
502                             Installer.log.fine("6. Dialog viewer open. Dialog opened. Push it. Reparent dialog viewer.");
503                             displayHelpInDialog(null);
504                         } else {
505                             Installer.log.warning("logic error"); // NOI18N
506
}
507                     } else {
508                         // dialog viewer opened, fine
509
}
510                 }
511             } else {
512                 //Installer.log.fine("nonmodal dialog event: " + ev);
513
}
514         } else {
515             //Installer.log.fine("frame event: " + ev);
516
}
517     }
518     private void showDialogStack() {
519         if (Installer.log.isLoggable(Level.FINE)) {
520             StringBuffer JavaDoc buf = new StringBuffer JavaDoc("new modal dialog stack: ["); // NOI18N
521
boolean first = true;
522             Iterator JavaDoc it = currentModalDialogs.iterator();
523             while (it.hasNext()) {
524                 if (first) {
525                     first = false;
526                 } else {
527                     buf.append(", "); // NOI18N
528
}
529                 buf.append(((Dialog JavaDoc)it.next()).getTitle());
530             }
531             buf.append("]"); // NOI18N
532
Installer.log.fine(buf.toString());
533         }
534     }
535     
536     /** If needed, visually rearrange dialogViewer and dlg on screen.
537      * If they overlap, try to make them not overlap.
538      * @param dlg the visible modal dialog
539      */

540     private void rearrange(Dialog JavaDoc dlg) {
541         Rectangle JavaDoc r1 = dlg.getBounds();
542         Rectangle JavaDoc r2 = dialogViewer.getBounds();
543         if (r1.intersects(r2)) {
544             Installer.log.fine("modal dialog and dialog viewer overlap");
545             Dimension JavaDoc s = Toolkit.getDefaultToolkit().getScreenSize();
546             int xExtra = s.width - r1.width - r2.width;
547             int yExtra = s.height - r1.height - r2.height;
548             if(xExtra >= yExtra){
549                 //compare y axes of r1 and r2 to know how to relocate them - horizontal relocation
550
int r1Yaxis = r1.x + (r1.width/2);
551                 int r2Yaxis = r2.x + (r2.width/2);
552                 if(r1Yaxis <= r2Yaxis) {
553                     Installer.log.fine(" send help to the right");
554                     if((r1.x + r1.width + r2.width) <= s.width) {
555                         Installer.log.fine("there is enough place fo help");
556                         r2.x = r1.x + r1.width;
557                     } else {
558                         Installer.log.fine("there is not enough place");
559                         if((r1.width + r2.width) < s.width) {
560                             Installer.log.fine("relocate both");
561                             r2.x = s.width - r2.width;
562                             r1.x = r2.x - r1.width;
563                         } else {
564                             Installer.log.fine("relocate both and resize help");
565                             r1.x = 0;
566                             r2.x = r1.width;
567                             r2.width = s.width - r1.width;
568                         }
569                     }
570                 } else {
571                     Installer.log.fine("send help to the left");
572                     if((r1.x - r2.width) > 0) {
573                         Installer.log.fine("there is enough place for help");
574                         r2.x = r1.x - r2.width;
575                     } else {
576                         Installer.log.fine("there is not enough place");
577                         if((r1.width + r2.width) < s.width){
578                             Installer.log.fine("relocate both");
579                             r2.x = 0;
580                             r1.x = r2.width;
581                         } else {
582                             Installer.log.fine("relocate both and resize help");
583                             r1.x = s.width - r1.width;
584                             r2.x = 0;
585                             r2.width = r1.x;
586                         }
587                     }
588                 }
589             } else {
590                 //compare x axes of r1 and r2 to know how to relocate them
591
int r1Xaxis = r1.y + (r1.height/2);
592                 int r2Xaxis = r2.y + (r2.height/2);
593                 if(r1Xaxis <= r2Xaxis) {
594                     Installer.log.fine(" send help to the bottom");
595                     if((r1.y + r1.height + r2.height) <= s.height) {
596                         Installer.log.fine("there is enough place fo help");
597                         r2.y = r1.y + r1.height;
598                     } else {
599                         Installer.log.fine("there is not enough place");
600                         if((r1.height + r2.height) < s.height) {
601                             Installer.log.fine("relocate both");
602                             r2.y = s.height - r2.height;
603                             r1.y = r2.y - r1.height;
604                         } else {
605                             Installer.log.fine("relocate both and resize help");
606                             r1.y = 0;
607                             r2.y = r1.height;
608                             r2.height = s.height - r1.height;
609                         }
610                     }
611                 } else {
612                     Installer.log.fine("send help to the top");
613                     if((r1.y - r2.height) > 0){
614                         Installer.log.fine("there is enough place for help");
615                         r2.y = r1.y - r2.height;
616                     } else {
617                         Installer.log.fine("there is not enough place");
618                         if((r1.height + r2.height) < s.height) {
619                             Installer.log.fine("relocate both");
620                             r2.y = 0;
621                             r1.y = r2.height;
622                         } else {
623                             Installer.log.fine("relocate both and resize help");
624                             r1.y = s.height - r1.height;
625                             r2.y = 0; //or with -1
626
r2.height = r1.y;
627                         }
628                     }
629                 }
630             }
631             dlg.setBounds(r1);
632             dialogViewer.setBounds(r2);
633         }
634     }
635     
636     /** Make a dialog showing progress of parsing & merging help sets.
637      * Show it; when the runnable is done, it will hide itself.
638      * @param run something to do while it is showing
639      * @param parent dialog (may be null)
640      * @return a new progress dialog
641      */

642     private JDialog JavaDoc createProgressDialog(Runnable JavaDoc run, Dialog JavaDoc parent) {
643         return (parent == null) ?
644         new ProgressDialog(run, WindowManager.getDefault().getMainWindow()) :
645             new ProgressDialog(run, parent);
646     }
647     
648     private final class ProgressDialog extends JDialog JavaDoc implements TaskListener, Runnable JavaDoc {
649         private Runnable JavaDoc run;
650         public ProgressDialog(Runnable JavaDoc run, Dialog JavaDoc parent) {
651             super(parent, NbBundle.getMessage(JavaHelp.class, "TITLE_loading_help_sets"), true);
652             init(run);
653         }
654         public ProgressDialog(Runnable JavaDoc run, Frame JavaDoc parent) {
655             super(parent, NbBundle.getMessage(JavaHelp.class, "TITLE_loading_help_sets"), true);
656             init(run);
657         }
658         private void init(Runnable JavaDoc run) {
659             this.run = run;
660             JComponent JavaDoc c = ProgressHandleFactory.createProgressComponent(progressHandle);
661             c.setPreferredSize(new Dimension JavaDoc(3 * c.getPreferredSize().width, 3 * c.getPreferredSize().height));
662             c.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
663             getContentPane().add(c);
664             progressHandle.start();
665             getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(JavaHelp.class, "ACSD_Loading_Dialog")); //NOI18N
666
pack();
667             Dimension JavaDoc screen = Toolkit.getDefaultToolkit().getScreenSize();
668             Dimension JavaDoc me = getSize();
669             setLocation((screen.width - me.width) / 2, (screen.height - me.height) / 2);
670         }
671         public void setVisible(boolean show) {
672             if (show && run != null) {
673                 Installer.log.fine("posting request from progress dialog...");
674                 getHelpLoader().post(run).addTaskListener(this);
675                 run = null;
676             }
677             super.setVisible(show);
678         }
679         public void taskFinished(Task task) {
680             Installer.log.fine("posting request from progress dialog...request finished.");
681             SwingUtilities.invokeLater(this);
682         }
683         public void run() {
684             setVisible(false);
685             dispose();
686         }
687     }
688     
689     private static RequestProcessor helpLoader = null;
690     private static RequestProcessor getHelpLoader() {
691         if (helpLoader == null) {
692             helpLoader = new RequestProcessor("org.netbeans.modules.javahelp.JavaHelp"); // NOI18N
693
}
694         return helpLoader;
695     }
696
697     /** Find the proper help set for an ID.
698     * @param id the ID to look up (may be null)
699     * @return the proper help set (master if not otherwise found)
700     */

701     private HelpSet findHelpSetForID(String JavaDoc id) {
702         if (id != null) {
703             Iterator JavaDoc it = getHelpSets().iterator();
704             while (it.hasNext()) {
705                 HelpSet hs = (HelpSet)it.next();
706                 if (hs.getCombinedMap().isValidID(id, hs))
707                     return hs;
708             }
709             warnBadID(id);
710         }
711         return getMaster();
712     }
713     
714     public Boolean JavaDoc isValidID(String JavaDoc id, boolean force) {
715         if (force || helpSetsReady()) {
716             Iterator JavaDoc it = getHelpSets().iterator();
717             if (MASTER_ID.equals(id)) {
718                 if (it.hasNext()) {
719                     Installer.log.fine("master id, and >=1 help set");
720                     return Boolean.TRUE;
721                 } else {
722                     Installer.log.fine("master id, and 0 help sets");
723                     return Boolean.FALSE;
724                 }
725             } else {
726                 // Regular ID.
727
while (it.hasNext()) {
728                     HelpSet hs = (HelpSet)it.next();
729                     if (hs.getCombinedMap().isValidID(id, hs)) {
730                         Installer.log.fine("found normal valid id " + id + " in " + hs.getTitle());
731                         return Boolean.TRUE;
732                     }
733                 }
734                 Installer.log.fine("did not find id " + id);
735                 return Boolean.FALSE;
736             }
737         } else {
738             Installer.log.fine("not checking " + id + " specifically");
739             return null;
740         }
741     }
742
743     /** Warn that an ID was not found in any help set.
744     * @param id the help ID
745     */

746     private static void warnBadID(String JavaDoc id) {
747         // PLEASE DO NOT COMMENT OUT...localized warning
748
Installer.log.fine(NbBundle.getMessage(JavaHelp.class, "MSG_jh_id_not_found", id));
749     }
750
751     /** Display something in a JHelp.
752      *Handles {@link #MASTER_ID}, as well as help IDs
753      *that were not found in any help set, various exceptions, etc.
754      * @param jh the help component
755      * @param helpID a help ID string to display, may be <CODE>null</CODE>
756      * @param url a URL to display, may be <CODE>null</CODE>; lower priority than the help ID
757      */

758     private synchronized void displayInJHelp(JHelp jh, String JavaDoc helpID, URL JavaDoc url) {
759         if (jh == null) throw new NullPointerException JavaDoc();
760         if (jh.getModel() == null) throw new IllegalArgumentException JavaDoc();
761         Installer.log.fine("displayInJHelp: " + helpID + " " + url);
762         try {
763             if (helpID != null && ! helpID.equals(MASTER_ID)) {
764                 HelpSet hs = jh.getModel().getHelpSet();
765                 if (hs.getCombinedMap().isValidID(helpID, hs)) {
766                     jh.setCurrentID(helpID);
767                 } else {
768                     warnBadID(helpID);
769                 }
770             } else if (url != null) {
771                 jh.setCurrentURL(url);
772             }
773         } catch (RuntimeException JavaDoc e) {
774             Installer.log.log(Level.WARNING, null, e);
775         }
776     }
777
778     /** Create &amp; return a JHelp with the supplied help set.
779      * In the case of the master help, will show the home page for
780      * the distinguished help set if there is exactly one such,
781      * or in the case of exactly one home page, will show that.
782      * Caches the result and the result may be a reused JHelp.
783      * @return the new JHelp
784      * @param hs the help set to show
785      */

786     private JHelp createJHelp(HelpSet hs) {
787         if (hs == null) throw new NullPointerException JavaDoc();
788         JHelp jh;
789         synchronized (availableJHelps) {
790             Reference JavaDoc<JHelp> r = availableJHelps.get(hs);
791             if (r != null) {
792                 jh = r.get();
793                 if (jh != null) {
794                     return jh;
795                 }
796             }
797         }
798         String JavaDoc title = null; // for debugging purposes
799
try {
800             title = hs.getTitle();
801             jh = new JHelp(hs);
802         } catch (RuntimeException JavaDoc e) {
803             Installer.log.log(Level.WARNING, "While trying to display: " + title, e); // NOI18N
804
return null;
805         }
806         synchronized (availableJHelps) {
807             availableJHelps.put(hs, new SoftReference JavaDoc<JHelp>(jh));
808         }
809         try {
810             javax.help.Map.ID home = hs.getHomeID();
811             if (home != null) {
812                 jh.setCurrentID(home);
813             }
814         } catch (Exception JavaDoc e) {
815             Installer.log.log(Level.WARNING, null, e);
816         }
817         return jh;
818     }
819
820     // XXX(ttran) see JDK bug 5092094 for details
821

822     private static int modalExcludedSupported = -1;
823     
824     private static boolean isModalExcludedSupported() {
825         if (modalExcludedSupported == -1) {
826             modalExcludedSupported = 0;
827             
828             try {
829                 Class JavaDoc<?> clazz = Class.forName("sun.awt.SunToolkit"); // NOI18N
830
Method JavaDoc m = clazz.getMethod("isModalExcludedSupported"); // NOI18N
831
Boolean JavaDoc b = (Boolean JavaDoc) m.invoke(null);
832                 modalExcludedSupported = b.booleanValue() ? 1 : 0;
833                 Installer.log.fine("isModalExcludedSupported = " + modalExcludedSupported); // NOI18N
834
} catch (ThreadDeath JavaDoc ex) {
835                 throw ex;
836             } catch (Throwable JavaDoc ex) {
837                 Installer.log.fine("isModalExcludedSupported() failed " + ex); // NOI18N
838
}
839         }
840         
841         return modalExcludedSupported == 1;
842     }
843
844     private static void setModalExcluded(Window JavaDoc window) {
845         if (modalExcludedSupported == 0)
846             return;
847         
848         try {
849             Class JavaDoc<?> clazz = Class.forName("sun.awt.SunToolkit"); // NOI18N
850
Method JavaDoc m = clazz.getMethod("setModalExcluded", Window JavaDoc.class); // NOI18N
851
m.invoke(null, window);
852         } catch (ThreadDeath JavaDoc ex) {
853             throw ex;
854         } catch (Throwable JavaDoc ex) {
855             Installer.log.fine("setModalExcluded(Window) failed " + ex); // NOI18N
856
modalExcludedSupported = 0;
857         }
858     }
859 }
860
Popular Tags