KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > ui > tabbedui > AbstractTabbedUI


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------------
28  * AbstractTabbedUI.java
29  * ---------------------
30  * (C)opyright 2004, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Thomas Morgner;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: AbstractTabbedUI.java,v 1.9 2005/11/03 09:55:27 mungady Exp $
36  *
37  * Changes
38  * -------------------------
39  * 16-Feb-2004 : Initial version
40  * 07-Jun-2004 : Added standard header (DG);
41  */

42
43 package org.jfree.ui.tabbedui;
44
45 import java.awt.BorderLayout JavaDoc;
46 import java.awt.Component JavaDoc;
47 import java.awt.Window JavaDoc;
48 import java.awt.event.ActionEvent JavaDoc;
49 import java.beans.PropertyChangeEvent JavaDoc;
50 import java.beans.PropertyChangeListener JavaDoc;
51 import java.util.ArrayList JavaDoc;
52
53 import javax.swing.AbstractAction JavaDoc;
54 import javax.swing.Action JavaDoc;
55 import javax.swing.JComponent JavaDoc;
56 import javax.swing.JMenu JavaDoc;
57 import javax.swing.JMenuBar JavaDoc;
58 import javax.swing.JPanel JavaDoc;
59 import javax.swing.JTabbedPane JavaDoc;
60 import javax.swing.SwingConstants JavaDoc;
61 import javax.swing.SwingUtilities JavaDoc;
62 import javax.swing.event.ChangeEvent JavaDoc;
63 import javax.swing.event.ChangeListener JavaDoc;
64
65 import org.jfree.util.Log;
66
67 /**
68  * A tabbed GUI. All views on the data are contained in tabs.
69  *
70  * @author Thomas Morgner
71  */

