1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.gui;
22
23import javax.swing.*;
24import java.awt.*;
25import java.awt.event.*;
26
27
28/**
29 * This <code>Jpanel</code> is similar to a <code>JTabbedPane</code>.
30 * It uses buttons on the left-hand side to switch between panels.
31 * An image can be added below these buttons.
32 * Some methods are provided to switch between tabs.
33 *
34 * @author Eric Lafortune
35 */
36public class TabbedPane
37     extends JPanel
38{
39    private final CardLayout  cardLayout  = new CardLayout();
40    private final JPanel      cardPanel   = new JPanel(cardLayout);
41    private final ButtonGroup buttonGroup = new ButtonGroup();
42
43
44    /**
45     * Creates a new TabbedPane.
46     */
47    public TabbedPane()
48    {
49        GridBagLayout layout = new GridBagLayout();
50        setLayout(layout);
51
52        GridBagConstraints cardConstraints = new GridBagConstraints();
53        cardConstraints.gridx      = 1;
54        cardConstraints.gridy      = 0;
55        cardConstraints.gridheight = GridBagConstraints.REMAINDER;
56        cardConstraints.fill       = GridBagConstraints.BOTH;
57        cardConstraints.weightx    = 1.0;
58        cardConstraints.weighty    = 1.0;
59        cardConstraints.anchor     = GridBagConstraints.NORTHWEST;
60
61        add(cardPanel, cardConstraints);
62    }
63
64
65    /**
66     * Adds a component with a given title to the tabbed pane.
67     *
68     * @param title     the title that will be used in the tab button.
69     * @param component the component that will be added as a tab.
70     */
71    public Component add(final String title, Component component)
72    {
73        GridBagConstraints buttonConstraints = new GridBagConstraints();
74        buttonConstraints.gridx  = 0;
75        buttonConstraints.fill   = GridBagConstraints.HORIZONTAL;
76        buttonConstraints.anchor = GridBagConstraints.NORTHWEST;
77        buttonConstraints.ipadx  = 10;
78        buttonConstraints.ipady  = 4;
79
80        JToggleButton button = new JToggleButton(title);
81
82        // Let the button react on the mouse press, instead of waiting for the
83        // mouse release.
84        button.setModel(new JToggleButton.ToggleButtonModel()
85        {
86            public void setPressed(boolean b)
87            {
88                if ((isPressed() == b) || !isEnabled())
89                {
90                    return;
91                }
92
93                if (!b && isArmed())
94                {
95                    setSelected(!this.isSelected());
96                }
97
98                if (b)
99                {
100                    stateMask |= PRESSED;
101                }
102                else
103                {
104                    stateMask &= ~PRESSED;
105                }
106
107                fireStateChanged();
108
109                if (isPressed())
110                {
111                    fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getActionCommand()));
112                }
113            }
114
115        });
116
117        // Switch to the tab on a button press.
118        button.addActionListener(new ActionListener()
119        {
120            public void actionPerformed(ActionEvent e)
121            {
122                cardLayout.show(cardPanel, title);
123            }
124        });
125
126        // Only one button can be selected at the same time.
127        buttonGroup.add(button);
128
129        // If this is the first tab, make sure its button is selected.
130        if (cardPanel.getComponentCount() == 0)
131        {
132            button.setSelected(true);
133        }
134
135        // Add the button and its panel.
136        add(button, buttonConstraints);
137        cardPanel.add(title, component);
138
139        return component;
140    }
141
142
143    /**
144     * Adds an image below the tab buttons, after all tabs have been added.
145     * The image will only be as visible as permitted by the available space.
146     *
147     * @param image the image.
148     * @return the component containing the image.
149     */
150    public Component addImage(final Image image)
151    {
152        GridBagConstraints imageConstraints = new GridBagConstraints();
153        imageConstraints.gridx   = 0;
154        imageConstraints.weighty = 1.0;
155        imageConstraints.fill    = GridBagConstraints.BOTH;
156        imageConstraints.anchor  = GridBagConstraints.SOUTHWEST;
157
158        JButton component = new JButton(new ImageIcon(image));
159        component.setFocusPainted(false);
160        component.setFocusable(false);
161        component.setRequestFocusEnabled(false);
162        component.setRolloverEnabled(false);
163        component.setMargin(new Insets(0, 0, 0, 0));
164        component.setHorizontalAlignment(JButton.LEFT);
165        component.setVerticalAlignment(JButton.BOTTOM);
166        component.setPreferredSize(new Dimension(0, 0));
167
168        add(component, imageConstraints);
169
170        return component;
171    }
172
173
174    /**
175     * Selects the first tab.
176     */
177    public void first()
178    {
179        cardLayout.first(cardPanel);
180        updateButtonSelection();
181    }
182
183
184    /**
185     * Selects the last tab.
186     */
187    public void last()
188    {
189        cardLayout.last(cardPanel);
190        updateButtonSelection();
191    }
192
193
194    /**
195     * Selects the previous tab.
196     */
197    public void previous()
198    {
199        cardLayout.previous(cardPanel);
200        updateButtonSelection();
201    }
202
203
204    /**
205     * Selects the next tab.
206     */
207    public void next()
208    {
209        cardLayout.next(cardPanel);
210        updateButtonSelection();
211    }
212
213
214    /**
215     * Lets the button selection reflect the currently visible panel.
216     */
217    private void updateButtonSelection()
218    {
219        int count = cardPanel.getComponentCount();
220        for (int index = 0 ; index < count ; index++) {
221            Component card = cardPanel.getComponent(index);
222            if (card.isShowing())
223            {
224                JToggleButton button = (JToggleButton)getComponent(index+1);
225                button.setSelected(true);
226            }
227        }
228    }
229}
230