Sep 21

The following class will allow you to include a component in the top left of a Swing Border, similar to how the text is displayed in a TitledBorder. But instead of text you can insert any JComponent.

The MouseListener is there to enable the component in the border to respond to mouse events. You can remove it if not needed.

The code is provided as is with limited testing, so use at your own risk.

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;

public class ComponentTitledBorder extends AbstractBorder {
	
	// How much to offset component from left edge
	
	private static final int X_OFFSET = 10;
	
	private JComponent container = null;
	private JComponent component = null;
	private Border border = null;
	private Rectangle rect = null;
	
	public ComponentTitledBorder(JComponent container, JComponent component, Border border) {
		this.container = container;
		this.component = component;
		this.border = border;
		if (container!=null) {
			container.addMouseListener(new MouseListener() {

				@Override
				public void mouseClicked(MouseEvent e) {
					dispatchEvent(e);
				}

				@Override
				public void mouseEntered(MouseEvent e) {
					dispatchEvent(e);
				}

				@Override
				public void mouseExited(MouseEvent e) {
					dispatchEvent(e);
				}

				@Override
				public void mousePressed(MouseEvent e) {
					dispatchEvent(e);
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					dispatchEvent(e);
				}
				
				private void dispatchEvent(MouseEvent event) {
					Point p = event.getPoint();
					if (rect!=null && rect.contains(p)) { 
						p.translate(-X_OFFSET, 0); 
						JComponent comp = ComponentTitledBorder.this.component;
						comp.setBounds(rect);
						comp.dispatchEvent(
							new MouseEvent(comp, event.getID(), event.getWhen(), event.getModifiers(), 
								p.x, p.y, event.getClickCount(), event.isPopupTrigger(), event.getButton()));
						ComponentTitledBorder.this.container.repaint();
					}
				}

			});
		}
	}
	
	@Override
	public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

		Insets insets = getBorderInsets(c);
		
		// First paint the border
		
		if (border != null) {
			Insets borderInsets = border.getBorderInsets(c);
			int halfTop = (insets.top - borderInsets.top) / 2;
			border.paintBorder(c, g, x, y+halfTop, width, height-halfTop);			
		}
		
		// Now paint the component
		
		if (component!=null) {
			rect = new Rectangle(component.getPreferredSize());
			rect.x = X_OFFSET;
			SwingUtilities.paintComponent(g, component, (Container) c, rect);
		}
	}

	@Override
    public Insets getBorderInsets(Component c)       {
        return getBorderInsets(c, new Insets(0, 0, 0, 0));
    }

    @Override
	public Insets getBorderInsets(Component c, Insets insets) {
        if (border != null) {
            if (border instanceof AbstractBorder) {
                ((AbstractBorder)border).getBorderInsets(c, insets);
            } else {
                Insets i = border.getBorderInsets(c);
                insets.top = i.top;
                insets.right = i.right;
                insets.bottom = i.bottom;
                insets.left = i.left;
            }
        }
        
        if (c==null || component==null) return insets;
        
        // height of the top is the bigger of the component and the border
        
        Dimension size = component.getPreferredSize();
		insets.top = Math.max(size.height, insets.top);

		return insets;
	}

	@Override
	public boolean isBorderOpaque() {
		return true;
	}

}

written by objects \\ tags: , , ,


Leave a Reply

You must be logged in to post a comment.