72 public abstract class AbstractTabbedUI extends JComponent JavaDoc {
73
74     /** The menu bar property key. */
75     public static final String JavaDoc JMENUBAR_PROPERTY = "jMenuBar";
76     
77     /** The global menu property. */
78     public static final String JavaDoc GLOBAL_MENU_PROPERTY = "globalMenu";
79
80     /**
81      * An exit action.
82      */

83     protected class ExitAction extends AbstractAction JavaDoc {
84
85         /**
86          * Defines an <code>Action</code> object with a default
87          * description string and default icon.
88          */

89         public ExitAction() {
90             putValue(NAME, "Exit");
91         }
92
93         /**
94          * Invoked when an action occurs.
95          *
96          * @param e the event.
97          */

98         public void actionPerformed(final ActionEvent JavaDoc e) {
99             attempExit();
100         }
101
102     }
103
104     /**
105      * A tab change handler.
106      */

107     private class TabChangeHandler implements ChangeListener JavaDoc {
108
109         /** The tabbed pane to which this handler is registered. */
110         private final JTabbedPane JavaDoc pane;
111
112         /**
113          * Creates a new handler.
114          *
115          * @param pane the pane.
116          */

117         public TabChangeHandler(final JTabbedPane JavaDoc pane) {
118             this.pane = pane;
119         }
120
121         /**
122          * Invoked when the target of the listener has changed its state.
123          *
124          * @param e a ChangeEvent object
125          */

126         public void stateChanged(final ChangeEvent JavaDoc e) {
127             setSelectedEditor(this.pane.getSelectedIndex());
128         }
129     }
130
131     /**
132      * A tab enable change listener.
133      */

134     private class TabEnableChangeListener implements PropertyChangeListener JavaDoc {
135         
136         /**
137          * Default constructor.
138          */

139         public TabEnableChangeListener() {
140         }
141
142         /**
143          * This method gets called when a bound property is changed.
144          *
145          * @param evt A PropertyChangeEvent object describing the event source
146          * and the property that has changed.
147          */

148         public void propertyChange(final PropertyChangeEvent JavaDoc evt) {
149             if (evt.getPropertyName().equals("enabled") == false) {
150                 Log.debug ("PropertyName");
151                 return;
152             }
153             if (evt.getSource() instanceof RootEditor == false) {
154                 Log.debug ("Source");
155                 return;
156             }
157             final RootEditor editor = (RootEditor) evt.getSource();
158             updateRootEditorEnabled(editor);
159         }
160     }
161
162     /** The list of root editors. One for each tab. */
163     private ArrayList JavaDoc rootEditors;
164     /** The tabbed pane filling the content area. */
165     private JTabbedPane JavaDoc tabbedPane;
166     /** The index of the currently selected root editor. */
167     private int selectedRootEditor;
168     /** The current toolbar. */
169     private JComponent JavaDoc currentToolbar;
170     /** The container component for the toolbar. */
171     private JPanel JavaDoc toolbarContainer;
172     /** The close action assigned to this UI. */
173     private Action JavaDoc closeAction;
174     /** The current menu bar. */
175     private JMenuBar JavaDoc jMenuBar;
176     /** Whether the UI should build a global menu from all root editors. */
177     private boolean globalMenu;
178
179     /**
180      * Default constructor.
181      */

182     public AbstractTabbedUI() {
183         this.selectedRootEditor = -1;
184
185         this.toolbarContainer = new JPanel JavaDoc();
186         this.toolbarContainer.setLayout(new BorderLayout JavaDoc());
187
188         this.tabbedPane = new JTabbedPane JavaDoc(SwingConstants.BOTTOM);
189         this.tabbedPane.addChangeListener(new TabChangeHandler(this.tabbedPane));
190
191         this.rootEditors = new ArrayList JavaDoc();
192
193         setLayout(new BorderLayout JavaDoc());
194         add(this.toolbarContainer, BorderLayout.NORTH);
195         add(this.tabbedPane, BorderLayout.CENTER);
196
197         this.closeAction = createCloseAction();
198     }
199
200     /**
201      * Returns the tabbed pane.
202      *
203      * @return The tabbed pane.
204      */

205     protected JTabbedPane JavaDoc getTabbedPane() {
206         return this.tabbedPane;
207     }
208
209     /**
210      * Defines whether to use a global unified menu bar, which contains
211      * all menus from all tab-panes or whether to use local menubars.
212      * <p>
213      * From an usability point of view, global menubars should be preferred,
214      * as this way users always see which menus are possibly available and
215      * do not wonder where the menus are disappearing.
216      *
217      * @return true, if global menus should be used, false otherwise.
218      */

219     public boolean isGlobalMenu() {
220         return this.globalMenu;
221     }
222
223     /**
224      * Sets the global menu flag.
225      *
226      * @param globalMenu the flag.
227      */

228     public void setGlobalMenu(final boolean globalMenu) {
229         this.globalMenu = globalMenu;
230         if (isGlobalMenu()) {
231             setJMenuBar(updateGlobalMenubar());
232         }
233         else {
234             if (getRootEditorCount () > 0) {
235               setJMenuBar(createEditorMenubar(getRootEditor(getSelectedEditor())));
236             }
237         }
238     }
239
240     /**
241      * Returns the menu bar.
242      *
243      * @return The menu bar.
244      */

245     public JMenuBar JavaDoc getJMenuBar() {
246         return this.jMenuBar;
247     }
248
249     /**
250      * Sets the menu bar.
251      *
252      * @param menuBar the menu bar.
253      */

254     protected void setJMenuBar(final JMenuBar JavaDoc menuBar) {
255         final JMenuBar JavaDoc oldMenuBar = this.jMenuBar;
256         this.jMenuBar = menuBar;
257         firePropertyChange(JMENUBAR_PROPERTY, oldMenuBar, menuBar);
258     }
259
260     /**
261      * Creates a close action.
262      *
263      * @return A close action.
264      */

265     protected Action JavaDoc createCloseAction() {
266         return new ExitAction();
267     }
268
269     /**
270      * Returns the close action.
271      *
272      * @return The close action.
273      */

274     public Action JavaDoc getCloseAction() {
275         return this.closeAction;
276     }
277
278     /**
279      * Returns the prefix menus.
280      *
281      * @return The prefix menus.
282      */

283     protected abstract JMenu JavaDoc[] getPrefixMenus();
284
285     /**
286      * The postfix menus.
287      *
288      * @return The postfix menus.
289      */

290     protected abstract JMenu JavaDoc[] getPostfixMenus();
291
292     /**
293      * Adds menus.
294      *
295      * @param menuBar the menu bar
296      * @param customMenus the menus that should be added.
297      */

298     private void addMenus(final JMenuBar JavaDoc menuBar, final JMenu JavaDoc[] customMenus) {
299         for (int i = 0; i < customMenus.length; i++) {
300             menuBar.add(customMenus[i]);
301         }
302     }
303
304     /**
305      * Updates the global menu bar.
306      * @return the fully initialized menu bar.
307      */

308     private JMenuBar JavaDoc updateGlobalMenubar () {
309       JMenuBar JavaDoc menuBar = getJMenuBar();
310       if (menuBar == null) {
311           menuBar = new JMenuBar JavaDoc();
312       }
313       else {
314           menuBar.removeAll();
315       }
316
317       addMenus(menuBar, getPrefixMenus());
318       for (int i = 0; i < this.rootEditors.size(); i++)
319       {
320           final RootEditor editor = (RootEditor) this.rootEditors.get(i);
321           addMenus(menuBar, editor.getMenus());
322       }
323       addMenus(menuBar, getPostfixMenus());
324       return menuBar;
325     }
326
327     /**
328      * Creates a menu bar.
329      *
330      * @param root
331      * @return A menu bar.
332      */

333     private JMenuBar JavaDoc createEditorMenubar(final RootEditor root) {
334
335         JMenuBar JavaDoc menuBar = getJMenuBar();
336         if (menuBar == null) {
337             menuBar = new JMenuBar JavaDoc();
338         }
339         else {
340             menuBar.removeAll();
341         }
342
343         addMenus(menuBar, getPrefixMenus());
344         if (isGlobalMenu())
345         {
346             for (int i = 0; i < this.rootEditors.size(); i++)
347             {
348                 final RootEditor editor = (RootEditor) this.rootEditors.get(i);
349                 addMenus(menuBar, editor.getMenus());
350             }
351         }
352         else
353         {
354             addMenus(menuBar, root.getMenus());
355         }
356         addMenus(menuBar, getPostfixMenus());
357         return menuBar;
358     }
359
360     /**
361      * Adds a root editor.
362      *
363      * @param rootPanel the root panel.
364      */

365     public void addRootEditor(final RootEditor rootPanel) {
366         this.rootEditors.add(rootPanel);
367         this.tabbedPane.add(rootPanel.getEditorName(), rootPanel.getMainPanel());
368         rootPanel.addPropertyChangeListener("enabled", new TabEnableChangeListener());
369         updateRootEditorEnabled(rootPanel);
370         if (getRootEditorCount () == 1) {
371             setSelectedEditor(0);
372         }
373         else if (isGlobalMenu()) {
374             setJMenuBar(updateGlobalMenubar());
375         }
376     }
377
378     /**
379      * Returns the number of root editors.
380      *
381      * @return The count.
382      */

383     public int getRootEditorCount () {
384         return this.rootEditors.size();
385     }
386
387     /**
388      * Returns the specified editor.
389      *
390      * @param pos the position index.
391      *
392      * @return The editor at the given position.
393      */

394     public RootEditor getRootEditor(final int pos) {
395         return (RootEditor) this.rootEditors.get(pos);
396     }
397
398     /**
399      * Returns the selected editor.
400      *
401      * @return The selected editor.
402      */

403     public int getSelectedEditor() {
404         return this.selectedRootEditor;
405     }
406
407     /**
408      * Sets the selected editor.
409      *
410      * @param selectedEditor the selected editor.
411      */

412     public void setSelectedEditor(final int selectedEditor) {
413         final int oldEditor = this.selectedRootEditor;
414         if (oldEditor == selectedEditor) {
415             // no change - so nothing to do!
416
return;
417         }
418         this.selectedRootEditor = selectedEditor;
419         // make sure that only the selected editor is active.
420
// all other editors will be disabled, if needed and
421
// not touched if they are already in the correct state
422

423         for (int i = 0; i < this.rootEditors.size(); i++) {
424             final boolean shouldBeActive = (i == selectedEditor);
425             final RootEditor container =
426                 (RootEditor) this.rootEditors.get(i);
427             if (container.isActive() && (shouldBeActive == false)) {
428                 container.setActive(false);
429             }
430         }
431
432         if (this.currentToolbar != null) {
433             closeToolbar();
434             this.toolbarContainer.removeAll();
435             this.currentToolbar = null;
436         }
437
438         for (int i = 0; i < this.rootEditors.size(); i++) {
439             final boolean shouldBeActive = (i == selectedEditor);
440             final RootEditor container =
441                 (RootEditor) this.rootEditors.get(i);
442             if ((container.isActive() == false) && (shouldBeActive == true)) {
443                 container.setActive(true);
444                 setJMenuBar(createEditorMenubar(container));
445                 this.currentToolbar = container.getToolbar();
446                 if (this.currentToolbar != null) {
447                     this.toolbarContainer.add
448                         (this.currentToolbar, BorderLayout.CENTER);
449                     this.toolbarContainer.setVisible(true);
450                     this.currentToolbar.setVisible(true);
451                 }
452                 else {
453                     this.toolbarContainer.setVisible(false);
454                 }
455
456                 this.getJMenuBar().repaint();
457             }
458         }
459     }
460
461     /**
462      * Closes the toolbar.
463      */

464     private void closeToolbar() {
465         if (this.currentToolbar != null) {
466             if (this.currentToolbar.getParent() != this.toolbarContainer) {
467                 // ha!, the toolbar is floating ...
468
// Log.debug (currentToolbar.getParent());
469
final Window JavaDoc w = SwingUtilities.windowForComponent(this.currentToolbar);
470                 if (w != null) {
471                     w.setVisible(false);
472                     w.dispose();
473                 }
474             }
475             this.currentToolbar.setVisible(false);
476         }
477     }
478
479     /**
480      * Attempts to exit.
481      */

482     protected abstract void attempExit();
483
484     /**
485      * Update handler for the enable state of the root editor.
486      *
487      * @param editor the editor.
488      */

489     protected void updateRootEditorEnabled(final RootEditor editor) {
490
491         final boolean enabled = editor.isEnabled();
492         for (int i = 0; i < this.tabbedPane.getTabCount(); i++) {
493             final Component JavaDoc tab = this.tabbedPane.getComponentAt(i);
494             if (tab == editor.getMainPanel()) {
495                 this.tabbedPane.setEnabledAt(i, enabled);
496                 return;
497             }
498         }
499     }
500 }
501
Popular Tags