001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.gui;
022:
023: import javax.swing.*;
024: import java.awt.*;
025: import java.awt.event.*;
026:
027: /**
028: * This <code>Jpanel</code> is similar to a <code>JTabbedPane</code>.
029: * It uses buttons on the left-hand side to switch between panels.
030: * An image can be added below these buttons.
031: * Some methods are provided to switch between tabs.
032: *
033: * @author Eric Lafortune
034: */
035: public class TabbedPane extends JPanel {
036: private final CardLayout cardLayout = new CardLayout();
037: private final JPanel cardPanel = new JPanel(cardLayout);
038: private final ButtonGroup buttonGroup = new ButtonGroup();
039:
040: /**
041: * Creates a new TabbedPane.
042: */
043: public TabbedPane() {
044: GridBagLayout layout = new GridBagLayout();
045: setLayout(layout);
046:
047: GridBagConstraints cardConstraints = new GridBagConstraints();
048: cardConstraints.gridx = 1;
049: cardConstraints.gridy = 0;
050: cardConstraints.gridheight = GridBagConstraints.REMAINDER;
051: cardConstraints.fill = GridBagConstraints.BOTH;
052: cardConstraints.weightx = 1.0;
053: cardConstraints.weighty = 1.0;
054: cardConstraints.anchor = GridBagConstraints.NORTHWEST;
055:
056: add(cardPanel, cardConstraints);
057: }
058:
059: /**
060: * Adds a component with a given title to the tabbed pane.
061: *
062: * @param title the title that will be used in the tab button.
063: * @param component the component that will be added as a tab.
064: */
065: public Component add(final String title, Component component) {
066: GridBagConstraints buttonConstraints = new GridBagConstraints();
067: buttonConstraints.gridx = 0;
068: buttonConstraints.fill = GridBagConstraints.HORIZONTAL;
069: buttonConstraints.anchor = GridBagConstraints.NORTHWEST;
070: buttonConstraints.ipadx = 10;
071: buttonConstraints.ipady = 4;
072:
073: JToggleButton button = new JToggleButton(title);
074:
075: // Let the button react on the mouse press, instead of waiting for the
076: // mouse release.
077: button.setModel(new JToggleButton.ToggleButtonModel() {
078: public void setPressed(boolean b) {
079: if ((isPressed() == b) || !isEnabled()) {
080: return;
081: }
082:
083: if (!b && isArmed()) {
084: setSelected(!this .isSelected());
085: }
086:
087: if (b) {
088: stateMask |= PRESSED;
089: } else {
090: stateMask &= ~PRESSED;
091: }
092:
093: fireStateChanged();
094:
095: if (isPressed()) {
096: fireActionPerformed(new ActionEvent(this ,
097: ActionEvent.ACTION_PERFORMED,
098: getActionCommand()));
099: }
100: }
101:
102: });
103:
104: // Switch to the tab on a button press.
105: button.addActionListener(new ActionListener() {
106: public void actionPerformed(ActionEvent e) {
107: cardLayout.show(cardPanel, title);
108: }
109: });
110:
111: // Only one button can be selected at the same time.
112: buttonGroup.add(button);
113:
114: // If this is the first tab, make sure its button is selected.
115: if (cardPanel.getComponentCount() == 0) {
116: button.setSelected(true);
117: }
118:
119: // Add the button and its panel.
120: add(button, buttonConstraints);
121: cardPanel.add(title, component);
122:
123: return component;
124: }
125:
126: /**
127: * Adds an image below the tab buttons, after all tabs have been added.
128: * The image will only be as visible as permitted by the available space.
129: *
130: * @param image the image.
131: * @return the component containing the image.
132: */
133: public Component addImage(final Image image) {
134: GridBagConstraints imageConstraints = new GridBagConstraints();
135: imageConstraints.gridx = 0;
136: imageConstraints.weighty = 1.0;
137: imageConstraints.fill = GridBagConstraints.BOTH;
138: imageConstraints.anchor = GridBagConstraints.SOUTHWEST;
139:
140: JPanel component = new JPanel() {
141: public void paintComponent(Graphics graphics) {
142: graphics.drawImage(image, 0, getHeight()
143: - image.getHeight(null), this );
144: }
145: };
146: component.setBorder(BorderFactory.createEtchedBorder());
147:
148: add(component, imageConstraints);
149:
150: return component;
151: }
152:
153: /**
154: * Selects the first tab.
155: */
156: public void first() {
157: cardLayout.first(cardPanel);
158: updateButtonSelection();
159: }
160:
161: /**
162: * Selects the last tab.
163: */
164: public void last() {
165: cardLayout.last(cardPanel);
166: updateButtonSelection();
167: }
168:
169: /**
170: * Selects the previous tab.
171: */
172: public void previous() {
173: cardLayout.previous(cardPanel);
174: updateButtonSelection();
175: }
176:
177: /**
178: * Selects the next tab.
179: */
180: public void next() {
181: cardLayout.next(cardPanel);
182: updateButtonSelection();
183: }
184:
185: /**
186: * Lets the button selection reflect the currently visible panel.
187: */
188: private void updateButtonSelection() {
189: int count = cardPanel.getComponentCount();
190: for (int index = 0; index < count; index++) {
191: Component card = cardPanel.getComponent(index);
192: if (card.isShowing()) {
193: JToggleButton button = (JToggleButton) getComponent(index + 1);
194: button.setSelected(true);
195: }
196: }
197: }
198: }
|