| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * 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. |
| */ |
| package com.intellij.ui; |
| |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.KeyEvent; |
| import java.util.Collection; |
| |
| public class CollapsiblePanel extends JPanel { |
| private final JButton myToggleCollapseButton; |
| private final JComponent myContent; |
| private boolean myIsCollapsed; |
| private final Collection<CollapsingListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); |
| private boolean myIsInitialized = false; |
| private final Icon myExpandIcon; |
| private final Icon myCollapseIcon; |
| private Label myTitleLabel; |
| public static final KeyStroke LEFT_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); |
| public static final KeyStroke RIGHT_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); |
| @NonNls public static final String EXPAND = "expand"; |
| @NonNls public static final String COLLAPSE = "collapse"; |
| |
| public CollapsiblePanel(JComponent content, boolean collapseButtonAtLeft, |
| boolean isCollapsed, Icon collapseIcon, Icon expandIcon, |
| String title) { |
| super(new GridBagLayout()); |
| myContent = content; |
| setBackground(content.getBackground()); |
| myExpandIcon = expandIcon; |
| myCollapseIcon = collapseIcon; |
| final Dimension buttonDimension = getButtonDimension(); |
| myToggleCollapseButton = new JButton(); |
| myToggleCollapseButton.setOpaque(false); |
| myToggleCollapseButton.setBorderPainted(false); |
| myToggleCollapseButton.setBackground(content.getBackground()); |
| myToggleCollapseButton.setSize(buttonDimension); |
| myToggleCollapseButton.setPreferredSize(buttonDimension); |
| myToggleCollapseButton.setMinimumSize(buttonDimension); |
| myToggleCollapseButton.setMaximumSize(buttonDimension); |
| |
| myToggleCollapseButton.setFocusable(true); |
| |
| myToggleCollapseButton.getActionMap().put(COLLAPSE, new AbstractAction() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| collapse(); |
| } |
| }); |
| |
| myToggleCollapseButton.getActionMap().put(EXPAND, new AbstractAction() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| expand(); |
| } |
| }); |
| |
| myToggleCollapseButton.getInputMap().put(LEFT_KEY_STROKE, COLLAPSE); |
| myToggleCollapseButton.getInputMap().put(RIGHT_KEY_STROKE, EXPAND); |
| |
| |
| final int iconAnchor = collapseButtonAtLeft ? GridBagConstraints.WEST : GridBagConstraints.EAST; |
| add(myToggleCollapseButton, |
| new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, |
| iconAnchor, |
| GridBagConstraints.NONE, |
| new Insets(-5, collapseButtonAtLeft ? 0 : -5, 0, collapseButtonAtLeft ? -5 : 0), 0, |
| 0)); |
| if (title != null) { |
| myTitleLabel = new Label(title); |
| myTitleLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)); |
| myTitleLabel.setBackground(content.getBackground()); |
| add(myTitleLabel, |
| new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, |
| GridBagConstraints.CENTER, |
| GridBagConstraints.NONE, |
| new Insets(-5, -3, 0, -3), 0, |
| 0)); |
| |
| } |
| |
| myToggleCollapseButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| setCollapsed(!myIsCollapsed); |
| } |
| }); |
| setCollapsed(isCollapsed); |
| |
| } |
| |
| private Dimension getButtonDimension() { |
| if (myExpandIcon == null) { |
| return new Dimension(7, 7); |
| } |
| else { |
| return new Dimension(myExpandIcon.getIconWidth(), myExpandIcon.getIconHeight()); |
| } |
| } |
| |
| public CollapsiblePanel(JComponent content, boolean collapseButtonAtLeft) { |
| this(content, collapseButtonAtLeft, false, null, null, null); |
| } |
| |
| protected void setCollapsed(boolean collapse) { |
| try { |
| if (collapse) { |
| if (myIsInitialized) remove(myContent); |
| } |
| else { |
| add(myContent, |
| new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, |
| new Insets(0, 0, 0, 0), 0, 0)); |
| } |
| myIsCollapsed = collapse; |
| |
| Icon icon = getIcon(); |
| if (icon != null){ |
| myToggleCollapseButton.setIcon(icon); |
| myToggleCollapseButton.setBorder(null); |
| myToggleCollapseButton.setBorderPainted(false); |
| myToggleCollapseButton.setToolTipText(getToggleButtonToolTipText()); |
| } |
| |
| if (collapse) { |
| setFocused(true); |
| setSelected(true); |
| } else { |
| myContent.requestFocusInWindow(); |
| } |
| |
| notifyListners(); |
| |
| revalidate(); |
| repaint(); |
| } |
| finally { |
| myIsInitialized = true; |
| } |
| } |
| |
| private String getToggleButtonToolTipText() { |
| if (myIsCollapsed) { |
| return UIBundle.message("collapsible.panel.collapsed.state.tooltip.text"); |
| } |
| else { |
| return UIBundle.message("collapsible.panel.expanded.state.tooltip.text"); |
| } |
| } |
| |
| private Icon getIcon() { |
| if (myIsCollapsed) { |
| return myExpandIcon; |
| } |
| else { |
| return myCollapseIcon; |
| } |
| } |
| |
| private void notifyListners() { |
| for (CollapsingListener listener : myListeners) { |
| listener.onCollapsingChanged(this, isCollapsed()); |
| } |
| } |
| |
| public void addCollapsingListener(CollapsingListener listener) { |
| myListeners.add(listener); |
| } |
| |
| public void removeCollapsingListener(CollapsingListener listener) { |
| myListeners.remove(listener); |
| } |
| |
| public boolean isCollapsed() { |
| return myIsCollapsed; |
| } |
| |
| public void expand() { |
| if (myIsCollapsed) { |
| setCollapsed(false); |
| } |
| } |
| |
| public void collapse() { |
| if (!myIsCollapsed) { |
| setCollapsed(true); |
| } |
| } |
| |
| public void setFocused(boolean focused) { |
| myToggleCollapseButton.requestFocusInWindow(); |
| } |
| |
| public void setSelected(boolean selected) { |
| myToggleCollapseButton.setSelected(selected); |
| } |
| |
| public ActionMap getCollapsibleActionMap(){ |
| return myToggleCollapseButton.getActionMap(); |
| } |
| |
| public InputMap getCollapsibleInputMap(){ |
| return myToggleCollapseButton.getInputMap(); |
| } |
| |
| @Override |
| protected void paintComponent(Graphics g) { |
| updatePanel(); |
| super.paintComponent(g); |
| } |
| |
| private void updatePanel() { |
| if (paintAsSelected()) { |
| setBackground(UIUtil.getTableSelectionBackground()); |
| } else { |
| setBackground(myContent.getBackground()); |
| } |
| } |
| |
| @Override |
| protected void paintChildren(Graphics g) { |
| if (myTitleLabel != null) { |
| updateTitle(); |
| } |
| |
| |
| updateToggleButton(); |
| |
| super.paintChildren(g); |
| } |
| |
| private void updateToggleButton() { |
| if (paintAsSelected()) { |
| myToggleCollapseButton.setBackground(UIUtil.getTableSelectionBackground()); |
| } else { |
| myToggleCollapseButton.setBackground(myContent.getBackground()); |
| } |
| } |
| |
| private void updateTitle() { |
| if (paintAsSelected()) { |
| myTitleLabel.setForeground(UIUtil.getTableSelectionForeground()); |
| myTitleLabel.setBackground(UIUtil.getTableSelectionBackground()); |
| } else { |
| myTitleLabel.setForeground(UIUtil.getLabelForeground()); |
| myTitleLabel.setBackground(myContent.getBackground()); |
| } |
| } |
| |
| private boolean paintAsSelected() { |
| return myToggleCollapseButton.hasFocus() && isCollapsed(); |
| } |
| |
| } |