package com.lamatek.swingextras;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.ImageProducer;
import java.net.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.util.Enumeration;
/**
* A toolbar to be used in MDI interfaces. This toolbar is floatable and
* when floated, creates a new javax.swing.JInternalFrame with the toolbar enclosed.
* This toolbar provides a draggable 'thumb' component that the user drags into the
* desktop pane to float the toolbar. When the JInternalFrame is closed or is dragged
* back to the original docked location, the toolbar is docked and the JInternalFrame
* is disposed.<p>
* A JInternalToolBar can be either vertically or horizontally oriented.
*/
public class JInternalToolBar extends JPanel implements MouseListener, MouseMotionListener {
/** Variable used to declare vertical (top to bottom) orientation.*/
public static final int VERTICAL = 0;
/** Variable used to declare horizontal (left to right) orientation.*/
public static final int HORIZONTAL = 1;
protected int orientation;
private String title;
private GridBagLayout g;
private GridBagConstraints c;
protected boolean floatable = false;
protected boolean docked = true;
private ImageIcon icon;
private JInternalToolBar.Thumb thumb;
private JInternalToolBar.InternalFrame frame;
private JPanel panel;
protected JDesktopPane desktop;
private Border border;
private Rectangle dockSpace;
/**
* Creates a new floatable, dockable JInternalToolBar.
*
* @param title The text label for the JInternalFrame when floating.
* @param orientation Denotes whether the JInternalToolBar should be vertically or horizontally oriented. Use the
* {@link #VERTICAL VERTICAL} or {@link #HORIZONTAL HORIZONTAL} static variables.
* @param desktop The JDesktopPane to contain the Toolbar when floating.
*/
public JInternalToolBar(String title, int orientation, JDesktopPane desktop) {
super(new BorderLayout());
g = new GridBagLayout();
c = new GridBagConstraints();
c.anchor = c.WEST;
c.insets = new Insets(0, 0, 0, 0);
c.gridx = 0;
c.gridy = 0;
panel = new JPanel(g);
border = LineBorder.createBlackLineBorder();
setBorder(border);
if (orientation == HORIZONTAL) {
c.fill = c.VERTICAL;
super.add("West", panel);
}
else if (orientation == VERTICAL) {
c.fill = c.HORIZONTAL;
super.add("North", panel);
}
this.title = title;
this.orientation = orientation;
this.desktop = desktop;
}
//MouseMotionListener
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseDragged(MouseEvent e) {
if (e.getSource() instanceof JInternalToolBar.Thumb) {
if (! floatable) {
floatable = true;
}
}
}
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseMoved(MouseEvent e) {
}
//MouseListener
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseClicked(MouseEvent e) {
}
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof JInternalToolBar.Thumb) {
thumb.showPressed();
}
}
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof JInternalToolBar.Thumb) {
thumb.showReleased();
}
}
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mousePressed(MouseEvent e) {
}
/**
* Used by the {@link com.lamatek.swingextras.JInternalToolBar.Thumb Thumb} object.
*/
public void mouseReleased(MouseEvent e) {
if (e.getSource() instanceof JInternalToolBar.Thumb) {
if (floatable && docked) {
Point p = e.getPoint();
int xHeight = panel.getSize().height;
unDock();
if (p.x < 0) {
p.x += getToolkit().getScreenSize().width;
p.x -= frame.getSize().width;
}
if (p.y < 0) {
p.y += getToolkit().getScreenSize().height;
p.y -= (frame.getSize().height + xHeight);
}
frame.setLocation(p);
}
}
}
/**
* Sets the frame icon when the toolbar is floating.
*
* @param icon The icon for the frame when the toolbar is floating.
*/
public void setToolBarIcon(ImageIcon icon) {
this.icon = icon;
}
/**
* Adds a separator of the given size to the toolbar.
*
* @param size The size of the separator to be added.
*/
public void addSeparator(int size) {
JInternalToolBar.Separator separator = new JInternalToolBar.Separator(size, this);
panel.add(separator);
if (orientation == HORIZONTAL)
c.gridx++;
else if (orientation == VERTICAL)
c.gridy++;
g.setConstraints(separator, c);
}
/**
* Adds a javax.swing.JButton to the toolbar.
*
* @param button The next JButton to add to the toolbar.
* @return The button added to the toolbar.
*/
public JButton add(JButton button) {
if (c.gridx == 0 && c.gridy == 0) {
thumb = new JInternalToolBar.Thumb(this);
thumb.addMouseListener(this);
thumb.addMouseMotionListener(this);
panel.add(thumb);
g.setConstraints(thumb, c);
}
panel.add(button);
if (orientation == HORIZONTAL)
c.gridx++;
else if (orientation == VERTICAL)
c.gridy++;
g.setConstraints(button, c);
return button;
}
/**
* Sets the border for the toolbar when docked.
*
* @param b The border to be used when the toolbar is docked.
*/
public void setToolBarBorder(Border b) {
this.border = b;
setBorder(b);
}
protected void unDock() {
dockSpace = new Rectangle(getLocationOnScreen().x, getLocationOnScreen().y, getSize().width, getSize().height);
remove(panel);
setBorder(null);
Component p = getParent();
while (! (p instanceof Frame))
p = p.getParent();
p.validate();
panel.remove(thumb);
panel.validate();
frame = new JInternalToolBar.InternalFrame(title, panel, desktop, this);
frame.addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
Rectangle r = new Rectangle(frame.getLocationOnScreen().x, frame.getLocationOnScreen().y, frame.getSize().width, frame.getSize().height);
if (dockSpace.intersects(r)) {
frame.setVisible(false);
dock();
frame.dispose();
}
}
});
frame.addMouseListener(this);
if (icon != null)
frame.setFrameIcon(icon);
docked = false;
}
protected void dock() {
frame.getContentPane().remove(panel);
panel.add(thumb);
thumb.showReleased();
c.gridx = 0;
c.gridy = 0;
g.setConstraints(thumb, c);
panel.validate();
if (orientation == HORIZONTAL) {
super.add("West", panel);
}
else if (orientation == VERTICAL) {
super.add("North", panel);
}
setBorder(border);
Component p = getParent();
while (! (p instanceof Frame))
p = p.getParent();
p.validate();
floatable = false;
docked = true;
}
/**
* Sets the frame icon when the toolbar is floating.
* @param icon The icon to use when the toolbar is floating.
* @see #setToolBarIcon(ImageIcon) setToolBarIcon
*/
public void setFrameIcon(ImageIcon icon) {
this.icon = icon;
}
class Separator extends JComponent {
private int size;
private JInternalToolBar parent;
Separator(int size, JInternalToolBar p) {
this.size = size;
this.parent = p;
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
e.consume();
}
});
}
public Dimension getPreferredSize() {
if (parent.orientation == parent.HORIZONTAL) {
return new Dimension(size, 1);
}
else if (parent.orientation == parent.VERTICAL) {
return new Dimension(1, size);
}
return new Dimension(size, size);
}
public Dimension getMinimumSize() {
return getPreferredSize();
}
}
class InternalFrame extends JInternalFrame {
private JInternalToolBar tb;
InternalFrame(String title, JPanel c, JDesktopPane d, JInternalToolBar toolbar) {
super(title, false, true, false, true);
this.tb = toolbar;
getContentPane().add("Center", c);
pack();
d.add(this, JDesktopPane.MODAL_LAYER);
d.moveToFront(this);
setVisible(true);
addInternalFrameListener(new InternalFrameAdapter() {
public void internalFrameClosing(InternalFrameEvent e) {
setVisible(false);
tb.dock();
dispose();
}
});
}
}
class Thumb extends JComponent {
JInternalToolBar jit;
Color paint, bg, highlight;
Thumb(JInternalToolBar jit) {
super();
this.jit = jit;
UIDefaults ui = (UIManager.getLookAndFeel()).getDefaults();
bg = ui.getColor("control");
highlight = ui.getColor("controlShadow");
paint = bg;
}
public void paint(Graphics g) {
g.setColor(paint);
g.fillRect(0, 0, getSize().width, getSize().height);
int x = 0;
int y = 0;
boolean even = true;
while (y < getSize().height) {
while (x < getSize().width) {
g.setColor(paint.brighter());
g.fillRect(x, y, 1, 1);
g.setColor(paint.darker());
g.fillRect(x+1, y+1, 1, 1);
x += 4;
}
if (!even) {
x = 0;
}
else {
x = 2;
}
even = !even;
y += 2;
}
}
public void showPressed() {
paint = highlight;
repaint();
}
public void showReleased() {
paint = bg;
repaint();
}
public Dimension getMinimumSize() {
if (jit.orientation == jit.VERTICAL) {
return new Dimension(jit.getSize().width - 2, 20);
}
else {
return new Dimension(20, jit.getSize().height - 2);
}
}
public Dimension getPreferredSize() {
return getMinimumSize();
}
public void updateUI() {
UIDefaults ui = (UIManager.getLookAndFeel()).getDefaults();
bg = ui.getColor("control");
highlight = ui.getColor("controlShadow");
paint = bg;
repaint();
}
}
}