001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.html.image.resource;
018
019import java.awt.Color;
020import java.awt.Font;
021import java.awt.FontMetrics;
022import java.awt.Graphics2D;
023import java.awt.RenderingHints;
024import java.awt.font.TextAttribute;
025import java.util.HashMap;
026import java.util.Map;
027
028/**
029 * Automatically generates a basic button image. The model for the component determines the label
030 * displayed on the button.
031 * 
032 * @author Jonathan Locke
033 */
034public class DefaultButtonImageResource extends RenderedDynamicImageResource
035{
036        private static final long serialVersionUID = 1L;
037
038        /** The default height for button images */
039        private static int defaultHeight = 26;
040
041        /** The default width for button images */
042        private static int defaultWidth = 74;
043
044        /** default color: orange. */
045        private static final int DEFAULT_COLOR = new Color(0xE9, 0x60, 0x1A).getRGB();
046
047        /** default background color: white. */
048        private static final int DEFAULT_BACKGROUND_COLOR = Color.WHITE.getRGB();
049
050        /** default text color: white. */
051        private static final int DEFAULT_TEXT_COLOR = Color.WHITE.getRGB();
052
053        /** default font: Helvetica bold 16. */
054        private static final Map<TextAttribute, Object> DEFAULT_FONT = new HashMap<TextAttribute, Object>(
055                new Font("Helvetica", Font.BOLD, 16).getAttributes());
056
057        /**
058         * @param defaultHeight
059         *            The defaultHeight to set.
060         */
061        public static void setDefaultHeight(int defaultHeight)
062        {
063                DefaultButtonImageResource.defaultHeight = defaultHeight;
064        }
065
066        /**
067         * @param defaultWidth
068         *            The defaultWidth to set.
069         */
070        public static void setDefaultWidth(int defaultWidth)
071        {
072                DefaultButtonImageResource.defaultWidth = defaultWidth;
073        }
074
075        /** The height of the arc in the corner */
076        private int arcHeight = 10;
077
078        /** The width of the arc in the corner */
079        private int arcWidth = 10;
080
081        /** The background color behind the button */
082        private int backgroundColorRgb = DEFAULT_BACKGROUND_COLOR;
083
084        /** The color of the button itself */
085        private int colorRgb = DEFAULT_COLOR;
086
087        /** The font to use */
088        private Map<TextAttribute, Object> fontAttributes = DEFAULT_FONT;
089
090        /** The color of the text */
091        private int textColorRgb = DEFAULT_TEXT_COLOR;
092
093        /** The button label */
094        private final String label;
095
096        /**
097         * @param label
098         *            The label for this button image
099         * @param width
100         *            Width of image in pixels
101         * @param height
102         *            Height of image in pixels
103         */
104        public DefaultButtonImageResource(int width, int height, final String label)
105        {
106                super(width, height, "png");
107                this.label = label;
108                setWidth(width == -1 ? defaultWidth : width);
109                setHeight(height == -1 ? defaultHeight : height);
110        }
111
112        /**
113         * @param label
114         *            The label for this button image
115         */
116        public DefaultButtonImageResource(final String label)
117        {
118                this(defaultWidth, defaultHeight, label);
119        }
120
121        /**
122         * @return Returns the arcHeight.
123         */
124        public synchronized int getArcHeight()
125        {
126                return arcHeight;
127        }
128
129        /**
130         * @return Returns the arcWidth.
131         */
132        public synchronized int getArcWidth()
133        {
134                return arcWidth;
135        }
136
137        /**
138         * @return Returns the backgroundColor.
139         */
140        public synchronized Color getBackgroundColor()
141        {
142                return new Color(backgroundColorRgb);
143        }
144
145        /**
146         * @return Returns the color.
147         */
148        public synchronized Color getColor()
149        {
150                return new Color(colorRgb);
151        }
152
153        /**
154         * @return Returns the font.
155         */
156        public synchronized Font getFont()
157        {
158                return new Font(fontAttributes);
159        }
160
161        /**
162         * @return Returns the textColor.
163         */
164        public synchronized Color getTextColor()
165        {
166                return new Color(textColorRgb);
167        }
168
169        /**
170         * @param arcHeight
171         *            The arcHeight to set.
172         */
173        public synchronized void setArcHeight(int arcHeight)
174        {
175                this.arcHeight = arcHeight;
176                invalidate();
177        }
178
179        /**
180         * @param arcWidth
181         *            The arcWidth to set.
182         */
183        public synchronized void setArcWidth(int arcWidth)
184        {
185                this.arcWidth = arcWidth;
186                invalidate();
187        }
188
189        /**
190         * @param backgroundColor
191         *            The backgroundColor to set.
192         */
193        public synchronized void setBackgroundColor(Color backgroundColor)
194        {
195                backgroundColorRgb = backgroundColor.getRGB();
196                invalidate();
197        }
198
199        /**
200         * @param color
201         *            The color to set.
202         */
203        public synchronized void setColor(Color color)
204        {
205                colorRgb = color.getRGB();
206                invalidate();
207        }
208
209        /**
210         * @param font
211         *            The font to set.
212         */
213        public synchronized void setFont(Font font)
214        {
215                fontAttributes = new HashMap<>(font.getAttributes());
216                invalidate();
217        }
218
219        /**
220         * @param textColor
221         *            The textColor to set.
222         */
223        public synchronized void setTextColor(Color textColor)
224        {
225                textColorRgb = textColor.getRGB();
226                invalidate();
227        }
228
229        /**
230         * Renders button image.
231         * 
232         * @see RenderedDynamicImageResource#render(java.awt.Graphics2D, Attributes)
233         */
234        @Override
235        protected boolean render(Graphics2D graphics, Attributes attributes)
236        {
237                // Get width and height
238                final int width = getWidth();
239                final int height = getHeight();
240
241                // Get size of text
242                graphics.setFont(getFont());
243                final FontMetrics fontMetrics = graphics.getFontMetrics();
244                final int dxText = fontMetrics.stringWidth(label);
245                final int dxMargin = 10;
246
247                // Does text fit with a nice margin?
248                if (dxText > width - dxMargin)
249                {
250                        // Re-render as a larger button
251                        setWidth(dxText + dxMargin);
252                        return false;
253                }
254                else
255                {
256                        // Turn on anti-aliasing
257                        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
258                                RenderingHints.VALUE_ANTIALIAS_ON);
259
260                        // Draw background
261                        Color bgColor = getBackgroundColor();
262                        graphics.setColor(bgColor);
263                        graphics.fillRect(0, 0, width, height);
264
265                        // Draw round rectangle
266                        graphics.setColor(getColor());
267                        graphics.setBackground(bgColor);
268                        graphics.fillRoundRect(0, 0, width, height, arcWidth, arcHeight);
269
270                        // Draw text
271                        graphics.setColor(getTextColor());
272                        final int x = (width - dxText) / 2;
273                        final int y = (getHeight() - fontMetrics.getHeight()) / 2;
274                        graphics.drawString(label, x, y + fontMetrics.getAscent());
275                        return true;
276                }
277        }
278}