diff --git a/src/dev/kske/chess/ui/GameTabComponent.java b/src/dev/kske/chess/ui/GameTabComponent.java
new file mode 100644
index 0000000..ff492b4
--- /dev/null
+++ b/src/dev/kske/chess/ui/GameTabComponent.java
@@ -0,0 +1,99 @@
+package dev.kske.chess.ui;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.plaf.basic.BasicButtonUI;
+
+/**
+ * Project: Chess
+ * File: GameTabComponent.java
+ * Created: 11 Dec 2019
+ *
+ * @author Kai S. K. Engelbart
+ */
+public class GameTabComponent extends JPanel {
+
+ private final JTabbedPane tabbedPane;
+
+ private static final long serialVersionUID = 9022979950018125935L;
+
+ public GameTabComponent(JTabbedPane tabbedPane) {
+ super(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ if (tabbedPane == null) throw new NullPointerException("TabbedPane is null");
+ this.tabbedPane = tabbedPane;
+
+ // Create title JLabel
+ JLabel label = new JLabel() {
+
+ private static final long serialVersionUID = 7902391411509551586L;
+
+ @Override
+ public String getText() {
+ int i = tabbedPane.indexOfTabComponent(GameTabComponent.this);
+ return i != -1 ? tabbedPane.getTitleAt(i) : "";
+ }
+ };
+ label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
+ add(label);
+
+ // Create close JButton
+ add(new TabButton());
+ setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
+ }
+
+ private class TabButton extends JButton {
+
+ private static final long serialVersionUID = -2757857832337636731L;
+
+ public TabButton() {
+ final int size = 17;
+ setPreferredSize(new Dimension(size, size));
+ setToolTipText("Close this tab");
+ setUI(new BasicButtonUI());
+ setContentAreaFilled(false);
+ setFocusable(false);
+ setBorder(BorderFactory.createEtchedBorder());
+ setBorderPainted(false);
+ addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseEntered(MouseEvent evt) { setBorderPainted(true); }
+
+ @Override
+ public void mouseExited(MouseEvent evt) { setBorderPainted(false); }
+ });
+ setRolloverEnabled(true);
+ addActionListener((evt) -> { int i = tabbedPane.indexOfTabComponent(GameTabComponent.this); if (i != -1) tabbedPane.remove(i); });
+ }
+
+ @Override
+ public void updateUI() {}
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2 = (Graphics2D) g.create();
+ // shift the image for pressed buttons
+ if (getModel().isPressed()) { g2.translate(1, 1); }
+ g2.setStroke(new BasicStroke(2));
+ g2.setColor(Color.BLACK);
+ if (getModel().isRollover()) { g2.setColor(Color.MAGENTA); }
+ final int delta = 6;
+ g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
+ g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
+ g2.dispose();
+ }
+ }
+}
diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java
index 3dc54b5..22ccbc3 100644
--- a/src/dev/kske/chess/ui/MainWindow.java
+++ b/src/dev/kske/chess/ui/MainWindow.java
@@ -26,7 +26,7 @@ import dev.kske.chess.pgn.PGNGame;
* Project: Chess
* File: MainWindow.java
* Created: 01.07.2019
- *
+ *
* @since Chess v0.1-alpha
* @author Kai S. K. Engelbart
*/
@@ -88,21 +88,22 @@ public class MainWindow extends JFrame {
/**
* Creates a new {@link GamePane}, adds it to the tabbed pane and opens it.
* The new tab has the title {@code Game n} where {@code n} is its number.
- *
+ *
* @return The new {@link GamePane}
*/
- public GamePane addGamePane() { return addGamePane("Game " + (tabbedPane.getComponentCount() + 1)); }
+ public GamePane addGamePane() { return addGamePane("Game " + (tabbedPane.getTabCount() + 1)); }
/**
* Creates a new {@link GamePane}, adds it to the tabbed pane and opens it.
- *
+ *
* @param title The title of the {@link GamePane}
* @return The new {@link GamePane}
*/
public GamePane addGamePane(String title) {
GamePane gamePane = new GamePane();
tabbedPane.add(title, gamePane);
- tabbedPane.setSelectedIndex(tabbedPane.getComponentCount() - 1);
+ tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, new GameTabComponent(tabbedPane));
+ tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
return gamePane;
}
@@ -119,14 +120,14 @@ public class MainWindow extends JFrame {
/**
* Removes a {@link GamePane} form the tabbed pane.
- *
+ *
* @param index The index of the {@link GamePane} to remove
*/
public void removeGamePane(int index) { tabbedPane.remove(index); }
/**
* Loads a game file (FEN or PGN) and adds it to a new {@link GamePane}.
- *
+ *
* @param files the files to load the game from
*/
public void loadFiles(List files) {