import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MyTabbedPane extends JTabbedPane implements MouseListener, ActionListener {

  private JPopupMenu popup;
  private JMenuItem  menu1, menu2, close;
  private int        currentTab = -1;

  private ImageIcon closeIcon = ...;

  public MyTabbedPane () { this(JTabbedPane.TOP); }
  public MyTabbedPane (int tabPlacement) {
    super(tabPlacement);

    addMouseListener(this); // to enable tab removal and popup menu on mouse-click

    insertClosableTab("jodel1", new JLabel("Jodel1"), null, 0);
    insertClosableTab("jodel2", new JLabel("Jodel2"), null, 1);
  }

  public void insertClosableTab (String title, Component component, String tip, int index) {
    insertTab(title, closeIcon, component, tip, index); // unfortunately we do not have any control about the icon placement (or do we?)
  }

  public void mouseEntered (MouseEvent e) {}
  public void mouseExited (MouseEvent e) {}
  public void mouseClicked (MouseEvent e) {}
  public void mousePressed (MouseEvent e) {}

  public void mouseReleased (MouseEvent e) {
    currentTab = indexAtLocation(e.getX(), e.getY());
    if (currentTab < 0 || currentTab >= getTabCount() || !isEnabledAt(currentTab)) return; // tab is disabled or click occured outside of a tab area

    Icon icon = getIconAt(currentTab);
    boolean insideCloseIcon = closeIcon.equals(icon) && insideIcon(e.getX(), e.getY(), icon, currentTab);

    if (SwingUtilities.isRightMouseButton(e)) { // show popup menu on right-click
      if (popup == null) { // lazily instantiate popup menu
        popup = new JPopupMenu();
        menu1 = (JMenuItem) popup.add("menu1"); menu1.addActionListener(this);
        menu2 = (JMenuItem) popup.add("menu2"); menu2.addActionListener(this);
        close = (JMenuItem) popup.add("close"); close.addActionListener(this);
      }
      // bias menus:
      menu1.setEnabled(!insideCloseIcon);
      menu2.setEnabled(!insideCloseIcon);
      close.setEnabled(insideCloseIcon);

      popup.show(this, e.getX(), e.getY()); // how popup

    } else if (SwingUtilities.isLeftMouseButton(e) && insideCloseIcon) { // close tab if closeIcon was left-clicked
      removeCurrentTabWithDialog();
    }
  }

  // ActionListener impl - responds to clicks on popup menu
  public void actionPerformed (ActionEvent e) {
    Object src = e.getSource();
    if (src == menu1) {
      // do menu1 business
    } else if (src == menu2) {
      // do menu2 business
    } else if (src == close) {
      removeCurrentTabWithDialog();
    }
  }

  private void removeCurrentTabWithDialog () {
    if (currentTab < 0 || currentTab >= getTabCount() || !isEnabledAt(currentTab)) return; // tab is disabled or click occured outside of a tab area
    int result = JOptionPane.showConfirmDialog(this, "You are about to close '" + getTitleAt(currentTab) + "'! Are you certain?");
    if (result == JOptionPane.YES_OPTION) remove(getComponentAt(currentTab));
    currentTab = -1;
  }

  // return whether a mouse click (x,y) occured with the area of an icon (assumes that icon is placed left)
  private boolean insideIcon (int x, int y, Icon icon, int tab) {
    if (icon == null) return false;
    Insets insets = getInsets();
    Rectangle r = getBoundsAt(tab);
    if (x < r.x + insets.left || x > r.x + insets.left + closeIcon.getIconWidth())  return false;
    if (y < r.y + insets.top  || y > r.y + insets.top  + closeIcon.getIconHeight()) return false;
    return true;
  }
}
