/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.gui.impl; import gov.nasa.arc.mct.gui.util.UniqueNameGenerator; import java.awt.BorderLayout; import java.awt.Component; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.event.ChangeListener; /** * A tabbed pane that hides the tabs when there is only one tab. Since <code>JTabbedPane</code> * always shows the tabs, we implement a <code>JPanel</code> instead, with two possible * Components inside: either the component that would be shown in the first tab, or an * actual <code>JTabbedPane</code> with all components and tab titles. * * We implement a portion of the <code>JTabbedPane</code> protocol, intended to be the * most useful methods. */ @SuppressWarnings("serial") public class HidableTabbedPane extends JPanel { /** The component in the first tab. We have to keep track of it here, * because we can't insert it simultaneously into the first tab in * the <code>JTabbedPane</code> and into the top-level panel. We'll * remove it from one and place into the other as needed. */ private Component firstComponent; /** The tabbed pane holding all tabs. */ private JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); /** A dummy component used as the first tab component when there is only one tab, * since Java doesn't like the same object as a child of two different containers. */ private JPanel placeholder = new JPanel(); /** * Create a new hideable tabbed pane with no tabs. */ public HidableTabbedPane() { this.firstComponent = null; setLayout(new BorderLayout()); instrumentNames(); } private void instrumentNames() { setName(UniqueNameGenerator.get("hidableTabbedPane")); tabs.setName("tabbedPaneWithin"); } /** * Create a new hideable tabbed pane with the given title and component for the * first tab (which will be hidden until we add more tabs). * * @param firstTabTitle the textual title of the first tab * @param firstComponent the component to show in the first tab */ public HidableTabbedPane(String firstTabTitle, Component firstComponent) { this(); this.firstComponent = firstComponent; addTab(firstTabTitle, placeholder); add(firstComponent, BorderLayout.CENTER); } /** * Get the number of tabs in the pane. * * @return the number of tabs */ public int getTabCount() { return tabs.getTabCount(); } /** * Get the index of the selected tab, 0-relative. * * @return the selected tab index */ public int getSelectedIndex() { if (tabs.getTabCount() <= 1) { return 0; } else { return tabs.getSelectedIndex(); } } /** * Set the selected tab index. The index must be a valid tab index or -1, which * indicates that no tab should be selected (can also be used when there are no * tabs in the tabbedpane). * * @param index the new selected tab index */ public void setSelectedIndex(int index) { tabs.setSelectedIndex(index); } /** * Get the component shown in the context area of the given tab. * * @param index the index of the tab, 0-relative * @return the component in the content area of the tab */ public Component getComponentAt(int index) { if (index == 0) { return firstComponent; } else { return tabs.getComponentAt(index); } } /** * Get the component in the tab label at the given index. * * @param index the tab whose tab component we want, 0-relative * @return the component for the tab label */ public Component getTabComponentAt(int index) { return tabs.getTabComponentAt(index); } /** * Change the component in the content area for a tab. * * @param index the index of the tab to change * @param component the new component for the content area of the tab */ public void setComponentAt(int index, Component component) { if (isTabsShown()) { tabs.setComponentAt(index, component); } if (index == 0) { if (!isTabsShown()) { if (firstComponent != null) { remove(firstComponent); } if (component != null) { add(component, BorderLayout.CENTER); } } firstComponent = component; } validate(); } /** * Set the tab label component for a tab. * * @param index the index of the tab * @param component the component for the tab label */ public void setTabComponentAt(int index, Component component) { tabs.setTabComponentAt(index, component); } /** * Check whether the tabs are shown. We show the tabs whenever the tab count * is greater than one. * * @return true, if the tabs are shown */ public boolean isTabsShown() { return (tabs.getTabCount() > 1); } /** * Add a new tab with a textual title and content area component. Show the tabs, * if we then have more than one tab. * * @param title the title for the new tab * @param component the component for the content area */ public void addTab(String title, Component component) { tabs.add(title, component); if (tabs.getTabCount() == 2) { showTabs(); } } /** * Remove a tab. Hide the tabs, if we then have only one tab. * * @param index the index of the tab to remove */ public void removeTabAt(int index) { tabs.removeTabAt(index); if (tabs.getTabCount() >= 1) { firstComponent = tabs.getComponentAt(0); } if (tabs.getTabCount() == 1) { hideTabs(); } } /** * Show the tabs. Move the first component into the first tab. */ protected void showTabs() { if (firstComponent != null) { remove(firstComponent); } tabs.setComponentAt(0, firstComponent); add(tabs, BorderLayout.CENTER); validate(); } /** * Hide the tabs. Move the first component from the first tab * to be the entire content area. */ protected void hideTabs() { remove(tabs); tabs.setComponentAt(0, placeholder); add(firstComponent, BorderLayout.CENTER); validate(); } /** * Add a listener to notify when the currently selected tab changes. * * @param listener the listener */ public void addChangeListener(ChangeListener listener) { tabs.addChangeListener(listener); } }