/**
* Open Wonderland
*
* Copyright (c) 2010 - 2012, Open Wonderland Foundation, All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* The Open Wonderland Foundation designates this particular file as
* subject to the "Classpath" exception as provided by the Open Wonderland
* Foundation in the License file that accompanied this code.
*/
package org.jdesktop.wonderland.modules.textchat.client;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicButtonUI;
/**
* A tabbed pane customised component with a closing button to be used as chat panels.
* Some code modified from:
* http://download.oracle.com/javase/tutorial/uiswing/examples/components/TabComponentsDemoProject/src/components/ButtonTabComponent.java
* @author jos <josmasflores@gmail.com>
*/
public class TextChatPanelTabbedPane extends javax.swing.JPanel implements ChangeListener{
JLabel label;
public TextChatPanelTabbedPane() {
initComponents();
}
public TextChatPanelTabbedPane(final JTabbedPane tabPanel, boolean allowClosing) {
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
if (tabPanel == null) {
throw new NullPointerException("TabbedPane is null");
}
this.tabPanel = tabPanel;
this.tabPanel.setTabPlacement(JTabbedPane.BOTTOM);
setOpaque(true); //Otherwise the foreground colour does not apply
//make JLabel read titles from JTabbedPane
label = new JLabel() {
@Override
public String getText() {
int i = tabPanel.indexOfTabComponent(TextChatPanelTabbedPane.this);
if (i != -1) {
return tabPanel.getTitleAt(i);
}
return null;
}
};
add(label);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
//Don't allow to close the 'All' tab by not creating the close button.
if ( allowClosing ){
JButton button = new TabButton();
add(button);
}
setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
this.tabPanel.addChangeListener(this);
}
/**
* When clicking in a tab put back the default foreground colour to clean up
* potential 'new message' sings (coloured in red)
* @param evt
*/
public void stateChanged(javax.swing.event.ChangeEvent evt) {
JTabbedPane pane = (JTabbedPane) evt.getSource();
int sel = pane.getSelectedIndex();
((TextChatPanelTabbedPane)tabPanel.getTabComponentAt(sel)).label.setForeground(null);
}
private class TabButton extends JButton implements ActionListener {
public TabButton() {
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(buttonMouseListener);
setRolloverEnabled(true);
addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
int i = tabPanel.indexOfTabComponent(TextChatPanelTabbedPane.this);
if (i != -1) {
tabPanel.remove(i);
}
}
//we don't want to update UI for this button
@Override
public void updateUI() {
}
//paint the cross
@Override
protected 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);
}
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();
}
}
private final static MouseListener buttonMouseListener = new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
Component component = e.getComponent();
if (component instanceof AbstractButton) {
AbstractButton button = (AbstractButton) component;
button.setBorderPainted(true);
}
}
@Override
public void mouseExited(MouseEvent e) {
Component component = e.getComponent();
if (component instanceof AbstractButton) {
AbstractButton button = (AbstractButton) component;
button.setBorderPainted(false);
}
}
};
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
tabPanel = new javax.swing.JTabbedPane();
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(tabPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(tabPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE)
.add(11, 11, 11))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
public javax.swing.JTabbedPane tabPanel;
// End of variables declaration//GEN-END:variables
}