/* class JTabbedPane * * Copyright (C) 2001-2003 R M Pitman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Modified Jul 14, 2003 by Tadpole Computer, Inc. * Modifications Copyright 2003 by Tadpole Computer, Inc. * * Modifications are hereby licensed to all parties at no charge under * the same terms as the original. * * Modified to allow tabs to be focus traversable. Also added the * setEnabledAt and isEnabledAt methods. */ package charvax.swing; import java.util.Enumeration; import java.util.Vector; import charva.awt.BorderLayout; import charva.awt.Component; import charva.awt.Container; import charva.awt.Dimension; import charva.awt.Insets; import charva.awt.Point; import charva.awt.Toolkit; import charva.awt.event.ActionEvent; import charva.awt.event.ActionListener; /** * A component that lets the user display one of a set of components * (usually Panels) at a time. * The management of the tab-selection has to be performed outside of this * component because it is possible that the currently selected tab does * not contain any focusTraversable components. In this case, this JTabbedPane * will never get the keyboard focus. */ public class JTabbedPane extends Container { /** * Construct a JTabbedPane. */ public JTabbedPane() { _insets = new Insets(2,1,1,1); _layoutMgr = new BorderLayout(); } /** * Add the specified component to the tabbed pane. If * <code>constraints</code> is a String, it will be used as the tab's * title; otherwise the component's name will be used as the title. */ public void add(Component component_, Object constraints_) { String label; if (constraints_ instanceof String) label = (String) constraints_; else label = component_.getName(); int labelno = _tabComponents.size() + 1; String keylabel = "F" + labelno; addTab(label, null, component_, keylabel); } /** * Add a new tab with the specified component, title and function-key. * @param title_ The title of this tab. * @param icon_ An icon representing the component being added. This is * not used and is just for compatibility with Swing. Pass null for this * parameter. * @param component_ The component to be added in this tab. * @param keylabel_ A String representing the key that must be pressed to * select this tab. */ public void addTab(String title_, Object icon_, Component component_, String keylabel_) { TabButton tb = new TabButton(title_, component_, keylabel_); _tabComponents.add(component_); // arrange for our TabButton to be in the focus list... _components.add(_tabs.size(), tb); tb.setParent(this); _tabs.add(tb); _buttongroup.add(tb); if (_selectedIndex == -1) { setSelectedIndex(0); tb.setSelected(true); } /* If this component is already displayed, generate a PaintEvent * and post it onto the queue. */ else if (isDisplayed()) { repaint(); } } /** * */ public void setSelectedIndex(int index_) { if (index_ >= _tabComponents.size()) throw new IndexOutOfBoundsException(); if (index_ == _selectedIndex) return; /* Remove the previously-selected component from the container. */ if (_selectedIndex != -1) { super.remove((Component)_tabComponents.elementAt(_selectedIndex)); //_components.remove(_tabComponents) //_currentFocus = null; } /* Make the TabButton selected as well */ TabButton tb = (TabButton) _tabs.elementAt(index_); tb.setSelected(true); /* Add the newly-selected component to the container. */ Component selected = (Component) _tabComponents.elementAt(index_); super.add(selected); super.validate(); //_layoutMgr.doLayout(this); _selectedIndex = index_; /* If this component is already displayed, generate a PaintEvent * and post it onto the queue. */ repaint(); } public int getSelectedIndex() { return _selectedIndex; } public void setSelectedComponent(Component component_) { int index = _tabComponents.indexOf(component_); setSelectedIndex(index); } /** Override the method in Container. */ public Dimension getSize() { return minimumSize(); } /** Override the method in Container. */ public Dimension minimumSize() { if (super.isValid()) return _minimumSize; /* Scan through the components in each tab and determine * the smallest rectangle that will enclose all of them. */ int width = 0; int height = 0; Enumeration<Component> e = _tabComponents.elements(); while (e.hasMoreElements()) { Component c = e.nextElement(); Dimension size = c.minimumSize(); if (size.width > width) width = size.width; if (size.height > height) height = size.height; } /* Now scan through the titles of the tabs, and determine the width * that all of them will fit into. */ int tabwidth = 0; Enumeration<TabButton> e2 = _tabs.elements(); while (e2.hasMoreElements()) { tabwidth += e2.nextElement().getWidth(); } tabwidth += 2; if (tabwidth > width) width = tabwidth; /* Take into account the border and the height of the tabs. */ _minimumSize = new Dimension(width + _insets.left + _insets.right, height + _insets.top + _insets.bottom); _isValid = true; return _minimumSize; } public void draw(Toolkit toolkit) { /* Get the absolute origin of this component. */ Point origin = getLocationOnScreen(); Point relative = new Point(0, 0); int colorpair = getCursesColor(); /* Draw the enclosing frame */ Dimension size = getSize(); toolkit.blankBox(origin, size, colorpair); toolkit.drawBox(origin.addOffset(0,1), new Dimension(size.width, size.height-1), colorpair); /* Draw each of the tabs */ int hoffset = 1; Enumeration<TabButton> e = _tabs.elements(); for (int i=0; e.hasMoreElements(); i++) { TabButton tb = (TabButton) e.nextElement(); tb.setLocation(relative.addOffset(hoffset, 0)); tb.draw(toolkit); hoffset += tb.getWidth(); } /* Now draw the selected component. */ if (_selectedIndex != -1) { Component component = (Component) _tabComponents.elementAt(_selectedIndex); /* Note that we draw the component even if isVisible() would be * false; it doesn't make sense to make a component invisible * in a JTabbedPane. */ component.draw(toolkit); } } /** Removes the tab and component which corresponds to the specified * index. */ public void remove(int index) { //save this just in case Component selected = (Component) _tabComponents.elementAt(0); _tabComponents.remove(index); super.remove((Component) _tabs.elementAt(index)); _tabs.remove(index); if (getSelectedIndex() == index) { if (index - 1 < 0) { if (getTabCount() > 0) { setSelectedIndex(0); } else { //nothing left, this causes exception _selectedIndex = -1; super.remove(selected); super.validate(); } } else { setSelectedIndex(index - 1); } } if (isDisplayed()) { repaint(); } } /** Returns the first tab index with the specified title, or * -1 if no tab has the title. */ public int indexOfTab(String title) { for (int i = 0; i < _tabs.size(); i++) { if (title.equals(((TabButton) _tabs.elementAt(i)).getText())) { return (i); } } return (-1); } /** Returns the title of the tab with the specified index. */ public String getTitleAt(int index) { return ((TabButton) _tabs.elementAt(index)).getText(); } /** Sets the title of the tab with the specified index. */ public void setTitleAt(int index, String title) { ((TabButton) _tabs.elementAt(index)).setText(title); } /** Make the tab at the specified index enabled. */ public void setEnabledAt(int index, boolean enabled) { ((TabButton) _tabs.elementAt(index)).setEnabled(enabled); } /** Returns true if the tab the index is enabled. */ public boolean isEnabledAt(int index) { return ((TabButton) _tabs.elementAt(index)).isEnabled(); } /** Returns the number of tabs in this tabbedpane. */ public int getTabCount() { return _tabs.size(); } public void debug(int level_) { for (int i=0; i<level_; i++) System.err.print(" "); System.err.print("JTabbedPane origin=" + _origin + " size=" + _size + " _selectedIndex=" + _selectedIndex + " tabtitles ="); Enumeration<TabButton> e = _tabs.elements(); while (e.hasMoreElements()) { String title = ((TabButton) e.nextElement()).getText(); System.err.print(" " + title + " "); } System.err.println(""); super.debug(level_ + 1); } //==================================================================== // INSTANCE VARIABLES private Vector<Component> _tabComponents = new Vector<Component>(); private Vector<TabButton> _tabs = new Vector<TabButton>(); private int _selectedIndex = -1; private ButtonGroup _buttongroup = new ButtonGroup(); private class TabButton extends JButton implements ActionListener { public TabButton(String label_, Component c_, String keylabel_) { super(label_); _keylabel = keylabel_; _c = c_; addActionListener(this); } public String toString() { return "JTabbedPane.TabButton locaton=" + getLocation() + " label=\"" + getText() + "\" actionCommand=\"" + getActionCommand() + "\""; } public void actionPerformed(ActionEvent ev_) { setSelectedComponent(_c); } public String getKeyLabel() { return (_keylabel); } public void setKeyLabel(String keylabel_) { _keylabel = keylabel_; } public void requestFocus() { super.requestFocus(); Point origin = getLocationOnScreen(); Insets insets = super.getInsets(); Toolkit.getDefaultToolkit(). setCursor(origin.addOffset(2 + insets.left, 0 + insets.top)); } public void draw(Toolkit toolkit) { Point origin = getLocationOnScreen(); Insets insets = super.getInsets(); origin.translate(insets.left, insets.top); toolkit.setCursor(origin); int colorpair = getCursesColor(); toolkit.addChar(Toolkit.ACS_ULCORNER, 0, colorpair); toolkit.addChar(' ', 0, colorpair); toolkit.addString(getLabelString(), isEnabled() ? Toolkit.A_BOLD : 0, colorpair); toolkit.addChar(' ', 0, colorpair); toolkit.addChar(Toolkit.ACS_URCORNER, 0, colorpair); if (isEnabled()) { if (getMnemonic() > 0) { int mnemonicPos = getText().indexOf((char) getMnemonic()); if (mnemonicPos != -1) { toolkit.setCursor(origin.addOffset(2 + mnemonicPos, 0)); toolkit.addChar(getMnemonic(), Toolkit.A_UNDERLINE | Toolkit.A_REVERSE, colorpair); } } } toolkit.setCursor(origin.addOffset(0, 1)); if (isSelected()) { toolkit.addChar(Toolkit.ACS_LRCORNER, 0, colorpair); for (int j = 0; j < getText().length() + 2; j++) { toolkit.addChar(' ', 0, colorpair); } toolkit.addChar(Toolkit.ACS_LLCORNER, 0, colorpair); } else { toolkit.addChar(Toolkit.ACS_BTEE, 0, colorpair); toolkit.setCursor(origin.addOffset(getText().length() + 3, 1)); toolkit.addChar(Toolkit.ACS_BTEE, 0, colorpair); if (isEnabled()) { toolkit.setCursor(origin.addOffset(1, 1)); toolkit.addString(_keylabel, Toolkit.A_BOLD, colorpair); } } } public int getWidth() { Insets insets = super.getInsets(); return super.getText().length() + insets.left + insets.right + 4; } private String _keylabel; private Component _c; } }