/*
* Copyright 2013-2016 consulo.io
*
* 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 consulo.roots.ui;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.impl.StaticAnchoredButton;
import com.intellij.openapi.wm.impl.StripeButtonUI;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import consulo.annotations.RequiredDispatchThread;
import javax.swing.*;
import javax.swing.plaf.ButtonUI;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.List;
/**
* @author VISTALL
* @since 05.08.2015
*/
public class StripeTabPanel extends JPanel {
public static interface SelectListener extends EventListener {
@RequiredDispatchThread
void selected(@NotNull TabInfo tabInfo);
}
public static class TabInfo extends UserDataHolderBase {
private JComponent myComponent;
private JComponent myPreferredFocusableComponent;
private StaticAnchoredButton myButton;
public TabInfo(StaticAnchoredButton button, JComponent component, JComponent preferredFocusableComponent) {
myButton = button;
myComponent = component;
myPreferredFocusableComponent = preferredFocusableComponent;
}
@Nullable
public JComponent getPreferredFocusableComponent() {
return myPreferredFocusableComponent;
}
@NotNull
public String getTabName() {
return myButton.getText();
}
@NotNull
public JComponent getComponent() {
return myComponent;
}
public boolean isSelected() {
return myButton.isSelected();
}
@RequiredDispatchThread
public void select() {
myButton.setSelected(true);
}
public void setEnabled(boolean enabled) {
myButton.setEnabled(enabled);
}
}
private final JPanel myTabPanel;
private final JPanel myContentPanel;
private final ButtonGroup myButtonGroup = new ButtonGroup();
private final ItemListener myItemListener = new ItemListener() {
@Override
@RequiredDispatchThread
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
StaticAnchoredButton source = (StaticAnchoredButton)e.getSource();
TabInfo tabInfo = (TabInfo)source.getClientProperty(TabInfo.class);
CardLayout contentPanel = (CardLayout)myContentPanel.getLayout();
contentPanel.show(myContentPanel, tabInfo.getTabName());
mySelectListenerDispatcher.getMulticaster().selected(tabInfo);
JComponent preferredFocusableComponent = tabInfo.getPreferredFocusableComponent();
if(preferredFocusableComponent != null) {
IdeFocusManager.getGlobalInstance().doForceFocusWhenFocusSettlesDown(preferredFocusableComponent);
}
}
}
};
private final EventDispatcher<SelectListener> mySelectListenerDispatcher = EventDispatcher.create(SelectListener.class);
public StripeTabPanel() {
super(new BorderLayout());
myTabPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
myTabPanel.setBorder(new CustomLineBorder(0, 0, 0, JBUI.scale(1)));
add(myTabPanel, BorderLayout.WEST);
myContentPanel = new JPanel(new CardLayout());
add(myContentPanel, BorderLayout.CENTER);
}
public void addSelectListener(@NotNull SelectListener listener) {
mySelectListenerDispatcher.addListener(listener);
}
public void removeSelectListener(@NotNull SelectListener listener) {
mySelectListenerDispatcher.removeListener(listener);
}
@NotNull
@RequiredDispatchThread
public TabInfo addTab(@NotNull String tabName, @NotNull JComponent component) {
return addTab(tabName, component, component);
}
@NotNull
@RequiredDispatchThread
public TabInfo addTab(@NotNull String tabName, @NotNull JComponent component, @Nullable JComponent preferredFocusableComponent) {
StaticAnchoredButton button = new StaticAnchoredButton(tabName, ToolWindowAnchor.LEFT);
button.addItemListener(myItemListener);
button.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
button.setBackground(new Color(247, 243, 239));
button.setUI((ButtonUI)StripeButtonUI.createUI(button));
myTabPanel.add(button);
TabInfo tabInfo = new TabInfo(button, component, preferredFocusableComponent);
button.putClientProperty(TabInfo.class, tabInfo);
myButtonGroup.add(button);
myContentPanel.add(component, tabName);
if(myButtonGroup.getSelection() == null) {
tabInfo.select();
}
return tabInfo;
}
@Nullable
public TabInfo getSelectedTab() {
Enumeration<AbstractButton> elements = myButtonGroup.getElements();
while (elements.hasMoreElements()) {
AbstractButton button = elements.nextElement();
if (button.isSelected()) {
return (TabInfo)button.getClientProperty(TabInfo.class);
}
}
return null;
}
@NotNull
public List<TabInfo> getTabs() {
int buttonCount = myButtonGroup.getButtonCount();
List<TabInfo> list = new ArrayList<TabInfo>(buttonCount);
Enumeration<AbstractButton> elements = myButtonGroup.getElements();
while (elements.hasMoreElements()) {
AbstractButton button = elements.nextElement();
TabInfo tabInfo = (TabInfo)button.getClientProperty(TabInfo.class);
list.add(tabInfo);
}
return list;
}
}