001    /*
002     * Copyright 2002-2006 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.dialog;
017    
018    import java.util.HashMap;
019    import java.util.List;
020    import java.util.Map;
021    
022    import javax.swing.JComponent;
023    import javax.swing.JTabbedPane;
024    import javax.swing.event.ChangeEvent;
025    import javax.swing.event.ChangeListener;
026    
027    import org.springframework.richclient.core.LabeledObjectSupport;
028    import org.springframework.richclient.dialog.control.ExtTabbedPane;
029    import org.springframework.richclient.dialog.control.Tab;
030    import org.springframework.richclient.dialog.control.VetoableSingleSelectionModel;
031    
032    /**
033     * A concrete implementation of <code>CompositeDialogPage</code> that presents
034     * the child pages in a <code>JTabbedPane</code>.
035     * <p>
036     * Each child page is placed into a separate tab of the <code>JTabbedPane</code>.
037     * This class also decorates the tab titles to indicate the page completed
038     * status.
039     * <p>
040     * Has support for hiding/showing <code>DialogPage</code>s; on
041     * <code>DialogPage.setVisible(false)</code> the tab for the page is removed
042     * from the ui, on <code>DialogPage.setVisible(true)</code> it is shown again.
043     * 
044     * @author Oliver Hutchison
045     * @author Peter De Bruycker
046     */
047    public class TabbedDialogPage extends CompositeDialogPage {
048            private ExtTabbedPane tabbedPaneView;
049    
050            private Map page2tab = new HashMap();
051    
052            private Map tab2Page = new HashMap();
053    
054            private boolean settingSelection;
055    
056            public TabbedDialogPage(String pageId) {
057                    super(pageId);
058            }
059    
060            public TabbedDialogPage(String pageId, boolean autoConfigure) {
061                    super(pageId, autoConfigure);
062            }
063    
064            protected JComponent createControl() {
065                    createPageControls();
066                    final JTabbedPane tabbedPane = getComponentFactory().createTabbedPane();
067                    tabbedPaneView = new ExtTabbedPane(tabbedPane);
068    
069                    List pages = getPages();
070                    for (int i = 0; i < pages.size(); i++) {
071                            final DialogPage page = (DialogPage) pages.get(i);
072                            final Tab tab = new Tab();
073    
074                            JComponent control = page.getControl();
075                            control.setPreferredSize(getLargestPageSize());
076    
077                            tab.setComponent(control);
078                            tab.setVisible(page.isVisible());
079                            tab.setEnabled(page.isEnabled());
080                            decorateTab(tab, page);
081    
082                            page2tab.put(page, tab);
083                            tab2Page.put(tab, page);
084                            tabbedPaneView.addTab(tab);
085                    }
086                    
087                    tabbedPane.setModel(new VetoableSingleSelectionModel() {
088                            protected boolean selectionAllowed(int index) {
089                                    return canChangeTabs();
090                            }
091                    });
092                    
093                    tabbedPaneView.addChangeListener(new ChangeListener() {
094                            public void stateChanged(ChangeEvent e) {
095                                    int index = tabbedPane.getSelectedIndex();
096                                    
097                                    if (index >= 0) {
098                                            index = tabbedPaneView.convertUIIndexToModelIndex(index);
099                                            Tab tab = tabbedPaneView.getTab(index);
100                                            setActivePage((DialogPage) tab2Page.get(tab));
101                                    }
102                                    else {
103                                            setActivePage(null);
104                                    }
105                            }
106                    });
107                    
108                    // show first visible tab
109                    setActivePage((DialogPage) pages.get(tabbedPaneView.convertUIIndexToModelIndex(0)));
110                    return tabbedPane;
111            }
112    
113            /**
114             * Sets the active page of this TabbedDialogPage. This method will also
115             * select the tab wich displays the new active page.
116             * 
117             * @param activePage the page to be made active. Must be one of the child
118             * pages.
119             */
120            public void setActivePage(DialogPage page) {
121                    if (settingSelection) {
122                            return;
123                    }
124    
125                    try {
126                            settingSelection = true;
127    
128                            super.setActivePage(page);
129                            if (page != null) {
130                                    Tab tab = (Tab) page2tab.get(page);
131                                    tabbedPaneView.selectTab(tab);
132                            }
133                    }
134                    finally {
135                            settingSelection = false;
136                    }
137            }
138    
139            protected boolean canChangeTabs() {
140                    return true;
141            }
142    
143            protected void updatePageComplete(DialogPage page) {
144                    super.updatePageComplete(page);
145    
146                    if (tabbedPaneView != null) {
147                            Tab tab = (Tab) page2tab.get(page);
148                            decorateTab(tab, page);
149                    }
150            }
151    
152            protected void decorateTab(Tab tab, DialogPage page) {
153                    tab.setTitle(getDecoratedPageTitle(page));
154                    tab.setTooltip(page.getDescription());
155                    if (page instanceof LabeledObjectSupport) {
156                            tab.setMnemonic(((LabeledObjectSupport) page).getMnemonic());
157                    }
158                    tab.setIcon(page.getIcon());
159            }
160    
161            protected void updatePageVisibility(DialogPage page) {
162                    Tab tab = getTab(page);
163                    tab.setVisible(page.isVisible());
164            }
165            
166            protected void updatePageEnabled(DialogPage page) {
167                    Tab tab = getTab(page);
168                    tab.setEnabled(page.isEnabled());
169            }
170    
171            protected void updatePageLabels(DialogPage page) {
172                    Tab tab = getTab(page);
173                    tab.setTitle(getDecoratedPageTitle(page));
174            }
175    
176            protected final Tab getTab(final DialogPage page) {
177                    return (Tab) page2tab.get(page);
178            }
179    }