package org.korsakow.ide.ui.laf; import java.awt.BasicStroke; import java.awt.Component; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicButtonUI; import org.korsakow.ide.ui.components.KCollapsiblePane; import org.korsakow.ide.util.UIResourceManager; public class KorsakowCollapsiblePaneHeaderUI extends BasicButtonUI { private static final Icon arrowExpandedIcon = UIResourceManager.getIcon("arrow_down.png"); private static final Icon arrowCollapsedIcon = UIResourceManager.getIcon("arrow_left.png"); // Shared UI object private final static KorsakowCollapsiblePaneHeaderUI sharedUI = new KorsakowCollapsiblePaneHeaderUI(); public static ComponentUI createUI(JComponent c) { return sharedUI; } public void installUI(JComponent c) { super.installUI(c); c.setOpaque(false); ((AbstractButton)c).setRolloverEnabled(true); } // public void public void installDefaults(AbstractButton b) { super.installDefaults(b); Insets insets = UIManager.getInsets("CollapsiblePaneHeader.margin"); b.setBorder(null); // aqua does this. perhaps other too. this happens early enough that it should not interfere with borders set in user code b.setBorder(BorderFactory.createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right)); // cant get margins to work! b.setVerticalAlignment(SwingConstants.BOTTOM); b.setHorizontalAlignment(SwingConstants.LEFT); // b.setMargin(UIManager.getInsets("CollapsiblePaneHeader.margin")); } // contentPane.setBackground(UIManager.getColor("CollapsiblePane.background")); public void paint(Graphics g, JComponent c) { if (Boolean.FALSE.equals(c.getClientProperty("roundedCorners"))) paintSquare(g, c); else paintRounded(g, c); KCollapsiblePane pane = (KCollapsiblePane)c.getClientProperty(KCollapsiblePane.HEADER_UI_PROPERTY_OWNER_PANE); if (pane != null) { Rectangle bounds = c.getBounds(); Icon arrowIcon = pane.isExpanded()?arrowExpandedIcon:arrowCollapsedIcon; arrowIcon.paintIcon(c, g, bounds.width-arrowIcon.getIconWidth(), (bounds.height - arrowIcon.getIconWidth())/2); } } public void paintSquare(Graphics g, JComponent c) { AbstractButton button = (AbstractButton)c; button.getInsets(); float strokeSize = UIManager.getInt("CollapsiblePaneHeader.borderSize"); //KorsakowLookAndFeel.BORDER_STROKE_SIZE; int width = c.getWidth(); width -= 1; // rounded rect gets clipped slightly int height = c.getHeight(); Rectangle bounds = c.getBounds(); Graphics2D g2 = (Graphics2D)g; // background // background comes after to cover the crossign lines of the two border rects GradientPaint paint = new GradientPaint(0, 0, UIManager.getColor("CollapsiblePaneHeader.background"), 0, height, UIManager.getColor("CollapsiblePaneHeader.background2"), false); boolean isOver = button.getMousePosition(true) != null; if (isOver) paint = new GradientPaint(0, 0, UIManager.getColor("CollapsiblePaneHeader.activeBackground"), 0, height, UIManager.getColor("CollapsiblePaneHeader.activeBackground2"), false);; g2.setPaint(paint); g2.fill(bounds); // border g2.setStroke(new BasicStroke(strokeSize)); g2.setColor(UIManager.getColor("CollapsiblePaneHeader.border")); g2.draw(bounds); super.paint(g2, c); } public void paintRounded(Graphics g, JComponent c) { AbstractButton button = (AbstractButton)c; button.getInsets(); int arcWidth = UIManager.getInt("CollapsiblePaneHeader.roundedCornerSize"); //KorsakowLookAndFeel.ROUNDED_CORNER_SIZE; int arcHeight = UIManager.getInt("CollapsiblePaneHeader.roundedCornerSize"); //KorsakowLookAndFeel.ROUNDED_CORNER_SIZE; float strokeSize = UIManager.getInt("CollapsiblePaneHeader.borderSize"); //KorsakowLookAndFeel.BORDER_STROKE_SIZE; int width = c.getWidth(); width -= 1; // rounded rect gets clipped slightly int height = c.getHeight(); Rectangle bounds = c.getBounds(); Graphics2D g2 = (Graphics2D)g; RoundRectangle2D.Float borderTopRect = new RoundRectangle2D.Float(strokeSize/2, strokeSize/2, width-strokeSize, height-strokeSize, arcWidth, arcHeight); Rectangle2D.Float borderBottomRect = new Rectangle2D.Float(strokeSize/2, height/2, width, height/2); // background // background comes after to cover the crossign lines of the two border rects GradientPaint paint = new GradientPaint(0, 0, UIManager.getColor("CollapsiblePaneHeader.background"), 0, height, UIManager.getColor("CollapsiblePaneHeader.background2"), false); boolean isOver = button.getMousePosition(true) != null; if (isOver) paint = new GradientPaint(0, 0, UIManager.getColor("CollapsiblePaneHeader.activeBackground"), 0, height, UIManager.getColor("CollapsiblePaneHeader.activeBackground2"), false);; g2.setPaint(paint); g2.fill(borderTopRect); g2.fill(borderBottomRect); // border g2.setStroke(new BasicStroke(strokeSize)); g2.setColor(UIManager.getColor("CollapsiblePaneHeader.borderColor")); // g2.setColor(Color.red); KorsakowLafUtil.drawTopRoundedRect(g2, 0, 0, width, height, arcWidth, arcHeight); // g2.drawArc((int)(borderTopRect.x), (int)(borderTopRect.y), arcWidth, arcHeight*2, 90, 90); // top left // g2.drawArc((int)(borderTopRect.x+borderTopRect.width-arcWidth), (int)(borderTopRect.y), arcWidth, arcHeight, 0, 90); // top right // g2.drawLine((int)(borderTopRect.x+arcWidth/2), (int)(borderTopRect.y), (int)(borderTopRect.width-arcWidth/2), (int)borderTopRect.y); // top // g2.drawLine((int)(borderTopRect.x), (int)(borderTopRect.y+arcHeight/2), (int)(borderTopRect.x), (int)(borderBottomRect.y+borderBottomRect.height)); // left // g2.drawLine((int)(borderTopRect.x+borderTopRect.width), (int)(borderTopRect.y+arcHeight/2), (int)(borderTopRect.x+borderTopRect.width), (int)(borderBottomRect.y+borderBottomRect.height)); // right // g2.drawLine((int)(borderTopRect.x), (int)(borderBottomRect.y+borderBottomRect.height-1), (int)(borderTopRect.x + borderTopRect.width), (int)(borderBottomRect.y+borderBottomRect.height-1)); // bottom // g2.draw(borderTopRect); // g2.draw(borderBottomRect); super.paint(g2, c); } }