/* * 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.component; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.AbstractButton; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.plaf.UIResource; import com.seaglasslookandfeel.SeaGlassContext; import com.seaglasslookandfeel.SeaGlassStyle; import com.seaglasslookandfeel.ui.SeaGlassButtonUI; /** * JButton object that draws a scaled Arrow in one of the cardinal directions. * * <p>Based on SynthArrowButton by Scott Violet.</p> * * @see javax.swing.plaf.synth.SynthArrowButton */ public class SeaGlassArrowButton extends JButton implements SwingConstants, UIResource { private static final long serialVersionUID = 2673388860074501956L; private int direction; /** * Creates a new SeaGlassArrowButton object. * * @param direction the direction to point the arrow. This will be one of * the SwingConstants {@code NORTH}, {@code WEST}, * {@code SOUTH}, or {@code EAST}. */ public SeaGlassArrowButton(int direction) { super(); super.setFocusable(false); setDirection(direction); setDefaultCapable(false); } /** * @see javax.swing.JButton#getUIClassID() */ public String getUIClassID() { return "ArrowButtonUI"; } /** * @see javax.swing.JButton#updateUI() */ public void updateUI() { setUI(new SeaGlassArrowButtonUI()); } /** * Set the arrow's direction. * * @param dir the direction to point the arrow. This will be one of the * SwingConstants {@code NORTH}, {@code WEST}, {@code SOUTH}, or * {@code EAST}. */ public void setDirection(int dir) { direction = dir; putClientProperty("__arrow_direction__", new Integer(dir)); repaint(); } /** * Get the direction of the arrow. * * @return the direction the arrow points. This will be one of the * SwingConstants {@code NORTH}, {@code WEST}, {@code SOUTH}, or * {@code EAST}. */ public int getDirection() { return direction; } /** * @see java.awt.Component#setFocusable(boolean) */ public void setFocusable(boolean focusable) { } /** * The UI delegate for the arrow button. */ private static class SeaGlassArrowButtonUI extends SeaGlassButtonUI { /** * @see com.seaglasslookandfeel.ui.SeaGlassButtonUI#installDefaults(javax.swing.AbstractButton) */ protected void installDefaults(AbstractButton b) { super.installDefaults(b); updateStyle(b); } /** * @see com.seaglasslookandfeel.ui.SeaGlassButtonUI#paint(com.seaglasslookandfeel.SeaGlassContext, * java.awt.Graphics) */ protected void paint(SeaGlassContext context, Graphics g) { SeaGlassArrowButton button = (SeaGlassArrowButton) context.getComponent(); Double scale = (Double)button.getClientProperty("__arrow_scale__"); if (scale == null) { scale = 1.0; } int width = (int) (button.getWidth()*scale); int height = (int) (button.getHeight()*scale); int x = (button.getWidth()-width)/2 * (button.getDirection() == SwingConstants.EAST?-1:1); int y = (button.getHeight()-height)/2 * (button.getDirection() == SwingConstants.SOUTH ?-1:1); context.getPainter().paintArrowButtonForeground(context, g, x, y, width, height, button.getDirection()); } /** * Paint the arrow background. * * @param context the SynthContext. * @param g the Graphics context. * @param c the arrow component. */ @SuppressWarnings("all") void paintBackground(SeaGlassContext context, Graphics g, JComponent c) { context.getPainter().paintArrowButtonBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); } /** * Paint the arrow border. * * @param context the SynthContext. * @param g the Graphics context. * @param x the x coordinate corresponding to the upper-left * corner to paint. * @param y the y coordinate corresponding to the upper-left * corner to paint. * @param w the width to paint. * @param h the height to paint. */ @SuppressWarnings("unused") public void paintBorder(SeaGlassContext context, Graphics g, int x, int y, int w, int h) { context.getPainter().paintArrowButtonBorder(context, g, x, y, w, h); } /** * Get the minimum size for the arrow. * * @return the minimum size. */ @SuppressWarnings("unused") public Dimension getMinimumSize() { return new Dimension(5, 5); } /** * Get the maximum size for the arrow. * * @return the maximum size. */ @SuppressWarnings("unused") public Dimension getMaximumSize() { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** * @see com.seaglasslookandfeel.ui.SeaGlassButtonUI#getPreferredSize(javax.swing.JComponent) */ public Dimension getPreferredSize(JComponent c) { SeaGlassContext context = getContext(c); Dimension dim = null; if (context.getComponent().getName() == "ScrollBar.button") { // ScrollBar arrow buttons can be non-square when // the ScrollBar.squareButtons property is set to FALSE // and the ScrollBar.buttonSize property is non-null dim = (Dimension) context.getStyle().get(context, "ScrollBar.buttonSize"); } if (dim == null) { // For all other cases (including Spinner, ComboBox), we will // fall back on the single ArrowButton.size value to create // a square return value int size = context.getStyle().getInt(context, "ArrowButton.size", 16); dim = new Dimension(size, size); } // handle scaling for sizeVarients for special case components. The // key "JComponent.sizeVariant" scales for large/small/mini // components are based on Apples LAF JComponent parent = (JComponent) context.getComponent().getParent(); if (parent != null && !(parent instanceof JComboBox)) { String scaleKey = SeaGlassStyle.getSizeVariant(parent); if (scaleKey != null) { if (SeaGlassStyle.LARGE_KEY.equals(scaleKey)) { dim = new Dimension((int) (dim.width * 1.15), (int) (dim.height * 1.15)); } else if (SeaGlassStyle.SMALL_KEY.equals(scaleKey)) { dim = new Dimension((int) (dim.width * 0.857), (int) (dim.height * 0.857)); } else if (SeaGlassStyle.MINI_KEY.equals(scaleKey)) { dim = new Dimension((int) (dim.width * 0.714), (int) (dim.height * 0.714)); } } } context.dispose(); return dim; } } }