KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > view > ui > MainWindow


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.core.windows.view.ui;
21
22
23 import java.awt.AWTEvent JavaDoc;
24 import java.awt.BorderLayout JavaDoc;
25 import java.awt.Component JavaDoc;
26 import java.awt.Dimension JavaDoc;
27 import java.awt.EventQueue JavaDoc;
28 import java.awt.FlowLayout JavaDoc;
29 import java.awt.Graphics JavaDoc;
30 import java.awt.Image JavaDoc;
31 import java.awt.Rectangle JavaDoc;
32 import java.awt.event.*;
33 import java.awt.image.BufferedImage JavaDoc;
34 import java.text.*;
35 import java.util.*;
36 import javax.swing.*;
37 import javax.swing.border.*;
38 import javax.swing.event.*;
39 import org.netbeans.core.windows.*;
40 import org.openide.LifecycleManager;
41 import org.openide.awt.*;
42 import org.openide.cookies.InstanceCookie;
43 import org.openide.filesystems.*;
44 import org.openide.loaders.DataObject;
45 import org.openide.util.*;
46 import org.openide.windows.TopComponent;
47 import org.openide.windows.WindowManager;
48
49 /** The MainWindow of IDE. Holds toolbars, main menu and also entire desktop
50  * if in MDI user interface. Singleton.
51  * This class is final only for performance reasons, can be unfinaled
52  * if desired.
53  *
54  * @author Ian Formanek, Petr Hamernik
55  */

