001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.designtime.ext.componentgroup.util;
042:
043: import com.sun.rave.designtime.DesignBean;
044: import java.awt.Color;
045: import java.util.Map;
046: import com.sun.rave.designtime.DesignContext;
047: import com.sun.rave.designtime.DesignInfo;
048: import com.sun.rave.designtime.ext.componentgroup.ColorWrapper;
049: import com.sun.rave.designtime.ext.componentgroup.ComponentGroup;
050: import com.sun.rave.designtime.ext.componentgroup.ComponentGroupDesignInfo;
051: import com.sun.rave.designtime.ext.componentgroup.ComponentGroupHolder;
052: import com.sun.rave.designtime.ext.componentgroup.impl.ColorWrapperImpl;
053: import java.util.List;
054: import java.util.ArrayList;
055: import java.util.Arrays;
056: import java.util.Collection;
057: import java.util.HashMap;
058: import java.util.HashSet;
059: import java.util.Iterator;
060: import java.util.Set;
061:
062: /**
063: * <p>Helper class to paint Component Group colors, etc.</p>
064: * @author mbohm
065: */
066: public class ComponentGroupHelper {
067:
068: /**
069: * <p>Get a design context data key to store a component group color.</p>
070: */
071: public static String getComponentGroupColorKey(String holderName,
072: String groupName) {
073: return ComponentGroupHolder.COLOR_KEY_PREFIX + holderName + ":"
074: + groupName; //NOI18N
075: }
076:
077: /**
078: * <p>Populate a two-dimensional array of <code>ComponentGroup</code> based on the supplied
079: * <code>holders</code>, adding color information if necessary.</p>
080: * @param dcontext The design context.
081: * @param holders The array of existing holders.
082: * @param groupArr The two-dimensional array of <code>ComponentGroup</code> to populate based on <code>holders</code>.
083: */
084: public static void populateColorGroupArray(DesignContext dcontext,
085: ComponentGroupHolder[] holders, ComponentGroup[][] groupArr) {
086: populateColorModels(dcontext, holders, groupArr, null);
087: }
088:
089: /**
090: * <p>Populate a <code>Map<String,Color></code> based on the supplied
091: * <code>holders</code>, adding color information if necessary.</p>
092: * @param dcontext The design context.
093: * @param holders The array of existing holders.
094: * @param groupArr The <code>Map<String,Color></code> to populate based on <code>holders</code>.
095: */
096: public static void populateColorMap(DesignContext dcontext,
097: ComponentGroupHolder[] holders, Map<String, Color> colorMap) {
098: populateColorModels(dcontext, holders, null, colorMap);
099: }
100:
101: /**
102: * <p>Populate a two-dimensional array of <code>ComponentGroup</code> and
103: * a <code>Map<String,Color></code> based on the supplied
104: * <code>holders</code>, adding color information to both if necessary.</p>
105: * @param dcontext The design context.
106: * @param holders The array of existing holders.
107: * @param groupArr The two-dimensional array of <code>ComponentGroup</code> to populate based on <code>holders</code>.
108: * @param groupArr The <code>Map<String,Color></code> to populate based on <code>holders</code>.
109: */
110: public static void populateColorModels(DesignContext dcontext,
111: ComponentGroupHolder[] holders,
112: ComponentGroup[][] groupArr, Map<String, Color> colorMap) {
113: if (holders == null || holders.length == 0) {
114: return;
115: }
116: if (groupArr == null) {
117: groupArr = new ComponentGroup[holders.length][];
118: }
119: if (colorMap == null) {
120: colorMap = new HashMap<String, Color>();
121: }
122: List<ComponentGroup> unassignedComponentGroups = new ArrayList<ComponentGroup>();//existing groups that don't have a color assigned in colorMap
123: List<String> unassignedComponentGroupKeys = new ArrayList<String>(); //keys in dcontextData corresponding to unassignedComponentGroups
124: for (int h = 0; h < holders.length; h++) {
125: ComponentGroupHolder holder = holders[h];
126: ComponentGroup[] groups = holder
127: .getComponentGroups(dcontext);
128: groupArr[h] = groups;
129: if (groups != null) {
130: for (int i = 0; i < groups.length; i++) {
131: String holderName = holder.getName();
132: String name = groups[i].getName();
133: String key = ComponentGroupHelper
134: .getComponentGroupColorKey(holderName, name);
135: Object o = dcontext.getContextData(key);
136: Color color = null;
137: if (o instanceof ColorWrapper) {
138: color = ((ColorWrapper) o).getColor();
139: if (color != null) {
140: //color will already be in groups[i]
141:
142: //check to make sure the color is not already in the map
143: Collection<Color> values = colorMap
144: .values();
145: if (values.contains(color)) {
146: groups[i].setColor(null);
147: unassignedComponentGroups
148: .add(groups[i]);
149: unassignedComponentGroupKeys.add(key);
150: } else {
151: colorMap.put(key, color);
152: }
153: } else {
154: unassignedComponentGroups.add(groups[i]);
155: unassignedComponentGroupKeys.add(key);
156: }
157: } else if (o instanceof String) {
158: ColorWrapper cw = new ColorWrapperImpl(
159: (String) o);
160: color = cw.getColor();
161: if (color != null) {
162: dcontext.setContextData(key, cw);
163:
164: //color will already be in groups[i]
165:
166: //check to make sure the color is not already in the map
167: Collection<Color> values = colorMap
168: .values();
169: if (values.contains(color)) {
170: groups[i].setColor(null);
171: unassignedComponentGroups
172: .add(groups[i]);
173: unassignedComponentGroupKeys.add(key);
174: } else {
175: colorMap.put(key, color);
176: }
177: } else {
178: unassignedComponentGroups.add(groups[i]);
179: unassignedComponentGroupKeys.add(key);
180: }
181: } else {
182: unassignedComponentGroups.add(groups[i]);
183: unassignedComponentGroupKeys.add(key);
184: }
185: }
186: }
187: }
188: for (int i = 0; i < unassignedComponentGroups.size(); i++) {
189: ComponentGroup group = unassignedComponentGroups.get(i);
190: String key = unassignedComponentGroupKeys.get(i);
191: Color c = getLeastUsedColor(colorMap);
192: group.setColor(c);
193: colorMap.put(key, c);
194: }
195: }
196:
197: /**
198: * <p>The colors which can be assigned to a Component Group.</p>
199: */
200: public static Color[] DEFAULT_COLOR_SET = new Color[] { Color.blue,
201: Color.green, Color.red, Color.yellow, Color.magenta,
202: Color.orange, Color.cyan, Color.pink, new Color(0, 0, 128), //navy blue
203: new Color(255, 250, 205), //lemon chifon
204: new Color(0, 100, 0), //dark green
205: new Color(255, 228, 225), //misty rose
206: new Color(250, 128, 114), //salmon
207: new Color(224, 255, 255), //light cyan
208: new Color(255, 105, 180), //hot pink
209: new Color(205, 92, 92), //indian red
210: new Color(0, 0, 205), //medium blue
211: new Color(143, 188, 143), //dark sea green
212: new Color(238, 221, 130), //light goldenrod
213: new Color(238, 130, 238), //violet
214: new Color(244, 238, 224), //honeydew 2
215: new Color(64, 224, 208), //turquoise
216: new Color(255, 218, 185), //peach puff
217: new Color(240, 128, 128), //light coral
218: new Color(135, 206, 250), //light sky blue
219: new Color(46, 139, 87), //sea green
220: new Color(218, 165, 32), //goldenrod
221: new Color(230, 230, 250), //lavender
222: new Color(189, 183, 107), //dark khaki
223: new Color(208, 32, 144), //violet red
224: new Color(173, 255, 47), //green yellow
225: new Color(70, 130, 180), //steel blue
226: new Color(205, 133, 63), //peru
227: new Color(175, 238, 238), //pale turquoise
228: new Color(60, 179, 113), //medium sea green
229: new Color(176, 196, 222), //light steel blue
230: new Color(186, 85, 211), //medium orchid
231: new Color(244, 164, 96), //sandy brown
232: new Color(32, 178, 170), //light sea green
233: new Color(165, 42, 42), //brown
234: new Color(50, 205, 50), //lime green
235: };
236:
237: /**
238: * <p>Get the appropriate <code>Color</code> in the supplied
239: * <code>Map</code>, assigning one if necessary.</p>
240: */
241: public static Color getMappedColor(String key, Map colorMap) {
242: Color c = (Color) colorMap.get(key);
243: if (c != null) {
244: return c;
245: }
246: c = getLeastUsedColor(colorMap);
247: colorMap.put(key, c);
248: return c;
249: }
250:
251: /**
252: * <p>Of the colors in the default set, get one that appears least in the
253: * supplied <code>colorMap</code>.</p>
254: */
255: private static Color getLeastUsedColor(Map colorMap) {
256: Map<Color, Integer> timesUsed = new HashMap();
257: for (Iterator<Color> iter = colorMap.values().iterator(); iter
258: .hasNext();) {
259: Color c = iter.next();
260: Integer times = timesUsed.get(c);
261: if (times == null) {
262: timesUsed.put(c, new Integer(1));
263: } else {
264: int t = times.intValue();
265: timesUsed.put(c, new Integer(t + 1));
266: }
267: }
268:
269: Color leastUsedColor = null;
270: int leastTimesUsed = -1;
271: for (int i = 0; i < DEFAULT_COLOR_SET.length; i++) {
272: Color c = DEFAULT_COLOR_SET[i];
273: Integer times = timesUsed.get(c);
274: if (times == null) { //color c not yet used
275: return c;
276: } else {
277: int t = times.intValue(); //color c used t times
278: if (leastTimesUsed < 0 || t < leastTimesUsed) {
279: leastTimesUsed = t;
280: leastUsedColor = c;
281: }
282: }
283: }
284: return leastUsedColor;
285: }
286:
287: /**
288: * <p>Get all the <code>ComponentGroupHolder</code> instances associated
289: * with the supplied <code>DesignContext</code>.</p>
290: * @param dcontext The design context.
291: */
292: public static ComponentGroupHolder[] getComponentGroupHolders(
293: DesignContext dcontext) {
294: //get flat list of beans for this dcontext
295: DesignBean[] dcontextBeans = dcontext.getBeans();
296: if (dcontextBeans == null || dcontextBeans.length == 0) {
297: return null;
298: }
299: Set<String> designInfoSet = new HashSet<String>();
300: List<ComponentGroupHolder> holderList = new ArrayList<ComponentGroupHolder>();
301: for (int b = 0; b < dcontextBeans.length; b++) {
302: DesignInfo designInfo = dcontextBeans[b].getDesignInfo();
303: if (!(designInfo instanceof ComponentGroupDesignInfo)) {
304: continue;
305: }
306: String designInfoClassName = designInfo.getClass()
307: .getName();
308: if (designInfoSet.contains(designInfoClassName)) {
309: continue;
310: }
311: designInfoSet.add(designInfoClassName);
312: ComponentGroupDesignInfo componentGroupDesignInfo = (ComponentGroupDesignInfo) designInfo;
313: ComponentGroupHolder[] designInfoHolders = componentGroupDesignInfo
314: .getComponentGroupHolders();
315: if (designInfoHolders != null) {
316: holderList.addAll(Arrays.asList(designInfoHolders));
317: }
318: }
319: return holderList.toArray(new ComponentGroupHolder[holderList
320: .size()]);
321: }
322: }
|