2 package org.forester.phylogeny.data;
\r
4 import java.awt.Color;
\r
5 import java.awt.Font;
\r
6 import java.io.IOException;
\r
7 import java.io.Writer;
\r
8 import java.util.ArrayList;
\r
9 import java.util.List;
\r
11 import org.forester.phylogeny.data.Property.AppliesTo;
\r
12 import org.forester.util.ForesterUtil;
\r
14 public final class NodeVisualData implements PhylogenyData {
\r
16 public static final String APTX_VISUALIZATION_REF = "style:";
\r
17 public static final String FONT_COLOR_REF = APTX_VISUALIZATION_REF + "font_color";
\r
18 public static final String FONT_COLOR_TYPE = "xsd:token";
\r
19 public static final String FONT_REF = APTX_VISUALIZATION_REF + "font";
\r
20 public static final String FONT_SIZE_REF = APTX_VISUALIZATION_REF + "font_size";
\r
21 public static final String FONT_SIZE_TYPE = "xsd:unsignedByte";
\r
22 public static final String FONT_STYLE_BOLD = "bold";
\r
23 public static final String FONT_STYLE_BOLD_ITALIC = "bold_italic";
\r
24 public static final String FONT_STYLE_ITALIC = "italic";
\r
25 public static final String FONT_STYLE_PLAIN = "plain";
\r
26 public static final String FONT_STYLE_REF = APTX_VISUALIZATION_REF + "font_style";
\r
27 public static final String FONT_STYLE_TYPE = "xsd:token";
\r
28 public static final String FONT_TYPE = "xsd:token";
\r
29 public static final String NODE_BORDER_COLOR_REF = APTX_VISUALIZATION_REF + "node_border_color";
\r
30 public static final String NODE_BORDER_COLOR_TYPE = "xsd:token";
\r
31 public static final String NODE_FILL_COLOR_REF = APTX_VISUALIZATION_REF + "node_fill_color";
\r
32 public static final String NODE_FILL_COLOR_TYPE = "xsd:token";
\r
33 public static final String NODE_FILL_GRADIENT = "gradient";
\r
34 public static final String NODE_FILL_NONE = "none";
\r
35 public static final String NODE_FILL_SOLID = "solid";
\r
36 public static final String NODE_FILL_TYPE_REF = APTX_VISUALIZATION_REF + "node_fill_type";
\r
37 public static final String NODE_FILL_TYPE_TYPE = "xsd:token";
\r
38 public static final String NODE_SHAPE_CIRCLE = "cicle";
\r
39 public static final String NODE_SHAPE_RECTANGLE = "rectangle";
\r
40 public static final String NODE_SHAPE_REF = APTX_VISUALIZATION_REF + "node_shape";
\r
41 public static final String NODE_SHAPE_TYPE = "xsd:token";
\r
42 public static final String NODE_SIZE_REF = APTX_VISUALIZATION_REF + "node_size";
\r
43 public static final String NODE_SIZE_TYPE = "xsd:float";
\r
44 public static final String NODE_TRANSPARENCY_REF = APTX_VISUALIZATION_REF + "node_transparency";
\r
45 public static final String NODE_TRANSPARENCY_TYPE = "xsd:float";
\r
46 private static final byte DEFAULT_FONT_SIZE = -1;
\r
47 private static final int DEFAULT_SIZE = -1;
\r
48 private static final int DEFAULT_TRANSPARENCY = -1;
\r
49 private Color _border_color;
\r
50 private Color _fill_color;
\r
51 private NodeFill _fill_type;
\r
53 private Color _font_color;
\r
54 private String _font_name;
\r
55 private byte _font_size;
\r
56 private FontType _font_style;
\r
57 private NodeShape _shape;
\r
58 private float _size;
\r
59 private float _transparency;
\r
61 public NodeVisualData() {
\r
65 public NodeVisualData( final String font_name,
\r
66 final FontType font_style,
\r
67 final byte font_size,
\r
68 final Color font_color,
\r
69 final NodeShape shape,
\r
70 final NodeFill fill_type,
\r
71 final Color border_color,
\r
72 final Color fill_color,
\r
74 final float transparency ) {
\r
75 setFontName( font_name );
\r
76 setFontStyle( font_style );
\r
77 setFontSize( font_size );
\r
78 setFontColor( font_color );
\r
80 setFillType( fill_type );
\r
81 setBorderColor( border_color );
\r
82 setFillColor( fill_color );
\r
84 setTransparency( transparency );
\r
88 public final StringBuffer asSimpleText() {
\r
93 public final StringBuffer asText() {
\r
94 final StringBuffer sb = new StringBuffer();
\r
99 public final PhylogenyData copy() {
\r
100 return new NodeVisualData( !ForesterUtil.isEmpty( getFontName() ) ? new String( getFontName() ) : null,
\r
103 getFontColor() != null ? new Color( getFontColor().getRed(), getFontColor()
\r
104 .getGreen(), getFontColor().getBlue() ) : null,
\r
107 getBorderColor() != null ? new Color( getBorderColor().getRed(), getBorderColor()
\r
108 .getGreen(), getBorderColor().getBlue() ) : null,
\r
109 getFillColor() != null ? new Color( getFillColor().getRed(), getFillColor()
\r
110 .getGreen(), getFillColor().getBlue() ) : null,
\r
112 getTransparency() );
\r
115 public final Color getBorderColor() {
\r
116 return _border_color;
\r
119 public final Color getFillColor() {
\r
120 return _fill_color;
\r
123 public final NodeFill getFillType() {
\r
127 public final Font getFont() {
\r
128 if ( _font != null ) {
\r
131 else if ( !ForesterUtil.isEmpty( getFontName() ) ) {
\r
132 _font = new Font( getFontName(), getFontStyleInt(), getFontSize() );
\r
138 public final Color getFontColor() {
\r
139 return _font_color;
\r
142 public final String getFontName() {
\r
146 public final byte getFontSize() {
\r
150 public final FontType getFontStyle() {
\r
151 return _font_style;
\r
154 public final int getFontStyleInt() {
\r
155 if ( getFontStyle() == FontType.BOLD ) {
\r
158 else if ( getFontStyle() == FontType.ITALIC ) {
\r
159 return Font.ITALIC;
\r
161 else if ( getFontStyle() == FontType.BOLD_ITALIC ) {
\r
162 return Font.BOLD + Font.ITALIC;
\r
167 public final NodeShape getShape() {
\r
171 public final float getSize() {
\r
175 public final float getTransparency() {
\r
176 return _transparency;
\r
179 public final boolean isEmpty() {
\r
180 return ( ForesterUtil.isEmpty( getFontName() ) && ( getFontStyle() == FontType.PLAIN )
\r
181 && ( getFontSize() == DEFAULT_FONT_SIZE ) && ( getFontColor() == null )
\r
182 && ( getShape() == NodeShape.DEFAULT ) && ( getFillType() == NodeFill.DEFAULT )
\r
183 && ( getBorderColor() == null ) && ( getFillColor() == null ) && ( getSize() == DEFAULT_SIZE ) && ( getTransparency() == DEFAULT_TRANSPARENCY ) );
\r
187 public final boolean isEqual( final PhylogenyData data ) {
\r
188 throw new UnsupportedOperationException();
\r
191 public void parseProperty( final Property prop ) {
\r
192 if ( prop.getRef().equals( FONT_REF ) ) {
\r
193 setFontName( prop.getValue().trim() );
\r
195 else if ( prop.getRef().equals( FONT_SIZE_REF ) ) {
\r
198 s = Integer.parseInt( prop.getValue() );
\r
200 catch ( final NumberFormatException e ) {
\r
203 if ( ( s >= 0 ) && ( s < Byte.MAX_VALUE ) ) {
\r
207 else if ( prop.getRef().equals( FONT_STYLE_REF ) ) {
\r
208 setFontStyle( prop.getValue() );
\r
210 else if ( prop.getRef().equals( FONT_COLOR_REF ) ) {
\r
212 setFontColor( Color.decode( prop.getValue() ) );
\r
214 catch ( final NumberFormatException e ) {
\r
219 else if ( prop.getRef().equals( NODE_SIZE_REF ) ) {
\r
222 s = Integer.parseInt( prop.getValue() );
\r
224 catch ( final NumberFormatException e ) {
\r
231 else if ( prop.getRef().equals( NODE_FILL_COLOR_REF ) ) {
\r
233 setFillColor( Color.decode( prop.getValue() ) );
\r
235 catch ( final NumberFormatException e ) {
\r
239 else if ( prop.getRef().equals( NODE_BORDER_COLOR_REF ) ) {
\r
241 setBorderColor( Color.decode( prop.getValue() ) );
\r
243 catch ( final NumberFormatException e ) {
\r
247 else if ( prop.getRef().equals( NODE_SHAPE_REF ) ) {
\r
249 setShape( prop.getValue() );
\r
251 catch ( final NumberFormatException e ) {
\r
257 public final void setBorderColor( final Color border_color ) {
\r
258 _border_color = border_color;
\r
261 public final void setFillColor( final Color fill_color ) {
\r
262 _fill_color = fill_color;
\r
265 public final void setFillType( final NodeFill fill_type ) {
\r
266 _fill_type = fill_type;
\r
269 public final void setFontColor( final Color font_color ) {
\r
270 _font_color = font_color;
\r
273 public final void setFontName( final String font_name ) {
\r
274 if ( !ForesterUtil.isEmpty( font_name ) ) {
\r
275 _font_name = font_name;
\r
283 public final void setFontSize( final int font_size ) {
\r
284 if ( ( font_size != DEFAULT_FONT_SIZE ) && ( font_size < 0 ) ) {
\r
285 throw new IllegalArgumentException( "negative font size: " + font_size );
\r
287 else if ( font_size > Byte.MAX_VALUE ) {
\r
288 throw new IllegalArgumentException( "font size is too large: " + font_size );
\r
290 _font_size = ( byte ) font_size;
\r
294 public final void setFontStyle( final FontType font_style ) {
\r
295 _font_style = font_style;
\r
299 public final void setFontStyle( final int font_style ) {
\r
300 if ( ( font_style == ( Font.BOLD + Font.ITALIC ) ) ) {
\r
301 setFontStyle( FontType.BOLD_ITALIC );
\r
303 else if ( font_style == Font.ITALIC ) {
\r
304 setFontStyle( FontType.ITALIC );
\r
306 else if ( font_style == Font.BOLD ) {
\r
307 setFontStyle( FontType.BOLD );
\r
310 setFontStyle( FontType.PLAIN );
\r
314 public final void setFontStyle( final String font_style ) {
\r
315 if ( font_style.equalsIgnoreCase( FONT_STYLE_BOLD ) ) {
\r
316 setFontStyle( FontType.BOLD );
\r
318 else if ( font_style.equalsIgnoreCase( FONT_STYLE_ITALIC ) ) {
\r
319 setFontStyle( FontType.ITALIC );
\r
321 else if ( font_style.equalsIgnoreCase( FONT_STYLE_BOLD_ITALIC ) ) {
\r
322 setFontStyle( FontType.BOLD_ITALIC );
\r
325 setFontStyle( FontType.PLAIN );
\r
329 public final void setShape( final NodeShape shape ) {
\r
333 public final void setShape( final String shape ) {
\r
334 if ( shape.equalsIgnoreCase( NODE_SHAPE_CIRCLE ) ) {
\r
335 setShape( NodeShape.CIRCLE );
\r
337 else if ( shape.equalsIgnoreCase( NODE_SHAPE_RECTANGLE ) ) {
\r
338 setShape( NodeShape.RECTANGLE );
\r
341 setShape( NodeShape.DEFAULT );
\r
345 public final void setSize( final float size ) {
\r
346 if ( ( size != DEFAULT_SIZE ) && ( size < 0 ) ) {
\r
347 throw new IllegalArgumentException( "negative size: " + size );
\r
352 public final void setTransparency( final float transparency ) {
\r
353 _transparency = transparency;
\r
357 public final StringBuffer toNHX() {
\r
358 throw new UnsupportedOperationException();
\r
362 public final void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
\r
363 for( final Property p : toProperties() ) {
\r
364 p.toPhyloXML( writer, level, indentation );
\r
369 public final String toString() {
\r
370 return asText().toString();
\r
373 private String colorToHex( final Color c ) {
\r
374 return String.format( "#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue() );
\r
377 private final void init() {
\r
378 setFontName( null );
\r
379 setFontStyle( FontType.PLAIN );
\r
380 setFontSize( DEFAULT_FONT_SIZE );
\r
381 setFontColor( null );
\r
382 setShape( NodeShape.DEFAULT );
\r
383 setFillType( NodeFill.DEFAULT );
\r
384 setBorderColor( null );
\r
385 setFillColor( null );
\r
386 setSize( DEFAULT_SIZE );
\r
387 setTransparency( DEFAULT_TRANSPARENCY );
\r
391 private final List<Property> toProperties() {
\r
392 final List<Property> properties = new ArrayList<Property>();
\r
393 if ( !ForesterUtil.isEmpty( getFontName() ) ) {
\r
394 properties.add( new Property( FONT_REF, getFontName(), "", FONT_TYPE, AppliesTo.NODE ) );
\r
396 if ( getFontSize() != DEFAULT_FONT_SIZE ) {
\r
397 properties.add( new Property( FONT_SIZE_REF,
\r
398 String.valueOf( getFontSize() ),
\r
401 AppliesTo.NODE ) );
\r
403 if ( getFontStyle() != FontType.PLAIN ) {
\r
404 String font_style = "";
\r
405 if ( getFontStyle() == FontType.ITALIC ) {
\r
406 font_style = FONT_STYLE_ITALIC;
\r
408 else if ( getFontStyle() == FontType.BOLD ) {
\r
409 font_style = FONT_STYLE_BOLD;
\r
411 else if ( getFontStyle() == FontType.BOLD_ITALIC ) {
\r
412 font_style = FONT_STYLE_BOLD_ITALIC;
\r
415 throw new RuntimeException( "unknown font style" + getShape() );
\r
417 properties.add( new Property( FONT_STYLE_REF, font_style, "", FONT_STYLE_TYPE, AppliesTo.NODE ) );
\r
419 if ( getFontColor() != null ) {
\r
420 properties.add( new Property( FONT_COLOR_REF,
\r
421 colorToHex( getFontColor() ),
\r
424 AppliesTo.NODE ) );
\r
426 if ( getShape() != NodeShape.DEFAULT ) {
\r
427 String shape = null;
\r
428 if ( getShape() == NodeShape.RECTANGLE ) {
\r
429 shape = NODE_SHAPE_RECTANGLE;
\r
431 else if ( getShape() == NodeShape.CIRCLE ) {
\r
432 shape = NODE_SHAPE_CIRCLE;
\r
435 throw new RuntimeException( "unknown node shape" + getShape() );
\r
437 properties.add( new Property( NODE_SHAPE_REF, shape, "", NODE_SHAPE_TYPE, AppliesTo.NODE ) );
\r
439 if ( getSize() != DEFAULT_SIZE ) {
\r
440 properties.add( new Property( NODE_SIZE_REF,
\r
441 String.valueOf( getSize() ),
\r
444 AppliesTo.NODE ) );
\r
446 if ( getFillColor() != null ) {
\r
447 properties.add( new Property( NODE_FILL_COLOR_REF,
\r
448 colorToHex( getFillColor() ),
\r
450 NODE_FILL_COLOR_TYPE,
\r
451 AppliesTo.NODE ) );
\r
453 if ( getBorderColor() != null ) {
\r
454 properties.add( new Property( NODE_BORDER_COLOR_REF,
\r
455 colorToHex( getBorderColor() ),
\r
457 NODE_BORDER_COLOR_TYPE,
\r
458 AppliesTo.NODE ) );
\r
460 if ( getFillType() != NodeFill.DEFAULT ) {
\r
461 String fill = null;
\r
462 if ( getFillType() == NodeFill.GRADIENT ) {
\r
463 fill = NODE_FILL_GRADIENT;
\r
465 else if ( getFillType() == NodeFill.NONE ) {
\r
466 fill = NODE_FILL_NONE;
\r
468 else if ( getFillType() == NodeFill.SOLID ) {
\r
469 fill = NODE_FILL_SOLID;
\r
472 throw new RuntimeException( "unknown fill type " + getFillType() );
\r
474 properties.add( new Property( NODE_FILL_TYPE_REF, fill, "", NODE_FILL_TYPE_TYPE, AppliesTo.NODE ) );
\r
476 if ( getTransparency() != DEFAULT_TRANSPARENCY ) {
\r
477 properties.add( new Property( NODE_TRANSPARENCY_REF,
\r
478 String.valueOf( getTransparency() ),
\r
480 NODE_TRANSPARENCY_TYPE,
\r
481 AppliesTo.NODE ) );
\r
486 public enum FontType {
\r
487 BOLD, BOLD_ITALIC, ITALIC, PLAIN
\r
490 public enum NodeFill {
\r
491 DEFAULT, GRADIENT, NONE, SOLID
\r
494 public enum NodeShape {
\r
495 CIRCLE, DEFAULT, RECTANGLE
\r