56 public final class MainWindow extends JFrame {
57     /** generated Serialized Version UID */
58     static final long serialVersionUID = -1160791973145645501L;
59
60     /** Desktop. */
61     private Component JavaDoc desktop;
62     
63     /** Inner panel which contains desktop component */
64     private JPanel desktopPanel;
65     
66     private static JPanel innerIconsPanel;
67     
68     /** Flag indicating main window is initialized. */
69     private boolean inited;
70     
71
72     /** Constructs main window. */
73     public MainWindow() {
74     }
75     
76     /** Overrides superclass method, adds help context to the new root pane. */
77     protected void setRootPane(JRootPane root) {
78         super.setRootPane(root);
79         if(root != null) {
80             HelpCtx.setHelpIDString(
81                     root, new HelpCtx(MainWindow.class).getHelpID());
82         }
83         //Optimization related to jdk bug 4939857 - on pre 1.5 jdk's an
84
//extra repaint is caused by the search for an opaque component up
85
//to the component root. Post 1.5, root pane will automatically be
86
//opaque.
87
root.setOpaque(true);
88         if (Utilities.isWindows()) {
89             // use glass pane that will not cause repaint/revalidate of parent when set visible
90
// is called (when setting wait cursor in ModuleActions) #40689
91
JComponent c = new JPanel() {
92                 public void setVisible(boolean flag) {
93                     if (flag != isVisible ()) {
94                         super.setVisible(flag);
95                     }
96                 }
97             };
98             c.setName(root.getName()+".nbGlassPane"); // NOI18N
99
c.setVisible(false);
100             ((JPanel)c).setOpaque(false);
101             root.setGlassPane(c);
102         }
103     }
104     
105     /** Initializes main window. */
106     public void initializeComponents() {
107         if(inited) {
108             return;
109         }
110         inited = true;
111         
112         // initialize frame
113
setIconImage(createIDEImage());
114         
115         initListeners();
116
117         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
118
119         getAccessibleContext().setAccessibleDescription(
120                 NbBundle.getBundle(MainWindow.class).getString("ACSD_MainWindow"));
121
122         setJMenuBar(createMenuBar());
123     
124         if (!Constants.NO_TOOLBARS) {
125             JComponent tb = getToolbarComponent();
126             getContentPane().add(tb, BorderLayout.NORTH);
127         }
128         
129         if(!Constants.SWITCH_STATUSLINE_IN_MENUBAR) {
130             if (Constants.CUSTOM_STATUS_LINE_PATH == null) {
131                 JLabel status = new StatusLine();
132                 // XXX #19910 Not to squeeze status line.
133
status.setText(" "); // NOI18N
134
status.setPreferredSize(new Dimension JavaDoc(0, status.getPreferredSize().height));
135                 // text in line should be shifted for 4pix.
136
status.setBorder (BorderFactory.createEmptyBorder (0, 4, 0, 0));
137
138                 JPanel statusLinePanel = new JPanel(new BorderLayout JavaDoc());
139                 int magicConstant = 0;
140                 if (Utilities.isMac()) {
141                     // on mac there is window resize component in the right most bottom area.
142
// it paints over our icons..
143
magicConstant = 12;
144                 }
145                 
146                 // status line should add some pixels on the left side
147
statusLinePanel.setBorder(BorderFactory.createCompoundBorder(
148                         BorderFactory.createEmptyBorder (0, 0, 0, magicConstant),
149                         statusLinePanel.getBorder ()));
150                 
151                 statusLinePanel.add(new JSeparator(), BorderLayout.NORTH);
152                 statusLinePanel.add(status, BorderLayout.CENTER);
153                 
154                 decoratePanel (statusLinePanel);
155                 statusLinePanel.setName("statusLine"); //NOI18N
156
getContentPane().add (statusLinePanel, BorderLayout.SOUTH);
157             } else { // custom status line provided
158
JComponent status = getCustomStatusLine();
159                 if (status != null) {
160                     getContentPane().add(status, BorderLayout.SOUTH);
161                 }
162             }
163         }
164         
165         // initialize desktop panel
166
desktopPanel = new JPanel();
167     
168         desktopPanel.setBorder(getDesktopBorder());
169         desktopPanel.setLayout(new BorderLayout JavaDoc());
170         
171 // Color fillC = (Color)UIManager.get("nb_workplace_fill"); //NOI18N
172
// if (fillC != null) {
173
// desktopPanel.setBackground(fillC);
174
// }
175

176         getContentPane().add(desktopPanel, BorderLayout.CENTER);
177         //#38810 start - focusing the main window in case it's not active and the menu is
178
// selected..
179
MenuSelectionManager.defaultManager().addChangeListener(new ChangeListener(){
180             public void stateChanged(ChangeEvent e) {
181                 MenuElement[] elems = MenuSelectionManager.defaultManager().getSelectedPath();
182                 if (elems != null && elems.length > 0) {
183                     if (elems[0] == getJMenuBar()) {
184                         if (!isActive()) {
185                             toFront();
186                         }
187                     }
188                 }
189             }
190         });
191         //#38810 end
192
setTitle(NbBundle.getMessage(MainWindow.class, "CTL_MainWindow_Title_No_Project", System.getProperty("netbeans.buildnumber")));
193     }
194     
195     private static void decoratePanel (JPanel panel) {
196         assert SwingUtilities.isEventDispatchThread () : "Must run in AWT queue.";
197         if (innerIconsPanel != null) {
198             panel.remove (innerIconsPanel);
199         }
200         innerIconsPanel = getStatusLineElements (panel);
201         if (innerIconsPanel != null) {
202             panel.add (innerIconsPanel, BorderLayout.EAST);
203         }
204     }
205     
206     private static Lookup.Result<StatusLineElementProvider> result;
207     
208     // package-private because StatusLineElementProviderTest
209
static JPanel getStatusLineElements (JPanel panel) {
210         // bugfix #56375, don't duplicate the listeners
211
if (result == null) {
212             result = Lookup.getDefault ().lookup (
213                     new Lookup.Template<StatusLineElementProvider> (StatusLineElementProvider.class));
214             result.addLookupListener (new StatusLineElementsListener (panel));
215         }
216         Collection<? extends StatusLineElementProvider> c = result.allInstances ();
217         if (c == null || c.isEmpty ()) {
218             return null;
219         }
220         Iterator<? extends StatusLineElementProvider> it = c.iterator ();
221         JPanel icons = new JPanel (new FlowLayout JavaDoc (FlowLayout.RIGHT, 0, 0));
222         icons.setBorder (BorderFactory.createEmptyBorder (1, 0, 0, 2));
223         boolean some = false;
224         while (it.hasNext ()) {
225             StatusLineElementProvider o = it.next ();
226             Component JavaDoc comp = o.getStatusLineElement ();
227             if (comp != null) {
228                 some = true;
229                 icons.add (comp);
230             }
231         }
232         return some ? icons : null;
233     }
234     
235     static private class StatusLineElementsListener implements LookupListener {
236         private JPanel decoratingPanel;
237         StatusLineElementsListener (JPanel decoratingPanel) {
238             this.decoratingPanel = decoratingPanel;
239         }
240         public void resultChanged (LookupEvent ev) {
241             SwingUtilities.invokeLater (new Runnable JavaDoc () {
242                 public void run () {
243                     decoratePanel (decoratingPanel);
244                 }
245             });
246         }
247     }
248     
249     /** Creates and returns border for desktop which is visually aligned
250      * with currently active LF */

251     private static Border getDesktopBorder () {
252         Border b = (Border) UIManager.get ("nb.desktop.splitpane.border");
253         if (b != null) {
254             return b;
255         } else {
256             return new EmptyBorder(1, 1, 1, 1);
257         }
258     }
259     
260     private static final String JavaDoc ICON_SMALL = "org/netbeans/core/startup/frame.gif"; // NOI18N
261
private static final String JavaDoc ICON_BIG = "org/netbeans/core/startup/frame32.gif"; // NOI18N
262
static Image JavaDoc createIDEImage() {
263         return Utilities.loadImage(Utilities.isLargeFrameIcons() ? ICON_BIG : ICON_SMALL, true);
264     }
265     
266     private void initListeners() {
267         addWindowListener (new WindowAdapter() {
268                 public void windowClosing(WindowEvent evt) {
269                     LifecycleManager.getDefault().exit();
270                 }
271
272                 public void windowActivated (WindowEvent evt) {
273                    // #19685. Cancel foreigner popup when
274
// activated main window.
275
org.netbeans.core.windows.RegistryImpl.cancelMenu(MainWindow.this);
276                 }
277             }
278         );
279     }
280
281     /** Creates menu bar. */
282     private static JMenuBar createMenuBar() {
283         JMenuBar menu = getCustomMenuBar();
284         if (menu == null) {
285              menu = new MenuBar (null);
286         }
287         menu.setBorderPainted(false);
288         if (menu instanceof MenuBar) {
289             ((MenuBar)menu).waitFinished();
290         }
291         
292         if(Constants.SWITCH_STATUSLINE_IN_MENUBAR) {
293             if (Constants.CUSTOM_STATUS_LINE_PATH == null) {
294                 JLabel status = new StatusLine();
295                 JSeparator sep = new JSeparator(JSeparator.VERTICAL);
296                 Dimension JavaDoc d = sep.getPreferredSize();
297                 d.width += 6; // need a bit more padding...
298
sep.setPreferredSize(d);
299                 JPanel statusLinePanel = new JPanel(new BorderLayout JavaDoc());
300                 statusLinePanel.add(sep, BorderLayout.WEST);
301                 statusLinePanel.add(status, BorderLayout.CENTER);
302                 
303                 decoratePanel (statusLinePanel);
304                 statusLinePanel.setName("statusLine"); //NOI18N
305
menu.add(statusLinePanel);
306             } else {
307                 JComponent status = getCustomStatusLine();
308                 if (status != null) {
309                     menu.add(status);
310                 }
311             }
312         }
313         
314         return menu;
315     }
316
317      /**
318       * Tries to find custom menu bar component on system file system.
319       * @return menu bar component or <code>null</code> if no menu bar
320       * component is found on system file system.
321       */

322      private static JMenuBar getCustomMenuBar() {
323          try {
324              String JavaDoc fileName = Constants.CUSTOM_MENU_BAR_PATH;
325              if (fileName == null) {
326                  return null;
327              }
328              FileObject fo =
329                  Repository.getDefault().getDefaultFileSystem().findResource(
330                      fileName);
331              if (fo != null) {
332                  DataObject dobj = DataObject.find(fo);
333                  InstanceCookie ic = (InstanceCookie)dobj.getCookie(InstanceCookie.class);
334                  if (ic != null) {
335                      return (JMenuBar)ic.instanceCreate();
336                  }
337              }
338          } catch (Exception JavaDoc e) {
339              Exceptions.printStackTrace(e);
340          }
341          return null;
342      }
343     
344      /**
345       * Tries to find custom status line component on system file system.
346       * @return status line component or <code>null</code> if no status line
347       * component is found on system file system.
348       */

349      private static JComponent getCustomStatusLine() {
350          try {
351              String JavaDoc fileName = Constants.CUSTOM_STATUS_LINE_PATH;
352              if (fileName == null) {
353                  return null;
354              }
355              FileObject fo =
356                  Repository.getDefault().getDefaultFileSystem().findResource(
357                      fileName);
358              if (fo != null) {
359                  DataObject dobj = DataObject.find(fo);
360                  InstanceCookie ic = (InstanceCookie)dobj.getCookie(InstanceCookie.class);
361                  if (ic != null) {
362                      return (JComponent)ic.instanceCreate();
363                  }
364              }
365          } catch (Exception JavaDoc e) {
366              Exceptions.printStackTrace(e);
367          }
368          return null;
369      }
370      
371     /** Creates toolbar component. */
372     private static JComponent getToolbarComponent() {
373         ToolbarPool tp = ToolbarPool.getDefault();
374         tp.waitFinished();
375 // ErrorManager.getDefault().getInstance(MainWindow.class.getName()).log("toolbar config name=" + WindowManagerImpl.getInstance().getToolbarConfigName());
376
// tp.setConfiguration(WindowManagerImpl.getInstance().getToolbarConfigName()); // NOI18N
377

378         return tp;
379     }
380
381     /** Packs main window, to set its border */
382     private void initializeBounds() {
383         Rectangle JavaDoc bounds;
384         if(WindowManagerImpl.getInstance().getEditorAreaState() == Constants.EDITOR_AREA_JOINED) {
385             bounds = WindowManagerImpl.getInstance().getMainWindowBoundsJoined();
386         } else {
387             bounds = WindowManagerImpl.getInstance().getMainWindowBoundsSeparated();
388         }
389         
390         if(!bounds.isEmpty()) {
391             setBounds(bounds);
392         }
393     }
394     
395     /**
396      * don't allow smaller bounds than the one constructed from preffered sizes, making sure everything is visible when
397      * in SDI. #40063
398      */

399     public void setBounds(Rectangle JavaDoc rect) {
400         Rectangle JavaDoc bounds = rect;
401         if (bounds != null) {
402             if (bounds.height < getPreferredSize().height) {
403                 bounds = new Rectangle JavaDoc(bounds.x, bounds.y, bounds.width, getPreferredSize().height);
404             }
405         }
406         super.setBounds(bounds);
407     }
408     
409     /** Prepares main window, has to be called after {@link initializeComponents()}. */
410     public void prepareWindow() {
411         initializeBounds();
412     }
413
414     /** Sets desktop component. */
415     public void setDesktop(Component JavaDoc comp) {
416         if(desktop == comp) {
417             // XXX PENDING revise how to better manipulate with components
418
// so there don't happen unneeded removals.
419
if(desktop != null
420             && !Arrays.asList(desktopPanel.getComponents()).contains(desktop)) {
421                 desktopPanel.add(desktop, BorderLayout.CENTER);
422             }
423             return;
424         }
425
426         if(desktop != null) {
427             desktopPanel.remove(desktop);
428         }
429         
430         desktop = comp;
431         
432         if(desktop != null) {
433             desktopPanel.add(desktop, BorderLayout.CENTER);
434         }
435         invalidate();
436         validate();
437         // use #24291 hack only on Win OS
438
if( isOlderJDK && !System.getProperty("os.name").startsWith("Windows") ) {
439             releaseWaitingForPaintDummyGraphic();
440         }
441
442         repaint();
443     }
444
445     // XXX PENDING used in DnD only.
446
public Component JavaDoc getDesktop() {
447         return desktop;
448     }
449     
450     public boolean hasDesktop() {
451         return desktop != null;
452     }
453
454     // XXX
455
/** Gets bounds of main window without the dektop component. */
456     public Rectangle JavaDoc getPureMainWindowBounds() {
457         Rectangle JavaDoc bounds = getBounds();
458
459         // XXX Substract the desktop height, we know the pure main window
460
// is always at the top, the width is same.
461
if(desktop != null) {
462             Dimension JavaDoc desktopSize = desktop.getSize();
463             bounds.height -= desktopSize.height;
464         }
465         
466         return bounds;
467     }
468
469     // [dafe] Start of #24291 hacky fix, to prevent from main window flicking on
470
// JDK 1.5.x and older. Can be freely deleted when we will drop JDK 1.5.x
471
// support in future
472

473     private Image JavaDoc waitingForPaintDummyImage;
474     private Graphics JavaDoc waitingForPaintDummyGraphic;
475     boolean isOlderJDK = System.getProperty("java.version").startsWith("1.5");
476
477     public void setVisible (boolean flag) {
478         // The setVisible will cause a PaintEvent to be queued up, as a LOW_PRIORITY one
479
// As the painting of my child components occurs, they cause painting of their own
480
// When the PaintEvent queued from the setVisible is finally processed, it assumes
481
// nothing has been displayed and redraws the whole window.
482
// So we make it such that, UNTIL there is the repaint is dispatched, return a graphics
483
// which goes nowhere.
484
if (flag && isOlderJDK) {
485             waitingForPaintDummyImage = new BufferedImage JavaDoc(1, 1, BufferedImage.TYPE_INT_RGB);
486             waitingForPaintDummyGraphic = waitingForPaintDummyImage.getGraphics();
487         }
488         super.setVisible(flag);
489     }
490
491     public void paint(Graphics JavaDoc g) {
492         // As a safeguard, always release the dummy graphic when we get a paint
493
if (waitingForPaintDummyGraphic != null) {
494             releaseWaitingForPaintDummyGraphic();
495             // Since the release did not occur before the getGraphics() call,
496
// I need to get the actual graphics now that I've released
497
g = getGraphics();
498         }
499         super.paint(g);
500     }
501
502     /** Overrides parent version to return fake dummy graphic in certain time
503      * during startup
504      */

505     public Graphics JavaDoc getGraphics () {
506         // Return the dummy graphics that paint nowhere, until we receive a paint()
507
if (waitingForPaintDummyGraphic != null) {
508             // If we are the PaintEvent we are waiting for is being dispatched
509
// we better return the correct graphics.
510
AWTEvent JavaDoc event = EventQueue.getCurrentEvent();
511             if (event == null || (event.getID() != PaintEvent.PAINT && event.getSource() != this)) {
512                 return waitingForPaintDummyGraphic;
513             }
514             releaseWaitingForPaintDummyGraphic();
515         }
516         return super.getGraphics();
517     }
518
519     private void releaseWaitingForPaintDummyGraphic () {
520         if (waitingForPaintDummyGraphic != null) {
521             waitingForPaintDummyGraphic.dispose();
522             waitingForPaintDummyGraphic = null;
523             waitingForPaintDummyImage = null;
524         }
525     }
526
527     // end of #24291 hacky fix
528

529     // Full Screen Mode
530
private boolean isFullScreenMode = false;
531     private Rectangle JavaDoc restoreBounds;
532     private int restoreExtendedState = JFrame.NORMAL;
533     
534     public void setFullScreenMode( boolean fullScreenMode ) {
535         if( isFullScreenMode == fullScreenMode ) {
536             return;
537         }
538         final TopComponent activatedTc = WindowManager.getDefault().getRegistry().getActivated();
539         if( !isFullScreenMode ) {
540             restoreExtendedState = getExtendedState();
541             restoreBounds = getBounds();
542         }
543         isFullScreenMode = fullScreenMode;
544         setVisible( false );
545         dispose();
546         setUndecorated( isFullScreenMode );
547         setExtendedState( isFullScreenMode ? JFrame.MAXIMIZED_BOTH : restoreExtendedState );
548
549         getJMenuBar().setVisible( !isFullScreenMode );
550         getToolbarComponent().setVisible( !isFullScreenMode );
551         if( !isFullScreenMode && restoreExtendedState != JFrame.MAXIMIZED_BOTH ) {
552             setBounds( restoreBounds );
553         }
554         setVisible( true );
555         SwingUtilities.invokeLater( new Runnable JavaDoc() {
556             public void run() {
557                 invalidate();
558                 validate();
559                 repaint();
560                 if( null != activatedTc ) {
561                     activatedTc.requestFocusInWindow();
562                 }
563             }
564         });
565     }
566     
567     public boolean isFullScreenMode() {
568         return isFullScreenMode;
569     }
570 }
571
572
Popular Tags