package tk.amberide.ide.swing.tabs; import tk.amberide.ide.swing.MenuBuilder; import tk.amberide.ide.swing.UIUtil; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import javax.swing.plaf.basic.BasicButtonUI; /** * @author Tudor */ public class CloseableTabbedPane extends JTabbedPane { private HashMap<Integer, String> titles = new HashMap<Integer, String>(); private List<TabCloseListener> closers = new ArrayList<TabCloseListener>(); public CloseableTabbedPane() { super(); addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { final int index = getUI().tabForCoordinate(CloseableTabbedPane.this, e.getX(), e.getY()); if (index == -1) return; if (SwingUtilities.isMiddleMouseButton(e)) { if (getTabComponentAt(index) instanceof CloseableTabComponent) ((CloseableTabComponent) getTabComponentAt(index)).getCloseButton().doClick(); } else if (SwingUtilities.isRightMouseButton(e)) { e.consume(); new MenuBuilder("").addButton("Switch", new AbstractAction() { @Override public void actionPerformed(ActionEvent actionEvent) { if (getSelectedIndex() != index) setSelectedIndex(index); getSelectedComponent().requestFocusInWindow(); } }).addSeparator().addButton("Close", new AbstractAction() { @Override public void actionPerformed(ActionEvent actionEvent) { if (getTabComponentAt(index) instanceof CloseableTabComponent) ((CloseableTabComponent) getTabComponentAt(index)).getCloseButton().doClick(); } }).create().getPopupMenu().show(CloseableTabbedPane.this, e.getX(), e.getY()); } } @Override public void mousePressed(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) e.consume(); } @Override public void mouseReleased(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) e.consume(); } }); UIUtil.mapInput(this, JComponent.WHEN_IN_FOCUSED_WINDOW, KeyEvent.VK_W, InputEvent.CTRL_MASK, new AbstractAction() { @Override public void actionPerformed(ActionEvent actionEvent) { Component component = getTabComponentAt(getSelectedIndex()); if (component instanceof CloseableTabComponent) ((CloseableTabComponent) component).getCloseButton().doClick(); } }); } public void addTabCloseListener(TabCloseListener listener) { closers.add(listener); } public void removeTabCloseListener(TabCloseListener listener) { closers.remove(listener); } @Override public String getTitleAt(int index) { return titles.get(index); } @Override public void setTitleAt(int index, String name) { titles.put(index, name); } @Override public void remove(Component comp) { super.remove(comp); System.out.println("Removing " + comp); int index = this.indexOfComponent(comp); if (index != -1) { this.removeTabAt(index); } } public static class CloseableTabComponent extends JPanel { private JButton closeButton; private JLabel titleLabel; public CloseableTabComponent(String title) { super(new GridBagLayout()); closeButton = new JButton("") { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); if (getModel().isPressed()) { g2.translate(1, 1); } g2.setStroke(new Stroke() { BasicStroke stroke1 = new BasicStroke(1), stroke2 = new BasicStroke(1); public Shape createStrokedShape(Shape s) { return stroke2.createStrokedShape(stroke1.createStrokedShape(s)); } }); g2.setColor(getModel().isRollover() ? Color.RED : new Color(0x090909)); int delta = 5; g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); g2.dispose(); } }; closeButton.setPreferredSize(new Dimension(17, 17)); //Make the button looks the same for all Laf's closeButton.setUI(new BasicButtonUI()); //Make it transparent closeButton.setContentAreaFilled(false); //No need to be focusable closeButton.setFocusable(false); closeButton.setBorder(BorderFactory.createEtchedBorder()); closeButton.setBorderPainted(false); setOpaque(false); titleLabel = new JLabel(title); add(titleLabel); add(closeButton); setFocusable(false); } public JButton getCloseButton() { return closeButton; } public JLabel getTitleLabel() { return titleLabel; } } @Override public void insertTab(final String title, Icon icon, final Component c, String tip, int index) { System.out.println("Inserting tab " + title); super.insertTab(title, icon, c, tip, index == -1 ? getTabCount() : index); getComponentAt(index); titles.put(index, title); CloseableTabComponent comp = new CloseableTabComponent(title); setTabComponentAt(index, comp); comp.getCloseButton().addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { for (TabCloseListener listener : closers) { if (!listener.tabClosed(title, c, CloseableTabbedPane.this)) return; } remove(c); } }); } }