/* * Copyright (c) 2009 Kathryn Huxtable and Kenneth Orr. * * This file is part of the SeaGlass Pluggable Look and Feel. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * $Id$ */ package com.seaglasslookandfeel.painter; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.Path2D; import javax.swing.JComponent; import com.seaglasslookandfeel.painter.AbstractRegionPainter.PaintContext.CacheMode; /** * Title pane menu button painter implementation. * * @author Kathryn Huxtable */ public final class TitlePaneMenuButtonPainter extends TitlePaneButtonPainter { /** * Control states. */ public static enum Which { ICON_ENABLED, ICON_DISABLED, ICON_MOUSEOVER, ICON_PRESSED, ICON_ENABLED_WINDOWNOTFOCUSED, ICON_MOUSEOVER_WINDOWNOTFOCUSED, ICON_PRESSED_WINDOWNOTFOCUSED, } private ButtonColors enabled = new ButtonColors(white16, black66, white4c, black66, black33, white33, transparentColor, black99, white99); private ButtonColors hover = new ButtonColors(white68, black66, white8c, black66, black33, white46, white59, gray_10_e5, white); private ButtonColors pressed = new ButtonColors(gray_9b_82, black66, gray_a9_9e, black66, black33, white33, gray_e6_59, gray_0e_e5, gray_e6); private Path2D path = new Path2D.Double(); private Which state; private PaintContext ctx; /** * Creates a new TitlePaneMenuButtonPainter object. * * @param state button state. */ public TitlePaneMenuButtonPainter(Which state) { super(); this.state = state; this.ctx = new PaintContext(CacheMode.FIXED_SIZES); } /** * {@inheritDoc} */ @Override protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { switch (state) { case ICON_ENABLED: case ICON_DISABLED: case ICON_ENABLED_WINDOWNOTFOCUSED: paintEnabled(g, c, width, height); break; case ICON_MOUSEOVER: case ICON_MOUSEOVER_WINDOWNOTFOCUSED: paintHover(g, c, width, height); break; case ICON_PRESSED: case ICON_PRESSED_WINDOWNOTFOCUSED: paintPressed(g, c, width, height); break; } } /** * {@inheritDoc} */ @Override protected PaintContext getPaintContext() { return ctx; } /** * Paint the background enabled state. * * @param g the Graphics2D context to paint with. * @param c the component. * @param width the width of the component. * @param height the height of the component. */ private void paintEnabled(Graphics2D g, JComponent c, int width, int height) { paintMenu(g, c, width, height, enabled); } /** * Paint the background mouse-over state. * * @param g the Graphics2D context to paint with. * @param c the component. * @param width the width of the component. * @param height the height of the component. */ private void paintHover(Graphics2D g, JComponent c, int width, int height) { paintMenu(g, c, width, height, hover); } /** * Paint the background pressed state. * * @param g the Graphics2D context to paint with. * @param c the component. * @param width the width of the component. * @param height the height of the component. */ private void paintPressed(Graphics2D g, JComponent c, int width, int height) { paintMenu(g, c, width, height, pressed); } /** * Paint the button using the specified colors. * * @param g the Graphics2D context to paint with. * @param c the component. * @param width the width of the component. * @param height the height of the component. * @param colors the color set to use to paint the button. */ private void paintMenu(Graphics2D g, JComponent c, int width, int height, ButtonColors colors) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g.setColor(colors.top); g.drawLine(0, 0, width - 2, 0); g.setColor(colors.leftOuter); g.drawLine(0, 0, 0, height - 4); g.setColor(colors.leftInner); g.drawLine(1, 1, 1, height - 4); g.drawLine(2, height - 3, 2, height - 3); Shape s = decodeInterior(width, height); g.setColor(colors.interior); g.fill(s); s = decodeEdge(width, height); g.setColor(colors.edge); g.draw(s); g.setColor(colors.edgeShade); g.drawLine(2, height - 2, 2, height - 2); g.drawLine(1, height - 3, 1, height - 3); g.drawLine(0, height - 4, 0, height - 4); s = decodeShadow(width, height); g.setColor(colors.shadow); g.draw(s); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); s = decodeMarkInterior(width, height); g.setColor(colors.markInterior); g.fill(s); s = decodeMarkBorder(width, height); g.setColor(colors.markBorder); g.draw(s); } /** * Create the button interior shape * * @param width the width. * @param height the height. * * @return the shape of the button interior. */ private Shape decodeInterior(int width, int height) { path.reset(); path.moveTo(1, 1); path.lineTo(width - 2, 1); path.lineTo(width - 2, height - 3); path.lineTo(width - 3, height - 2); path.lineTo(3, height - 2); path.lineTo(2, height - 3); path.closePath(); return path; } /** * Create the button edge shape. * * @param width the width. * @param height the height. * * @return the shape of the button edge. */ private Shape decodeEdge(int width, int height) { path.reset(); path.moveTo(width - 2, 0); path.lineTo(width - 2, height - 4); path.lineTo(width - 4, height - 2); path.lineTo(3, height - 2); return path; } /** * Create the button shadow shape. * * @param width the width. * @param height the height. * * @return the shape of the button shadow. */ private Shape decodeShadow(int width, int height) { path.reset(); path.moveTo(width - 1, 0); path.lineTo(width - 1, height - 4); path.lineTo(width - 4, height - 1); path.lineTo(2, height - 1); path.lineTo(1, height - 2); return path; } /** * Create the mark border shape. * * @param width the width. * @param height the height. * * @return the shape of the mark border. */ private Shape decodeMarkBorder(int width, int height) { double left = width / 2.0 - 4; double top = height / 2.0 - 4; path.reset(); path.moveTo(left + 0, top + 0); path.lineTo(left + 8, top); path.lineTo(left + 4, top + 6); path.closePath(); return path; } /** * Create the mark interior shape. * * @param width the width. * @param height the height. * * @return the shape of the mark interior. */ private Shape decodeMarkInterior(int width, int height) { double left = width / 2.0 - 4; double top = height / 2.0 - 4; path.reset(); path.moveTo(left + 1, top + 1); path.lineTo(left + 8, top + 1); path.lineTo(left + 4, top + 6); path.closePath(); return path; } /** * A class encapsulating the colors used for a button. */ private static class ButtonColors { /** Top line color. */ public Color top; /** Left outer edge color. */ public Color leftOuter; /** Left inner edge color. */ public Color leftInner; /** Main edge color. */ public Color edge; /** Main edge shade color. */ public Color edgeShade; /** Main shadow color. */ public Color shadow; /** Interior color. */ public Color interior; /** Mark border color. */ public Color markBorder; /** Mark interior color. */ public Color markInterior; /** * Creates a new ButtonColors object. * * @param top the top line color. * @param leftOuter the left outer edge color. * @param leftInner the left inner edge color. * @param edge the main edge color. * @param edgeShade the main edge shade color. * @param shadow the main shadow color. * @param interior the interior color. * @param markBorder the mark border color. * @param markInterior the mark interior color. */ public ButtonColors(Color top, Color leftOuter, Color leftInner, Color edge, Color edgeShade, Color shadow, Color interior, Color markBorder, Color markInterior) { this.top = top; this.leftOuter = leftOuter; this.leftInner = leftInner; this.edge = edge; this.edgeShade = edgeShade; this.shadow = shadow; this.interior = interior; this.markBorder = markBorder; this.markInterior = markInterior; } } }