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: */
017:
018: package javax.swing.plaf.synth;
019:
020: import java.awt.Color;
021: import java.awt.Font;
022: import java.awt.Insets;
023: import java.util.ArrayList;
024: import java.util.HashMap;
025: import java.util.List;
026:
027: import javax.swing.Icon;
028:
029: /**
030: * XMLSynthStyle class represents SynthStyle, generated from XMLSynthParser. The
031: * setters used in parser to configure style. The getters used in UI to draw the
032: * component.
033: */
034: class XMLSynthStyle extends SynthStyle implements Cloneable {
035:
036: /**
037: * Style properties
038: */
039: private final HashMap<String, Object> propertiesMap = new HashMap<String, Object>();
040:
041: /**
042: * Painters manager defines the correct painter to draw the UI under the
043: * style
044: */
045: private final PaintersManager paintersManager = new PaintersManager();
046:
047: /**
048: * Insets used in UI under the style
049: */
050: private Insets insets = new Insets(0, 0, 0, 0);
051:
052: /**
053: * GraphicsUtils used in UI
054: */
055: private SynthGraphicsUtils gUtils = new SynthGraphicsUtils();
056:
057: /**
058: * isOpaque property for UI (used in painters)
059: */
060: private boolean isOpaque = false;
061:
062: /**
063: * FontInfo contains all the registered fonts
064: */
065: private List<FontInfo> fonts = new ArrayList<FontInfo>();
066:
067: /**
068: * contains all the registered icons
069: */
070: private List<IconInfo> icons = new ArrayList<IconInfo>();
071:
072: /**
073: * ColorInfo contains all the registered colors according to ColorTypes
074: */
075: private List<ColorInfo> colors = new ArrayList<ColorInfo>();
076:
077: @Override
078: public Object get(@SuppressWarnings("unused")
079: SynthContext context, Object key) {
080: return propertiesMap.get(key);
081: }
082:
083: /**
084: * According to spec, graphicsUitils stated for style - not for context.
085: * That's why context is unused.
086: */
087: @Override
088: @SuppressWarnings("unused")
089: public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
090: return gUtils;
091: }
092:
093: @Override
094: public Insets getInsets(SynthContext context, Insets modified) {
095:
096: if (modified == null) {
097:
098: return (Insets) this .insets.clone();
099: }
100:
101: modified.set(insets.top, insets.left, insets.bottom,
102: insets.right);
103:
104: return modified;
105: }
106:
107: @Override
108: @SuppressWarnings("unused")
109: public SynthPainter getPainter(SynthContext context) {
110: return paintersManager;
111: }
112:
113: @Override
114: @SuppressWarnings("unused")
115: public boolean isOpaque(SynthContext context) {
116: return isOpaque;
117: }
118:
119: @Override
120: public Icon getIcon(SynthContext context, Object key) {
121: Icon result = null;
122:
123: int resultState = 0;
124: int componentState = context.getComponentState();
125: for (IconInfo info : icons) {
126: if (info.getKey().equalsIgnoreCase((String) key)) {
127: if (info.isStateFits(componentState)) {
128: if ((result == null)
129: || info.getState() >= resultState) {
130:
131: resultState = info.getState();
132: result = info.getIcon();
133:
134: }
135: }
136: }
137: }
138: return result;
139: }
140:
141: @Override
142: protected Font getFontForState(SynthContext context) {
143: Font result = null;
144: int resultState = 0;
145: int componentState = context.getComponentState();
146: for (FontInfo info : fonts) {
147: if (info.isStateFits(componentState)) {
148: if ((result == null)
149: || (info.getState() >= resultState)) {
150: resultState = info.getState();
151: result = info.getFont();
152: }
153: }
154: }
155: return result;
156: }
157:
158: /**
159: * Should note that RI's behavior depends on the order, described in the xml
160: * file (for example either state=ENABLED before state=FOCUSED or after) and
161: * the (unspecified) order of UI's state verification (for example,
162: * if(ButtonModel.isFocused) before Button.isEnabled in SynthButtonUI).
163: *
164: * I've construct the getColorForState, getFontForState and
165: * PainterManager.findPainter methods according to the RI's black box
166: * testing (although, the RI's behavior seems incorrect for me)
167: *
168: * Anyway, if you will to deal with using coloring, fonts or painters order
169: * you should see the following: UI: getComponentState method,
170: * XMLSynthParser: processColorElement, processFontElement,
171: * processPainterElement, processImagePainterElement (generating the lists),
172: * PainterManager(for painters) and this class
173: */
174: @Override
175: protected Color getColorForState(SynthContext context,
176: ColorType type) {
177: Color result = null;
178: int resultState = 0;
179: int componentState = context.getComponentState();
180: for (ColorInfo info : colors) {
181: if (info.getColorType() == type) {
182: if (info.isStateFits(componentState)) {
183: if ((result == null)
184: || componentState > resultState) {
185:
186: resultState = info.getState();
187: result = info.getColor();
188:
189: }
190: }
191: }
192: }
193: return result;
194: }
195:
196: @Override
197: protected Object clone() throws CloneNotSupportedException {
198: return super .clone();
199: }
200:
201: /** Method used in parser only */
202: void addFont(Font f, int state) {
203: fonts.add(new FontInfo(f, state));
204: }
205:
206: /** Method used in parser only */
207: void addColor(Color c, int state, ColorType type) {
208: colors.add(new ColorInfo(c, type, state));
209: }
210:
211: /**
212: * add painter to paintersManager. Method used in parser only
213: */
214: void addPainter(SynthPainter p, int state, String method,
215: int direction) {
216: paintersManager.setPainter(p, state, method, direction);
217: }
218:
219: void addIcon(Icon icon, int SynthState, String key) {
220: icons.add(new IconInfo(icon, SynthState, key));
221: }
222:
223: /**
224: * Method used in parser only
225: */
226: void setGraphicsUtils(SynthGraphicsUtils proposed) {
227: this .gUtils = proposed;
228: }
229:
230: /** Method used in parser only */
231: void setProperty(String key, Object value) {
232: propertiesMap.put(key, value);
233: }
234:
235: /** Method used in parser only */
236: void setInsets(Insets insets) {
237: this .insets = insets;
238: }
239:
240: /** Method used in parser only */
241: void setOpaque(boolean isOpaque) {
242: this .isOpaque = isOpaque;
243: }
244:
245: /**
246: * ColorInfo class used in SynthStyle for correct search Colors in List of
247: * colors.
248: */
249: private static class ColorInfo {
250:
251: private final ColorType type;
252:
253: private final int state;
254:
255: private final Color color;
256:
257: ColorInfo(Color color, ColorType type, int state) {
258: this .color = color;
259: this .type = type;
260: this .state = state;
261: }
262:
263: ColorType getColorType() {
264: return type;
265: }
266:
267: Color getColor() {
268: return color;
269: }
270:
271: int getState() {
272: return state;
273: }
274:
275: boolean isStateFits(int comparedState) {
276: return (((~comparedState) & (this .state)) == 0);
277: }
278:
279: }
280:
281: /**
282: * ColorInfo class used in SynthStyle for correct search Fonts in List
283: */
284: private static class FontInfo {
285:
286: private final int state;
287:
288: private final Font font;
289:
290: FontInfo(Font font, int state) {
291: this .font = font;
292: this .state = state;
293: }
294:
295: Font getFont() {
296: return font;
297: }
298:
299: int getState() {
300: return state;
301: }
302:
303: boolean isStateFits(int comparedState) {
304: return (((~comparedState) & (this .state)) == 0);
305: }
306:
307: }
308:
309: /**
310: * IconInfo class used in SynthStyle for correct search Icons in List
311: */
312: private static class IconInfo {
313:
314: private final int state;
315:
316: private final Icon icon;
317:
318: private final String key;
319:
320: IconInfo(Icon icon, int state, String key) {
321: this .icon = icon;
322: this .state = state;
323: this .key = key;
324: }
325:
326: Icon getIcon() {
327: return icon;
328: }
329:
330: int getState() {
331: return state;
332: }
333:
334: String getKey() {
335: return key;
336: }
337:
338: boolean isStateFits(int comparedState) {
339: return (((~comparedState) & (this .state)) == 0);
340: }
341:
342: }
343:
344: }
|