/* * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of Substance Kirill Grouchnikov nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package test.check; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ContainerAdapter; import java.awt.event.ContainerEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; import org.pushingpixels.lafwidget.LafWidgetUtilities2; import org.pushingpixels.lafwidget.utils.LafConstants.TabOverviewKind; import org.pushingpixels.substance.api.SubstanceConstants.TabContentPaneBorderKind; import org.pushingpixels.substance.api.SubstanceLookAndFeel; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * Control panel for the tabbed panes. * * @author Kirill Grouchnikov */ public class TabControlPanel extends JPanel { /** * Tabbed pane. */ private JTabbedPane jtp; /** * Contains the closed components. */ public LinkedList<Component> closed; /** * Model for the combobox that contains the list of all tabs. * * @author Kirill Grouchnikov */ private static class TabComboBoxModel extends DefaultComboBoxModel { /** * Tabbed pane. */ private JTabbedPane jtp; /** * Creates the combobox model. * * @param jtp * Tabbed pane. */ public TabComboBoxModel(JTabbedPane jtp) { this.jtp = jtp; } /* * (non-Javadoc) * * @see javax.swing.DefaultComboBoxModel#getSize() */ @Override public int getSize() { return this.jtp.getTabCount(); } /* * (non-Javadoc) * * @see javax.swing.DefaultComboBoxModel#getElementAt(int) */ @Override public Object getElementAt(int index) { return index; } /* * (non-Javadoc) * * @see javax.swing.DefaultComboBoxModel#getIndexOf(java.lang.Object) */ @Override public int getIndexOf(Object anObject) { return (Integer) anObject; } /** * Fires the event that the combo contents has been changed. */ public void changed() { this.fireContentsChanged(this, 0, this.getSize() - 1); } } /** * Cell renderer for the combobox that lists the tabs. * * @author Kirill Grouchnikov */ private class TabCellRenderer extends JLabel implements ListCellRenderer { /* * (non-Javadoc) * * @see * javax.swing.ListCellRenderer#getListCellRendererComponent(javax.swing * .JList, java.lang.Object, int, boolean, boolean) */ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value == null) { this.setText(""); this.setIcon(null); } else { this.setText(jtp.getTitleAt((Integer) value)); this.setIcon(jtp.getIconAt((Integer) value)); } return this; } } /** * Returns the contents of the control panel. * * @param jtp * Tabbed pane. * @param mainTabPreviewPainter * Tab preview painter. * @return Control panel contents. */ private JPanel getContents(final JTabbedPane jtp, final MyTabPreviewPainter mainTabPreviewPainter) { FormLayout lm = new FormLayout( "right:pref, 4dlu, fill:min:grow(1), 2dlu, fill:min:grow(1)", "p, 2dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 7dlu, " + "p, 2dlu, p, 0dlu, p, 0dlu, p, 0dlu, p, 7dlu," + "p, 2dlu, p, 3dlu, p, 0dlu, p, 3dlu, p, 3dlu, p, 7dlu, " + "p, 2dlu, p, 0dlu, p, 0dlu, p, 0dlu, p, 7dlu, " + "p, 2dlu, p, 3dlu, p"); lm.setColumnGroups(new int[][] { { 3, 5 } }); PanelBuilder builder = new PanelBuilder(lm); // builder.setDefaultDialogBorder(); CellConstraints cc = new CellConstraints(); int row = 1; builder.addSeparator("General", cc.xyw(1, row, 5)); final JComboBox addKindCombo = new JComboBox(new Object[] { "regular", "null", "modified" }); JButton addNewTabButton = new JButton("Add"); addNewTabButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String selectedKind = (String) addKindCombo.getSelectedItem(); if ("null".equals(selectedKind)) { SwingUtilities.invokeLater(new Runnable() { public void run() { jtp.addTab("null tab", null); } }); return; } final int count = 1 + jtp.getTabCount(); final JComponent tabComp = new NumberedPanel(count); if ("modified".equals(selectedKind)) { tabComp.putClientProperty( SubstanceLookAndFeel.WINDOW_MODIFIED, Boolean.TRUE); } SwingUtilities.invokeLater(new Runnable() { public void run() { jtp.addTab("tab" + count, tabComp); } }); } }); row += 2; builder.addLabel("Add tab", cc.xy(1, row)); builder.add(addKindCombo, cc.xy(3, row)); builder.add(addNewTabButton, cc.xy(5, row)); final JComboBox placementCombo = new JComboBox(new Object[] { "top", "bottom", "left", "right" }); placementCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String selected = (String) placementCombo.getSelectedItem(); if ("top".equals(selected)) jtp.setTabPlacement(JTabbedPane.TOP); if ("bottom".equals(selected)) jtp.setTabPlacement(JTabbedPane.BOTTOM); if ("left".equals(selected)) jtp.setTabPlacement(JTabbedPane.LEFT); if ("right".equals(selected)) jtp.setTabPlacement(JTabbedPane.RIGHT); } }); row += 2; builder.addLabel("Placement", cc.xy(1, row)); builder.add(placementCombo, cc.xyw(3, row, 3)); try { final JComboBox overviewKindCombo = new FlexiComboBox<TabOverviewKind>( TabOverviewKind.GRID, TabOverviewKind.MENU_CAROUSEL, TabOverviewKind.ROUND_CAROUSEL) { @Override public String getCaption(TabOverviewKind item) { return item.getName(); } }; overviewKindCombo.setSelectedItem(LafWidgetUtilities2 .getTabPreviewPainter(jtp).getOverviewKind(jtp)); overviewKindCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { mainTabPreviewPainter .setTabOverviewKind((TabOverviewKind) overviewKindCombo .getSelectedItem()); } }); row += 2; builder.addLabel("Overview kind", cc.xy(1, row)); builder.add(overviewKindCombo, cc.xyw(3, row, 3)); } catch (NoClassDefFoundError ncdfe) { } final JCheckBox useScrollLayout = new JCheckBox("Uses scroll layout"); useScrollLayout.setSelected(false); useScrollLayout.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jtp .setTabLayoutPolicy(useScrollLayout.isSelected() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT); } }); row += 2; builder.addLabel("Layout", cc.xy(1, row)); builder.add(useScrollLayout, cc.xyw(3, row, 3)); final JComboBox contentBorderCombo = new JComboBox(new Object[] { TabContentPaneBorderKind.DOUBLE_FULL, TabContentPaneBorderKind.SINGLE_FULL, TabContentPaneBorderKind.DOUBLE_PLACEMENT, TabContentPaneBorderKind.SINGLE_PLACEMENT }); contentBorderCombo .setSelectedItem(TabContentPaneBorderKind.DOUBLE_FULL); contentBorderCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { TabContentPaneBorderKind contentBorderKind = (TabContentPaneBorderKind) contentBorderCombo .getSelectedItem(); jtp.putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, contentBorderKind); jtp.updateUI(); jtp.repaint(); } }); row += 2; builder.addLabel("Content border", cc.xy(1, row)); builder.add(contentBorderCombo, cc.xyw(3, row, 3)); JButton enableAll = new JButton("+ all"); enableAll.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (int i = 0; i < jtp.getTabCount(); i++) { jtp.setEnabledAt(i, true); } } }); JButton disableAll = new JButton("- all"); disableAll.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (int i = 0; i < jtp.getTabCount(); i++) { jtp.setEnabledAt(i, false); } } }); row += 2; builder.addLabel("Enable all", cc.xy(1, row)); builder.add(enableAll, cc.xy(3, row)); builder.add(disableAll, cc.xy(5, row)); JButton closeAllEnabled = new JButton("Close"); closeAllEnabled.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Set<Component> toRemove = new HashSet<Component>(); for (int i = 0; i < jtp.getTabCount(); i++) { if (jtp.isEnabledAt(i)) toRemove.add(jtp.getComponentAt(i)); } for (Component comp : toRemove) jtp.remove(comp); } }); JButton restoreClosed = new JButton("Restore"); restoreClosed.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (Component tnp : closed) { jtp.addTab("restored", tnp); } } }); row += 2; builder.addLabel("Close all", cc.xy(1, row)); builder.add(closeAllEnabled, cc.xy(3, row)); builder.add(restoreClosed, cc.xy(5, row)); row += 2; builder.addSeparator("Single Tab", cc.xyw(1, row, 5)); final JComboBox tabSelectorCombo = new JComboBox(new TabComboBoxModel( this.jtp)); tabSelectorCombo.setRenderer(new TabCellRenderer()); jtp.addContainerListener(new ContainerAdapter() { @Override public void componentAdded(ContainerEvent e) { ((TabComboBoxModel) tabSelectorCombo.getModel()).changed(); } @Override public void componentRemoved(ContainerEvent e) { ((TabComboBoxModel) tabSelectorCombo.getModel()).changed(); } }); row += 2; builder.addLabel("Select", cc.xy(1, row)); builder.add(tabSelectorCombo, cc.xyw(3, row, 3)); final JCheckBox markAsModified = new JCheckBox("Marked modified"); markAsModified.setSelected(false); markAsModified.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (tabSelectorCombo.getSelectedItem() == null) return; Component comp = jtp.getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((comp != null) && (comp instanceof JComponent)) { JComponent jc = (JComponent) comp; jc .putClientProperty( SubstanceLookAndFeel.WINDOW_MODIFIED, (markAsModified.isSelected() ? Boolean.TRUE : false)); } } }); tabSelectorCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Component selComp = jtp .getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((selComp != null) && (selComp instanceof JComponent)) { JComponent selected = (JComponent) selComp; markAsModified .setSelected(Boolean.TRUE .equals(selected .getClientProperty(SubstanceLookAndFeel.WINDOW_MODIFIED))); } } }); row += 2; builder.addLabel("Modified", cc.xy(1, row)); builder.add(markAsModified, cc.xyw(3, row, 3)); final JCheckBox isModifiedAnimOnClose = new JCheckBox("Animation on X"); isModifiedAnimOnClose.setSelected(false); isModifiedAnimOnClose.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (tabSelectorCombo.getSelectedItem() == null) return; Component comp = jtp.getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((comp != null) && (comp instanceof JComponent)) { JComponent jc = (JComponent) comp; jc .putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION, (isModifiedAnimOnClose.isSelected() ? Boolean.TRUE : null)); } } }); tabSelectorCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Component selComp = jtp .getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((selComp != null) && (selComp instanceof JComponent)) { JComponent selected = (JComponent) selComp; isModifiedAnimOnClose .setSelected(Boolean.TRUE .equals(selected .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_MODIFIED_ANIMATION))); } } }); row += 2; builder.add(isModifiedAnimOnClose, cc.xyw(3, row, 3)); final JCheckBox hasCloseButton = new JCheckBox("No close button"); hasCloseButton.setSelected(false); hasCloseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (tabSelectorCombo.getSelectedItem() == null) return; Component comp = jtp.getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((comp != null) && (comp instanceof JComponent)) { JComponent jc = (JComponent) comp; jc .putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, (hasCloseButton.isSelected() ? Boolean.FALSE : null)); jtp.repaint(); } } }); tabSelectorCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Component selComp = jtp .getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); if ((selComp != null) && (selComp instanceof JComponent)) { JComponent selected = (JComponent) selComp; hasCloseButton .setSelected(Boolean.FALSE .equals(selected .getClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY))); } } }); JButton closeButton = new JButton("Close"); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (tabSelectorCombo.getSelectedItem() == null) return; Component comp = jtp .getComponentAt((Integer) tabSelectorCombo .getSelectedItem()); jtp.removeTabAt((Integer) tabSelectorCombo .getSelectedItem()); closed.add(comp); jtp.repaint(); } }); } }); JButton selectButton = new JButton("Select"); selectButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (tabSelectorCombo.getSelectedItem() == null) return; jtp.setSelectedIndex((Integer) tabSelectorCombo .getSelectedItem()); } }); } }); row += 2; builder.addLabel("Tab op", cc.xy(1, row)); builder.add(closeButton, cc.xy(3, row)); builder.add(selectButton, cc.xy(5, row)); row += 2; builder.addSeparator("Close Button Single", cc.xyw(1, row, 5)); row += 2; builder.addLabel("Visible", cc.xy(1, row)); builder.add(hasCloseButton, cc.xyw(3, row, 3)); return builder.getPanel(); } /** * Creates the tab control panel. * * @param jtp * Tabbed pane. * @param previewPainter * Preview painter. */ public TabControlPanel(JTabbedPane jtp, MyTabPreviewPainter previewPainter) { super(); this.jtp = jtp; this.closed = new LinkedList<Component>(); this.setLayout(new BorderLayout()); JPanel contents = getContents(jtp, previewPainter); contents.setOpaque(false); contents.putClientProperty( SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE); this.add(contents, BorderLayout.CENTER); } // @Override // public Dimension getPreferredSize() { // Dimension result = super.getPreferredSize(); // return new Dimension(190, result.height); // } // // private class TabControlPanelLayout implements LayoutManager { // public void addLayoutComponent(String name, Component comp) { // } // // public void removeLayoutComponent(Component comp) { // } // // public void layoutContainer(Container parent) { // Insets pIns = paneControls.getInsets(); // Insets tIns = tabControls.getInsets(); // int width = Math.max(paneControls.getPreferredSize().width // + pIns.left + pIns.right, // tabControls.getPreferredSize().width + tIns.left // + tIns.right); // width = Math.min(parent.getWidth(), width); // // int h = paneControls.getPreferredSize().height + pIns.top // + pIns.bottom; // paneControls.setBounds(0, 0, width, h); // // tabControls.setBounds(0, h, width, // tabControls.getPreferredSize().height + tIns.top // + tIns.bottom); // } // // public Dimension minimumLayoutSize(Container parent) { // int w = Math.max(tabControls.getMinimumSize().width, paneControls // .getMinimumSize().width); // Insets tIns = tabControls.getInsets(); // Insets pIns = paneControls.getInsets(); // int h = tabControls.getMinimumSize().height // + paneControls.getMinimumSize().height + tIns.top // + tIns.bottom + pIns.top + pIns.bottom; // return new Dimension(w, h); // } // // public Dimension preferredLayoutSize(Container parent) { // int w = Math.max(tabControls.getPreferredSize().width, paneControls // .getPreferredSize().width); // Insets tIns = tabControls.getInsets(); // Insets pIns = paneControls.getInsets(); // int h = tabControls.getPreferredSize().height // + paneControls.getPreferredSize().height + tIns.top // + tIns.bottom + pIns.top + pIns.bottom; // return new Dimension(w, h); // } // } // // private void addSeparator(JPanel panel, String text) { // JLabel l = new JLabel(text, SwingConstants.LEADING); // l.setFont(l.getFont().deriveFont(Font.BOLD)); // // panel.add(l, "gapbottom 1,gaptop para, span, split 2"); // panel.add(new JSeparator(), "gapleft rel, gaptop para, growx"); // } }