8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.css;
27
28 import com.sun.javafx.css.converters.BooleanConverter;
29 import com.sun.javafx.css.converters.ColorConverter;
30 import com.sun.javafx.css.converters.DurationConverter;
31 import com.sun.javafx.css.converters.EffectConverter;
32 import com.sun.javafx.css.converters.EnumConverter;
33 import com.sun.javafx.css.converters.FontConverter;
34 import com.sun.javafx.css.converters.InsetsConverter;
35 import com.sun.javafx.css.converters.PaintConverter;
36 import com.sun.javafx.css.converters.SizeConverter;
37 import com.sun.javafx.css.converters.StringConverter;
38 import com.sun.javafx.css.converters.URLConverter;
39 import javafx.geometry.Insets;
40 import javafx.scene.effect.Effect;
41 import javafx.scene.paint.Color;
42 import javafx.scene.paint.Paint;
43 import javafx.scene.text.Font;
44 import javafx.util.Duration;
45
46 /**
47 * Converter converts {@code ParsedValue&tl;F,T>} from type F to type T. the
48 * {@link CssMetaData} API requires a {@code StyleConverter} which is used
49 * when computing a value for the {@see StyleableProperty}. There are
50 * a number of predefined converters which are accessible by the static
51 * methods of this class.
52 * @see ParsedValue
53 * @see StyleableProperty
54 * @since JavaFX 8.0
55 */
56 public class StyleConverter<F, T> {
57
58 /**
59 * Convert from the parsed CSS value to the target property type.
60 *
61 * @param value The {@link ParsedValue} to convert
62 * @param font The {@link Font} to use when converting a
63 * <a href="http://www.w3.org/TR/css3-values/#relative-lengths">relative</a>
64 * value.
65 */
66 @SuppressWarnings("unchecked")
67 public T convert(ParsedValue<F,T> value, Font font) {
68 // unchecked!
69 return (T) value.getValue();
70 }
71
168
169 /**
170 * A converter for quoted strings which may have embedded unicode characters.
171 * @return A {@code StyleConverter} that converts a representation of a
172 * CSS string value to a {@code String}.
173 */
174 public static StyleConverter<String,String> getStringConverter() {
175 return StringConverter.getInstance();
176 }
177
178 /**
179 * A converter for URL strings.
180 * @return A {@code StyleConverter} that converts a representation of a
181 * CSS URL value to a {@code String}.
182 */
183 public static StyleConverter<ParsedValue[], String> getUrlConverter() {
184 return URLConverter.getInstance();
185 }
186
187
188 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.css;
27
28 import javafx.css.converter.BooleanConverter;
29 import javafx.css.converter.ColorConverter;
30 import javafx.css.converter.DeriveColorConverter;
31 import javafx.css.converter.DeriveSizeConverter;
32 import javafx.css.converter.DurationConverter;
33 import javafx.css.converter.EffectConverter;
34 import javafx.css.converter.EnumConverter;
35 import javafx.css.converter.FontConverter;
36 import javafx.css.converter.InsetsConverter;
37 import javafx.css.converter.LadderConverter;
38 import javafx.css.converter.PaintConverter;
39 import javafx.css.converter.SizeConverter;
40 import javafx.css.converter.StopConverter;
41 import javafx.css.converter.StringConverter;
42 import javafx.css.converter.URLConverter;
43 import javafx.geometry.Insets;
44 import javafx.scene.effect.Effect;
45 import javafx.scene.paint.Color;
46 import javafx.scene.paint.Paint;
47 import javafx.scene.text.Font;
48 import javafx.util.Duration;
49
50 import com.sun.javafx.scene.layout.region.CornerRadiiConverter;
51 import com.sun.javafx.util.Logging;
52 import sun.util.logging.PlatformLogger;
53 import sun.util.logging.PlatformLogger.Level;
54
55 import java.io.DataInputStream;
56 import java.io.DataOutputStream;
57 import java.io.IOException;
58 import java.util.ArrayList;
59 import java.util.HashMap;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.WeakHashMap;
63
64
65 /**
66 * StyleConverter converts {@code ParsedValue&tl;F,T>} from type F to type T. The
67 * {@link CssMetaData} API requires a {@code StyleConverter} which is used
68 * when computing a value for the {@see StyleableProperty}. There are
69 * a number of predefined converters which are accessible by the static
70 * methods of this class.
71 *
72 * F is the type of the parsed value, T is the converted type of
73 * the ParsedValueImpl. For example, a converter from String to Color would
74 * be declared
75 * <p>
76 * <code>public Color convert(ParsedValueImpl<String,Color> value, Font font)</code>
77 * </p>
78 *
79 * @see ParsedValue
80 * @see StyleableProperty
81 * @since JavaFX 8.0
82 */
83 public class StyleConverter<F, T> {
84
85 /**
86 * Convert from the parsed CSS value to the target property type.
87 *
88 * @param value The {@link ParsedValue} to convert
89 * @param font The {@link Font} to use when converting a
90 * <a href="http://www.w3.org/TR/css3-values/#relative-lengths">relative</a>
91 * value.
92 */
93 @SuppressWarnings("unchecked")
94 public T convert(ParsedValue<F,T> value, Font font) {
95 // unchecked!
96 return (T) value.getValue();
97 }
98
195
196 /**
197 * A converter for quoted strings which may have embedded unicode characters.
198 * @return A {@code StyleConverter} that converts a representation of a
199 * CSS string value to a {@code String}.
200 */
201 public static StyleConverter<String,String> getStringConverter() {
202 return StringConverter.getInstance();
203 }
204
205 /**
206 * A converter for URL strings.
207 * @return A {@code StyleConverter} that converts a representation of a
208 * CSS URL value to a {@code String}.
209 */
210 public static StyleConverter<ParsedValue[], String> getUrlConverter() {
211 return URLConverter.getInstance();
212 }
213
214
215
216
217 /**
218 * Convert from the constituent values to the target property type.
219 * Implemented by Types that have Keys with subKeys.
220 *
221 * @since 9
222 */
223 public T convert(Map<CssMetaData<? extends Styleable, ?>,Object> convertedValues) {
224 return null;
225 }
226
227 /**
228 *
229 * @since 9
230 */
231 public void writeBinary(DataOutputStream os, StringStore sstore)
232 throws IOException {
233
234 String cname = getClass().getName();
235 int index = sstore.addString(cname);
236 os.writeShort(index);
237 }
238
239 private static Map<ParsedValue, Object> cache;
240
241 /**
242 *
243 * @since 9
244 */
245 public static void clearCache() {
246 if (cache != null) {
247 cache.clear();
248 }
249 }
250
251 /**
252 *
253 * @since 9
254 */
255 protected T getCachedValue(ParsedValue key) {
256 if (cache != null) {
257 return (T)cache.get(key);
258 }
259 return null;
260 }
261
262 /**
263 *
264 * @since 9
265 */
266 protected void cacheValue(ParsedValue key, Object value) {
267 if (cache == null) cache = new WeakHashMap<>();
268 cache.put(key, value);
269 }
270
271 // map of StyleConverter class name to StyleConverter
272 private static Map<String,StyleConverter<?, ?>> tmap;
273
274 /**
275 *
276 * @since 9
277 */
278 @SuppressWarnings("rawtypes")
279 public static StyleConverter<?,?> readBinary(DataInputStream is, String[] strings)
280 throws IOException {
281
282 int index = is.readShort();
283 String cname = strings[index];
284
285 if (cname == null || cname.isEmpty()) return null;
286
287 if (cname.startsWith("com.sun.javafx.css.converters.")) {
288 // JavaFX 9: converter classes were moved from
289 // com.sun.javafx.css.converters.* to javafx.css.converter.*
290 // Note: the word 'converters' has become 'converter'.
291 cname = "javafx.css.converter." + cname.substring("com.sun.javafx.css.converters.".length());
292 }
293 if (cname.startsWith("javafx.css.converter.EnumConverter")) {
294 return (StyleConverter)javafx.css.converter.EnumConverter.readBinary(is, strings);
295 }
296
297 // Make a new entry in tmap, if necessary
298 if (tmap == null || !tmap.containsKey(cname)) {
299 StyleConverter<?,?> converter = getInstance(cname);
300 if (converter == null) {
301 final PlatformLogger logger = Logging.getCSSLogger();
302 if (logger.isLoggable(Level.SEVERE)) {
303 logger.severe("could not deserialize " + cname);
304 }
305 }
306 if (converter == null) {
307 System.err.println("could not deserialize " + cname);
308 }
309 if (tmap == null) tmap = new HashMap<String,StyleConverter<?,?>>();
310 tmap.put(cname, converter);
311 return converter;
312 }
313 return tmap.get(cname);
314 }
315
316 // package for unit test purposes
317 static StyleConverter<?,?> getInstance(final String converterClass) {
318
319 StyleConverter<?,?> styleConverter = null;
320
321 switch(converterClass) {
322 case "javafx.css.converter.BooleanConverter" :
323 styleConverter = javafx.css.converter.BooleanConverter.getInstance();
324 break;
325 case "javafx.css.converter.ColorConverter" :
326 styleConverter = javafx.css.converter.ColorConverter.getInstance();
327 break;
328 case "javafx.css.converter.CursorConverter" :
329 styleConverter = javafx.css.converter.CursorConverter.getInstance();
330 break;
331 case "javafx.css.converter.EffectConverter" :
332 styleConverter = javafx.css.converter.EffectConverter.getInstance();
333 break;
334 case "javafx.css.converter.EffectConverter$DropShadowConverter" :
335 styleConverter = javafx.css.converter.EffectConverter.DropShadowConverter.getInstance();
336 break;
337 case "javafx.css.converter.EffectConverter$InnerShadowConverter" :
338 styleConverter = javafx.css.converter.EffectConverter.InnerShadowConverter.getInstance();
339 break;
340 case "javafx.css.converter.FontConverter" :
341 styleConverter = javafx.css.converter.FontConverter.getInstance();
342 break;
343 case "javafx.css.converter.FontConverter$FontStyleConverter" :
344 case "javafx.css.converter.FontConverter$StyleConverter" :
345 styleConverter = javafx.css.converter.FontConverter.FontStyleConverter.getInstance();
346 break;
347 case "javafx.css.converter.FontConverter$FontWeightConverter" :
348 case "javafx.css.converter.FontConverter$WeightConverter" :
349 styleConverter = javafx.css.converter.FontConverter.FontWeightConverter.getInstance();
350 break;
351 case "javafx.css.converter.FontConverter$FontSizeConverter" :
352 case "javafx.css.converter.FontConverter$SizeConverter" :
353 styleConverter = javafx.css.converter.FontConverter.FontSizeConverter.getInstance();
354 break;
355
356 case "javafx.css.converter.InsetsConverter" :
357 styleConverter = javafx.css.converter.InsetsConverter.getInstance();
358 break;
359 case "javafx.css.converter.InsetsConverter$SequenceConverter" :
360 styleConverter = javafx.css.converter.InsetsConverter.SequenceConverter.getInstance();
361 break;
362
363 case "javafx.css.converter.PaintConverter" :
364 styleConverter = javafx.css.converter.PaintConverter.getInstance();
365 break;
366 case "javafx.css.converter.PaintConverter$SequenceConverter" :
367 styleConverter = javafx.css.converter.PaintConverter.SequenceConverter.getInstance();
368 break;
369 case "javafx.css.converter.PaintConverter$LinearGradientConverter" :
370 styleConverter = javafx.css.converter.PaintConverter.LinearGradientConverter.getInstance();
371 break;
372 case "javafx.css.converter.PaintConverter$RadialGradientConverter" :
373 styleConverter = javafx.css.converter.PaintConverter.RadialGradientConverter.getInstance();
374 break;
375
376 case "javafx.css.converter.SizeConverter" :
377 styleConverter = javafx.css.converter.SizeConverter.getInstance();
378 break;
379 case "javafx.css.converter.SizeConverter$SequenceConverter" :
380 styleConverter = javafx.css.converter.SizeConverter.SequenceConverter.getInstance();
381 break;
382
383 case "javafx.css.converter.StringConverter" :
384 styleConverter = javafx.css.converter.StringConverter.getInstance();
385 break;
386 case "javafx.css.converter.StringConverter$SequenceConverter" :
387 styleConverter = javafx.css.converter.StringConverter.SequenceConverter.getInstance();
388 break;
389 case "javafx.css.converter.URLConverter" :
390 styleConverter = javafx.css.converter.URLConverter.getInstance();
391 break;
392 case "javafx.css.converter.URLConverter$SequenceConverter" :
393 styleConverter = javafx.css.converter.URLConverter.SequenceConverter.getInstance();
394 break;
395
396 // Region stuff - including 2.x class names
397 case "com.sun.javafx.scene.layout.region.BackgroundPositionConverter" :
398 case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundPositionConverter" :
399 styleConverter = com.sun.javafx.scene.layout.region.BackgroundPositionConverter.getInstance();
400 break;
401 case "com.sun.javafx.scene.layout.region.BackgroundSizeConverter" :
402 case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundSizeConverter" :
403 styleConverter = com.sun.javafx.scene.layout.region.BackgroundSizeConverter.getInstance();
404 break;
405 case "com.sun.javafx.scene.layout.region.BorderImageSliceConverter" :
406 case "com.sun.javafx.scene.layout.region.BorderImage$SliceConverter" :
407 styleConverter = com.sun.javafx.scene.layout.region.BorderImageSliceConverter.getInstance();
408 break;
409 case "com.sun.javafx.scene.layout.region.BorderImageWidthConverter" :
410 styleConverter = com.sun.javafx.scene.layout.region.BorderImageWidthConverter.getInstance();
411 break;
412 case "com.sun.javafx.scene.layout.region.BorderImageWidthsSequenceConverter" :
413 styleConverter = com.sun.javafx.scene.layout.region.BorderImageWidthsSequenceConverter.getInstance();
414 break;
415 case "com.sun.javafx.scene.layout.region.BorderStrokeStyleSequenceConverter" :
416 case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderStyleSequenceConverter" :
417 styleConverter = com.sun.javafx.scene.layout.region.BorderStrokeStyleSequenceConverter.getInstance();
418 break;
419 case "com.sun.javafx.scene.layout.region.BorderStyleConverter" :
420 case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderStyleConverter" :
421 styleConverter = com.sun.javafx.scene.layout.region.BorderStyleConverter.getInstance();
422 break;
423 case "com.sun.javafx.scene.layout.region.LayeredBackgroundPositionConverter" :
424 case "com.sun.javafx.scene.layout.region.BackgroundImage$LayeredBackgroundPositionConverter" :
425 styleConverter = com.sun.javafx.scene.layout.region.LayeredBackgroundPositionConverter.getInstance();
426 break;
427 case "com.sun.javafx.scene.layout.region.LayeredBackgroundSizeConverter" :
428 case "com.sun.javafx.scene.layout.region.BackgroundImage$LayeredBackgroundSizeConverter" :
429 styleConverter = com.sun.javafx.scene.layout.region.LayeredBackgroundSizeConverter.getInstance();
430 break;
431 case "com.sun.javafx.scene.layout.region.LayeredBorderPaintConverter" :
432 case "com.sun.javafx.scene.layout.region.StrokeBorder$LayeredBorderPaintConverter" :
433 styleConverter = com.sun.javafx.scene.layout.region.LayeredBorderPaintConverter.getInstance();
434 break;
435 case "com.sun.javafx.scene.layout.region.LayeredBorderStyleConverter" :
436 case "com.sun.javafx.scene.layout.region.StrokeBorder$LayeredBorderStyleConverter" :
437 styleConverter = com.sun.javafx.scene.layout.region.LayeredBorderStyleConverter.getInstance();
438 break;
439 case "com.sun.javafx.scene.layout.region.RepeatStructConverter" :
440 case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundRepeatConverter" :
441 case "com.sun.javafx.scene.layout.region.BorderImage$RepeatConverter" :
442 styleConverter = com.sun.javafx.scene.layout.region.RepeatStructConverter.getInstance();
443 break;
444 case "com.sun.javafx.scene.layout.region.SliceSequenceConverter" :
445 case "com.sun.javafx.scene.layout.region.BorderImage$SliceSequenceConverter" :
446 styleConverter = com.sun.javafx.scene.layout.region.SliceSequenceConverter.getInstance();
447 break;
448 case "com.sun.javafx.scene.layout.region.StrokeBorderPaintConverter" :
449 case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderPaintConverter" :
450 styleConverter = com.sun.javafx.scene.layout.region.StrokeBorderPaintConverter.getInstance();
451 break;
452 case "com.sun.javafx.scene.layout.region.Margins$Converter" :
453 styleConverter = com.sun.javafx.scene.layout.region.Margins.Converter.getInstance();
454 break;
455 case "com.sun.javafx.scene.layout.region.Margins$SequenceConverter" :
456 styleConverter = com.sun.javafx.scene.layout.region.Margins.SequenceConverter.getInstance();
457 break;
458 case "javafx.scene.layout.CornerRadiiConverter" : // Fix for RT-39665
459 case "com.sun.javafx.scene.layout.region.CornerRadiiConverter" :
460 styleConverter = CornerRadiiConverter.getInstance();
461 break;
462
463 // parser stuff
464 case "javafx.css.converter.DeriveColorConverter":
465 case "com.sun.javafx.css.parser.DeriveColorConverter" :
466 styleConverter = DeriveColorConverter.getInstance();
467 break;
468 case "javafx.css.converter.DeriveSizeConverter":
469 case "com.sun.javafx.css.parser.DeriveSizeConverter" :
470 styleConverter = DeriveSizeConverter.getInstance();
471 break;
472 case "javafx.css.converter.LadderConverter":
473 case "com.sun.javafx.css.parser.LadderConverter" :
474 styleConverter = LadderConverter.getInstance();
475 break;
476 case "javafx.css.converter.StopConverter":
477 case "com.sun.javafx.css.parser.StopConverter" :
478 styleConverter = StopConverter.getInstance();
479 break;
480
481 default :
482 final PlatformLogger logger = Logging.getCSSLogger();
483 if (logger.isLoggable(Level.SEVERE)) {
484 logger.severe("StyleConverter : converter Class is null for : "+converterClass);
485 }
486 break;
487 }
488
489 return styleConverter;
490 }
491
492
493 /**
494 *
495 * @since 9
496 */
497 public static class StringStore {
498 private final Map<String,Integer> stringMap = new HashMap<String,Integer>();
499 public final List<String> strings = new ArrayList<String>();
500
501 public int addString(String s) {
502 Integer index = stringMap.get(s);
503 if (index == null) {
504 index = strings.size();
505 strings.add(s);
506 stringMap.put(s,index);
507 }
508 return index;
509 }
510
511 public void writeBinary(DataOutputStream os) throws IOException {
512 os.writeShort(strings.size());
513 if (stringMap.containsKey(null)) {
514 Integer index = stringMap.get(null);
515 os.writeShort(index);
516 } else {
517 os.writeShort(-1);
518 }
519 for (int n=0; n<strings.size(); n++) {
520 String s = strings.get(n);
521 if (s == null) continue;
522 os.writeUTF(s);
523 }
524 }
525
526 // TODO: this isn't parallel with writeBinary
527 public static String[] readBinary(DataInputStream is) throws IOException {
528 int nStrings = is.readShort();
529 int nullIndex = is.readShort();
530 String[] strings = new String[nStrings];
531 java.util.Arrays.fill(strings, null);
532 for (int n=0; n<nStrings; n++) {
533 if (n == nullIndex) continue;
534 strings[n] = is.readUTF();
535 }
536 return strings;
537 }
538 }
539 }
|