2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.netbeans.swing.tabcontrol.plaf;
45
import java.awt.geom.AffineTransform;
46
import java.awt.image.BufferedImage;
47
import java.util.HashMap;
48
import java.util.Arrays;
49
import java.util.Date;
52
* GenericGlowingChiclet works nicely to draw Aqua-style decorations, but is a bit
53
* slow. In particular, Area.pruneEdges() is not cheap, but is heavily used to divide
56
* This wrapper class provides a cache of bitmaps painted by GenericGlowingChiclet,
57
* timestamped against the last
58
* time they were used, and occasionally prunes not recently used bitmaps.
60
* @author Tim Boudreau
62
public class ChicletWrapper implements Runnable {
63
private boolean allowVertical = true;
64
private boolean leftNotch = false;
65
private boolean rightNotch = false;
66
private int state = 0;
67
private Rectangle bounds = new Rectangle();
68
private float[] arcs = new float[4];
69
GenericGlowingChiclet chiclet = GenericGlowingChiclet.INSTANCE; //XXX kill static instance
71
public void setState (int state) {
75
public void setBounds (int x, int y, int w, int h) {
76
bounds.setBounds (x, y, w, h);
79
static int drawCount = 0;
80
public void draw (Graphics g) {
81
if (bounds.width == 0 || bounds.height == 0) {
84
BufferedImage img = findBufferedImage();
85
((Graphics2D) g).drawRenderedImage(img, AffineTransform.getTranslateInstance(0, 0));
87
if (drawCount % 100 == 0) {
88
//Occasionally prune old bitmaps
89
SwingUtilities.invokeLater(this);
93
public void setArcs (float a, float b, float c, float d) {
101
public void setAllowVertical (boolean b) {
105
public void setNotch (boolean right, boolean left) {
113
+ Double.doubleToLongBits(arcs[0]) * 31
114
+ Double.doubleToLongBits(arcs[1]) * 37
115
+ Double.doubleToLongBits(arcs[2]) * 43
116
+ Double.doubleToLongBits(arcs[3]) * 47
117
+ bounds.width * 6703
118
+ bounds.height * 1783;
130
return new Long(result);
133
private static HashMap<CacheEntry,BufferedImage> cache = new HashMap<CacheEntry,BufferedImage>();
135
private BufferedImage findBufferedImage() {
137
CacheEntry entry = new CacheEntry (hash);
139
BufferedImage result = cache.get(entry);
140
if (result == null) {
141
result = createImage();
143
//Store our new entry with new timestamp, even if we found an old one
144
cache.put (entry, result);
148
private BufferedImage createImage() {
149
BufferedImage img = new BufferedImage (bounds.width, bounds.height,
150
BufferedImage.TYPE_INT_ARGB_PRE);
151
chiclet.setNotch(rightNotch, leftNotch);
152
chiclet.setArcs (arcs[0], arcs[1], arcs[2], arcs[3]);
153
chiclet.setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
154
chiclet.setAllowVertical(allowVertical);
155
chiclet.setState (state);
156
Graphics g = img.getGraphics();
157
g.translate (-bounds.x, -bounds.y);
158
ColorUtil.setupAntialiasing(g);
159
chiclet.draw((Graphics2D)g);
160
g.translate (bounds.x, bounds.y);
165
if (cache.size() < 5) {
168
HashMap<CacheEntry,BufferedImage> newCache = new HashMap<CacheEntry,BufferedImage>( cache );
169
long startTime = System.currentTimeMillis();
170
CacheEntry[] entries = (CacheEntry[]) newCache.keySet().toArray(new CacheEntry[0]);
171
Arrays.sort (entries);
172
for (int i=entries.length-1; i >= entries.length / 3; i--) {
173
if (startTime - entries[i].timestamp > 240000) {
174
newCache.remove (entries[i]);
180
private static final class CacheEntry implements Comparable {
181
private final Long hash;
182
long timestamp = System.currentTimeMillis();
183
public CacheEntry (Long hash) {
187
public boolean equals (Object o) {
188
if (o instanceof CacheEntry) {
189
CacheEntry other = (CacheEntry) o;
190
return other.hash() == hash();
191
} else if (o instanceof Long) {
192
return ((Long) o).longValue() == hash();
199
return hash.longValue();
202
public int hashCode() {
203
return hash.intValue();
206
public int compareTo(Object o) {
207
CacheEntry other = (CacheEntry) o;
208
//Okay, every 4 days we might let an unused bitmap get old
209
return (int) (timestamp - other.timestamp);
212
public String toString() {
213
return "CacheEntry: " + new Date(timestamp) + " hash " + hash();