001    /*
002     * $Id: JXRootPane.java,v 1.5 2006/03/11 23:56:51 rbair Exp $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    
022    package org.jdesktop.swingx;
023    
024    import java.awt.BorderLayout;
025    import java.awt.Component;
026    import java.awt.Container;
027    
028    import javax.swing.BoxLayout;
029    import javax.swing.JMenuBar;
030    import javax.swing.JPanel;
031    import javax.swing.JRootPane;
032    import javax.swing.JToolBar;
033    
034    import org.jdesktop.swingx.event.MessageSource;
035    import org.jdesktop.swingx.event.ProgressSource;
036    
037    /**
038     * Extends the JRootPane by supporting specific placements for a toolbar and a
039     * status bar. If a status bar exists, then toolbars, menus and any
040     * MessageSource components will be registered with the status bar.
041     * <p>
042     * Components should be added using the <code>addComponent</code> method. This
043     * method will walk the containment hierarchy of the added component and will
044     * register all <code>MessageSource</code> or <code>ProgressSource</code>
045     * components.
046     * 
047     * @see JXStatusBar
048     * @see org.jdesktop.swingx.event.MessageEvent
049     * @see org.jdesktop.swingx.event.MessageSource
050     * @see org.jdesktop.swingx.event.ProgressSource
051     * @author Mark Davidson
052     */
053    public class JXRootPane extends JRootPane {
054    
055        private JXStatusBar statusBar;
056    
057        private JToolBar toolBar;
058    
059        private JPanel contentPanel;
060    
061        public JXRootPane() {
062            contentPanel = new JPanel();
063            contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
064    
065            getContentPane().add(contentPanel, BorderLayout.CENTER);
066        }
067    
068        /**
069         * Adds a component to the root pane. If this component and/or it's children
070         * is a <code>MessageSource</code> then it will be registered with the
071         * status bar.
072         */
073        public void addComponent(Component comp) {
074            contentPanel.add(comp);
075            registerStatusBar(comp);
076        }
077    
078        /**
079         * Removes a component from the center panel.
080         */
081        public void removeComponent(Component comp) {
082            contentPanel.remove(comp);
083            unregisterStatusBar(statusBar, comp);
084        }
085    
086        /**
087         * Return an array of components that were added to the content panel with
088         * addComponent.
089         */
090        public Component[] getContentComponents() {
091            return contentPanel.getComponents();
092        }
093    
094        private void registerStatusBar(Component comp) {
095            if (statusBar == null || comp == null) {
096                return;
097            }
098            if (comp instanceof MessageSource) {
099                MessageSource source = (MessageSource) comp;
100    //            source.addMessageListener(statusBar);
101            }
102            if (comp instanceof ProgressSource) {
103                ProgressSource source = (ProgressSource) comp;
104    //            source.addProgressListener(statusBar);
105            }
106            if (comp instanceof Container) {
107                Component[] comps = ((Container) comp).getComponents();
108                for (int i = 0; i < comps.length; i++) {
109                    registerStatusBar(comps[i]);
110                }
111            }
112        }
113    
114        private void unregisterStatusBar(JXStatusBar statusBar, Component comp) {
115            if (statusBar == null || comp == null) {
116                return;
117            }
118            if (comp instanceof MessageSource) {
119                MessageSource source = (MessageSource) comp;
120    //            source.removeMessageListener(statusBar);
121            }
122            if (comp instanceof ProgressSource) {
123                ProgressSource source = (ProgressSource) comp;
124    //            source.removeProgressListener(statusBar);
125            }
126            if (comp instanceof Container) {
127                Component[] comps = ((Container) comp).getComponents();
128                for (int i = 0; i < comps.length; i++) {
129                    unregisterStatusBar(statusBar, comps[i]);
130                }
131            }
132        }
133    
134        /**
135         * Set the status bar for this root pane. Any components held by this root
136         * pane will be registered. If this is replacing an existing status bar then
137         * the existing component will be unregistered from the old status bar.
138         * 
139         * @param statusBar
140         *            the status bar to use
141         */
142        public void setStatusBar(JXStatusBar statusBar) {
143            JXStatusBar oldStatusBar = this.statusBar;
144            this.statusBar = statusBar;
145    
146            if (statusBar != null) {
147                if (handler == null) {
148                    // Create the new mouse handler and register the toolbar
149                    // and menu components.
150    //                handler = new MouseMessagingHandler(this, statusBar);
151                    if (toolBar != null) {
152    //                    handler.registerListeners(toolBar.getComponents());
153                    }
154                    if (menuBar != null) {
155    //                    handler.registerListeners(menuBar.getSubElements());
156                    }
157                } else {
158    //                handler.setMessageListener(statusBar);
159                }
160            }
161    
162            Component[] comps = contentPanel.getComponents();
163            for (int i = 0; i < comps.length; i++) {
164                // Unregister the old status bar.
165                unregisterStatusBar(oldStatusBar, comps[i]);
166    
167                // register the new status bar.
168                registerStatusBar(comps[i]);
169            }
170            if (oldStatusBar != null) {
171                getContentPane().remove(oldStatusBar);
172            }
173            if (statusBar != null) {
174                getContentPane().add(BorderLayout.SOUTH, statusBar);
175            }
176        }
177    
178        public JXStatusBar getStatusBar() {
179            return statusBar;
180        }
181    
182        private MouseMessagingHandler handler;
183    
184        /**
185         * Set the toolbar bar for this root pane. If the status bar exists, then
186         * all components will be registered with a
187         * <code>MouseMessagingHandler</code> so that mouse over messages will be
188         * sent to the status bar.
189         * 
190         * @param toolBar
191         *            the toolbar to register
192         * @see MouseMessagingHandler
193         */
194        public void setToolBar(JToolBar toolBar) {
195            JToolBar oldToolBar = this.toolBar;
196            this.toolBar = toolBar;
197    
198            if (handler != null && oldToolBar != null) {
199                handler.unregisterListeners(oldToolBar.getComponents());
200            }
201    
202            if (handler != null && toolBar != null) {
203                handler.registerListeners(toolBar.getComponents());
204            }
205    
206            getContentPane().add(BorderLayout.NORTH, toolBar);
207        }
208    
209        public JToolBar getToolBar() {
210            return toolBar;
211        }
212    
213        /**
214         * Set the menu bar for this root pane. If the status bar exists, then all
215         * components will be registered with a <code>MouseMessagingHandler</code>
216         * so that mouse over messages will be sent to the status bar.
217         * 
218         * @param menuBar
219         *            the menu bar to register
220         * @see MouseMessagingHandler
221         */
222        public void setJMenuBar(JMenuBar menuBar) {
223            JMenuBar oldMenuBar = this.menuBar;
224    
225            super.setJMenuBar(menuBar);
226    
227            if (handler != null && oldMenuBar != null) {
228                handler.unregisterListeners(oldMenuBar.getSubElements());
229            }
230    
231            if (handler != null && menuBar != null) {
232                handler.registerListeners(menuBar.getSubElements());
233            }
234        }
235    
236    }