in progress (special coloring is still true)
[jalview.git] / forester / java / src / org / forester / phylogeny / data / NodeVisualData.java
index ffeb8af..b3f4b5c 100644 (file)
@@ -13,46 +13,70 @@ import org.forester.util.ForesterUtil;
 \r
 public final class NodeVisualData implements PhylogenyData {\r
 \r
-    public static final String SIZE_REF             = "aptx_visualiation:node_size";\r
-    public static final String SIZE_TYPE            = "xsd:decimal";\r
-    private static final byte  DEFAULT_FONT_SIZE    = -1;\r
-    private static final int   DEFAULT_SIZE         = -1;\r
-    private static final int   DEFAULT_TRANSPARANCY = -1;\r
-    private Color              _border_color;\r
-    private Color              _fill_color;\r
+    public static final String APTX_VISUALIZATION_REF = "style:";\r
+    public static final int    DEFAULT_SIZE           = -1;\r
+    public static final String FONT_COLOR_REF         = APTX_VISUALIZATION_REF + "font_color";\r
+    public static final String FONT_COLOR_TYPE        = "xsd:token";\r
+    public static final String FONT_REF               = APTX_VISUALIZATION_REF + "font";\r
+    public static final String FONT_SIZE_REF          = APTX_VISUALIZATION_REF + "font_size";\r
+    public static final String FONT_SIZE_TYPE         = "xsd:unsignedByte";\r
+    public static final String FONT_STYLE_BOLD        = "bold";\r
+    public static final String FONT_STYLE_BOLD_ITALIC = "bold_italic";\r
+    public static final String FONT_STYLE_ITALIC      = "italic";\r
+    public static final String FONT_STYLE_PLAIN       = "plain";\r
+    public static final String FONT_STYLE_REF         = APTX_VISUALIZATION_REF + "font_style";\r
+    public static final String FONT_STYLE_TYPE        = "xsd:token";\r
+    public static final String FONT_TYPE              = "xsd:token";\r
+    public static final String NODE_COLOR_REF         = APTX_VISUALIZATION_REF + "node_color";\r
+    public static final String NODE_COLOR_TYPE        = "xsd:token";\r
+    public static final String NODE_FILL_GRADIENT     = "gradient";\r
+    public static final String NODE_FILL_NONE         = "none";\r
+    public static final String NODE_FILL_SOLID        = "solid";\r
+    public static final String NODE_FILL_TYPE_REF     = APTX_VISUALIZATION_REF + "node_fill_type";\r
+    public static final String NODE_FILL_TYPE_TYPE    = "xsd:token";\r
+    public static final String NODE_SHAPE_CIRCLE      = "circle";\r
+    public static final String NODE_SHAPE_RECTANGLE   = "rectangle";\r
+    public static final String NODE_SHAPE_REF         = APTX_VISUALIZATION_REF + "node_shape";\r
+    public static final String NODE_SHAPE_TYPE        = "xsd:token";\r
+    public static final String NODE_SIZE_REF          = APTX_VISUALIZATION_REF + "node_size";\r
+    public static final String NODE_SIZE_TYPE         = "xsd:float";\r
+    public static final String NODE_TRANSPARENCY_REF  = APTX_VISUALIZATION_REF + "node_transparency";\r
+    public static final String NODE_TRANSPARENCY_TYPE = "xsd:float";\r
+    private static final byte  DEFAULT_FONT_SIZE      = -1;\r
+    private static final int   DEFAULT_TRANSPARENCY   = -1;\r
     private NodeFill           _fill_type;\r
-    private String             _font;\r
+    private Font               _font;\r
     private Color              _font_color;\r
+    private String             _font_name;\r
     private byte               _font_size;\r
-    private FontType           _font_type;\r
+    private FontType           _font_style;\r
+    private Color              _node_color;\r
     private NodeShape          _shape;\r
     private float              _size;\r
-    private float              _transparancy;\r
+    private float              _transparency;\r
 \r
     public NodeVisualData() {\r
         init();\r
     }\r
 \r
-    public NodeVisualData( final String font,\r
-                           final FontType font_type,\r
+    public NodeVisualData( final String font_name,\r
+                           final FontType font_style,\r
                            final byte font_size,\r
                            final Color font_color,\r
                            final NodeShape shape,\r
                            final NodeFill fill_type,\r
-                           final Color border_color,\r
-                           final Color fill_color,\r
+                           final Color node_color,\r
                            final float size,\r
-                           final float transparancy ) {\r
-        setFont( font );\r
-        setFontType( font_type );\r
+                           final float transparency ) {\r
+        setFontName( font_name );\r
+        setFontStyle( font_style );\r
         setFontSize( font_size );\r
         setFontColor( font_color );\r
         setShape( shape );\r
         setFillType( fill_type );\r
-        setBorderColor( border_color );\r
-        setFillColor( fill_color );\r
+        setNodeColor( node_color );\r
         setSize( size );\r
-        setTransparancy( transparancy );\r
+        setTransparency( transparency );\r
     }\r
 \r
     @Override\r
@@ -68,47 +92,65 @@ public final class NodeVisualData implements PhylogenyData {
 \r
     @Override\r
     public final PhylogenyData copy() {\r
-        return new NodeVisualData( !ForesterUtil.isEmpty( getFont() ) ? new String( getFont() ) : null,\r
-                                   getFontType(),\r
+        return new NodeVisualData( !ForesterUtil.isEmpty( getFontName() ) ? new String( getFontName() ) : null,\r
+                                   getFontStyle(),\r
                                    getFontSize(),\r
                                    getFontColor() != null ? new Color( getFontColor().getRed(), getFontColor()\r
                                            .getGreen(), getFontColor().getBlue() ) : null,\r
                                    getShape(),\r
                                    getFillType(),\r
-                                   getBorderColor() != null ? new Color( getBorderColor().getRed(), getBorderColor()\r
-                                           .getGreen(), getBorderColor().getBlue() ) : null,\r
-                                   getFillColor() != null ? new Color( getFillColor().getRed(), getFillColor()\r
-                                           .getGreen(), getFillColor().getBlue() ) : null,\r
+                                   getNodeColor() != null ? new Color( getNodeColor().getRed(), getNodeColor()\r
+                                           .getGreen(), getNodeColor().getBlue() ) : null,\r
                                    getSize(),\r
-                                   getTransparancy() );\r
-    }\r
-\r
-    public final Color getBorderColor() {\r
-        return _border_color;\r
-    }\r
-\r
-    public final Color getFillColor() {\r
-        return _fill_color;\r
+                                   getTransparency() );\r
     }\r
 \r
     public final NodeFill getFillType() {\r
         return _fill_type;\r
     }\r
 \r
-    public final String getFont() {\r
-        return _font;\r
+    public final Font getFont() {\r
+        if ( _font != null ) {\r
+            return _font;\r
+        }\r
+        else if ( !ForesterUtil.isEmpty( getFontName() ) ) {\r
+            _font = new Font( getFontName(), getFontStyleInt(), getFontSize() );\r
+            return _font;\r
+        }\r
+        return null;\r
     }\r
 \r
     public final Color getFontColor() {\r
         return _font_color;\r
     }\r
 \r
+    public final String getFontName() {\r
+        return _font_name;\r
+    }\r
+\r
     public final byte getFontSize() {\r
         return _font_size;\r
     }\r
 \r
-    public final FontType getFontType() {\r
-        return _font_type;\r
+    public final FontType getFontStyle() {\r
+        return _font_style;\r
+    }\r
+\r
+    public final int getFontStyleInt() {\r
+        if ( getFontStyle() == FontType.BOLD ) {\r
+            return Font.BOLD;\r
+        }\r
+        else if ( getFontStyle() == FontType.ITALIC ) {\r
+            return Font.ITALIC;\r
+        }\r
+        else if ( getFontStyle() == FontType.BOLD_ITALIC ) {\r
+            return Font.BOLD + Font.ITALIC;\r
+        }\r
+        return Font.PLAIN;\r
+    }\r
+\r
+    public final Color getNodeColor() {\r
+        return _node_color;\r
     }\r
 \r
     public final NodeShape getShape() {\r
@@ -119,15 +161,15 @@ public final class NodeVisualData implements PhylogenyData {
         return _size;\r
     }\r
 \r
-    public final float getTransparancy() {\r
-        return _transparancy;\r
+    public final float getTransparency() {\r
+        return _transparency;\r
     }\r
 \r
     public final boolean isEmpty() {\r
-        return ( ForesterUtil.isEmpty( getFont() ) && ( getFontType() == FontType.NORMAL )\r
+        return ( ForesterUtil.isEmpty( getFontName() ) && ( getFontStyle() == FontType.PLAIN )\r
                 && ( getFontSize() == DEFAULT_FONT_SIZE ) && ( getFontColor() == null )\r
                 && ( getShape() == NodeShape.DEFAULT ) && ( getFillType() == NodeFill.DEFAULT )\r
-                && ( getBorderColor() == null ) && ( getFillColor() == null ) && ( getSize() == DEFAULT_SIZE ) && ( getTransparancy() == DEFAULT_TRANSPARANCY ) );\r
+                && ( getNodeColor() == null ) && ( getSize() == DEFAULT_SIZE ) && ( getTransparency() == DEFAULT_TRANSPARENCY ) );\r
     }\r
 \r
     @Override\r
@@ -135,24 +177,77 @@ public final class NodeVisualData implements PhylogenyData {
         throw new UnsupportedOperationException();\r
     }\r
 \r
-    public final void setBorderColor( final Color border_color ) {\r
-        _border_color = border_color;\r
-    }\r
-\r
-    public final void setFillColor( final Color fill_color ) {\r
-        _fill_color = fill_color;\r
+    public void parseProperty( final Property prop ) {\r
+        if ( prop.getRef().equals( FONT_REF ) ) {\r
+            setFontName( prop.getValue().trim() );\r
+        }\r
+        else if ( prop.getRef().equals( FONT_SIZE_REF ) ) {\r
+            int s = -1;\r
+            try {\r
+                s = Integer.parseInt( prop.getValue() );\r
+            }\r
+            catch ( final NumberFormatException e ) {\r
+                return;\r
+            }\r
+            if ( ( s >= 0 ) && ( s < Byte.MAX_VALUE ) ) {\r
+                setFontSize( s );\r
+            }\r
+        }\r
+        else if ( prop.getRef().equals( FONT_STYLE_REF ) ) {\r
+            setFontStyle( prop.getValue() );\r
+        }\r
+        else if ( prop.getRef().equals( FONT_COLOR_REF ) ) {\r
+            try {\r
+                setFontColor( Color.decode( prop.getValue() ) );\r
+            }\r
+            catch ( final NumberFormatException e ) {\r
+                return;\r
+            }\r
+        }\r
+        else if ( prop.getRef().equals( NODE_SIZE_REF ) ) {\r
+            float s = -1.0f;\r
+            try {\r
+                s = Float.parseFloat( prop.getValue() );\r
+            }\r
+            catch ( final NumberFormatException e ) {\r
+                return;\r
+            }\r
+            if ( s >= 0 ) {\r
+                setSize( s );\r
+            }\r
+        }\r
+        else if ( prop.getRef().equals( NODE_COLOR_REF ) ) {\r
+            try {\r
+                setNodeColor( Color.decode( prop.getValue() ) );\r
+            }\r
+            catch ( final NumberFormatException e ) {\r
+                return;\r
+            }\r
+        }\r
+        else if ( prop.getRef().equals( NODE_SHAPE_REF ) ) {\r
+            setShape( prop.getValue() );\r
+        }\r
+        else if ( prop.getRef().equals( NODE_FILL_TYPE_REF ) ) {\r
+            setFillType( prop.getValue() );\r
+        }\r
     }\r
 \r
     public final void setFillType( final NodeFill fill_type ) {\r
         _fill_type = fill_type;\r
     }\r
 \r
-    public final void setFont( final String font ) {\r
-        if ( !ForesterUtil.isEmpty( font ) ) {\r
-            _font = font;\r
+    public final void setFillType( final String fill ) {\r
+        if ( fill.equalsIgnoreCase( NODE_FILL_NONE ) ) {\r
+            setFillType( NodeFill.NONE );\r
+        }\r
+        else if ( fill.equalsIgnoreCase( NODE_FILL_SOLID ) ) {\r
+            setFillType( NodeFill.SOLID );\r
+        }\r
+        else if ( fill.equalsIgnoreCase( NODE_FILL_GRADIENT ) ) {\r
+            setFillType( NodeFill.GRADIENT );\r
         }\r
         else {\r
-            _font = null;\r
+            setFillType( NodeFill.DEFAULT );\r
         }\r
     }\r
 \r
@@ -160,44 +255,91 @@ public final class NodeVisualData implements PhylogenyData {
         _font_color = font_color;\r
     }\r
 \r
-    public final void setFontSize( final byte font_size ) {\r
-        _font_size = font_size;\r
+    public final void setFontName( final String font_name ) {\r
+        if ( !ForesterUtil.isEmpty( font_name ) ) {\r
+            _font_name = font_name;\r
+        }\r
+        else {\r
+            _font_name = null;\r
+        }\r
+        _font = null;\r
     }\r
 \r
-    public final void setFontType( final FontType font_type ) {\r
-        _font_type = font_type;\r
+    public final void setFontSize( final int font_size ) {\r
+        if ( ( font_size != DEFAULT_FONT_SIZE ) && ( font_size < 0 ) ) {\r
+            throw new IllegalArgumentException( "negative font size: " + font_size );\r
+        }\r
+        else if ( font_size > Byte.MAX_VALUE ) {\r
+            throw new IllegalArgumentException( "font size is too large: " + font_size );\r
+        }\r
+        _font_size = ( byte ) font_size;\r
+        _font = null;\r
     }\r
 \r
-    public final void setShape( final NodeShape shape ) {\r
-        _shape = shape;\r
+    public final void setFontStyle( final FontType font_style ) {\r
+        _font_style = font_style;\r
+        _font = null;\r
     }\r
 \r
-    public final void setSize( final float size ) {\r
-        _size = size;\r
+    public final void setFontStyle( final int font_style ) {\r
+        if ( ( font_style == ( Font.BOLD + Font.ITALIC ) ) ) {\r
+            setFontStyle( FontType.BOLD_ITALIC );\r
+        }\r
+        else if ( font_style == Font.ITALIC ) {\r
+            setFontStyle( FontType.ITALIC );\r
+        }\r
+        else if ( font_style == Font.BOLD ) {\r
+            setFontStyle( FontType.BOLD );\r
+        }\r
+        else {\r
+            setFontStyle( FontType.PLAIN );\r
+        }\r
+    }\r
+\r
+    public final void setFontStyle( final String font_style ) {\r
+        if ( font_style.equalsIgnoreCase( FONT_STYLE_BOLD ) ) {\r
+            setFontStyle( FontType.BOLD );\r
+        }\r
+        else if ( font_style.equalsIgnoreCase( FONT_STYLE_ITALIC ) ) {\r
+            setFontStyle( FontType.ITALIC );\r
+        }\r
+        else if ( font_style.equalsIgnoreCase( FONT_STYLE_BOLD_ITALIC ) ) {\r
+            setFontStyle( FontType.BOLD_ITALIC );\r
+        }\r
+        else {\r
+            setFontStyle( FontType.PLAIN );\r
+        }\r
     }\r
 \r
-    public final void setTransparancy( final float transparancy ) {\r
-        _transparancy = transparancy;\r
+    public final void setNodeColor( final Color node_color ) {\r
+        _node_color = node_color;\r
     }\r
 \r
-    public final int getFontStyle() {\r
-        if ( getFontType() == FontType.BOLD ) {\r
-            return Font.BOLD;\r
+    public final void setShape( final NodeShape shape ) {\r
+        _shape = shape;\r
+    }\r
+\r
+    public final void setShape( final String shape ) {\r
+        if ( shape.equalsIgnoreCase( NODE_SHAPE_CIRCLE ) ) {\r
+            setShape( NodeShape.CIRCLE );\r
         }\r
-        else if ( getFontType() == FontType.ITALIC ) {\r
-            return Font.ITALIC;\r
+        else if ( shape.equalsIgnoreCase( NODE_SHAPE_RECTANGLE ) ) {\r
+            setShape( NodeShape.RECTANGLE );\r
         }\r
-        else if ( getFontType() == FontType.BOLD_ITALIC ) {\r
-            return Font.BOLD & Font.ITALIC;\r
+        else {\r
+            setShape( NodeShape.DEFAULT );\r
         }\r
-        return Font.PLAIN;\r
     }\r
 \r
-    public final Font getFontObject() {\r
-        if ( !ForesterUtil.isEmpty( getFont() ) ) {\r
-            return new Font( getFont(), getFontStyle(), getFontSize() );\r
+    public final void setSize( final float size ) {\r
+        if ( ( size != DEFAULT_SIZE ) && ( size < 0 ) ) {\r
+            throw new IllegalArgumentException( "negative size: " + size );\r
         }\r
-        return null;\r
+        _size = size;\r
+    }\r
+\r
+    public final void setTransparency( final float transparency ) {\r
+        _transparency = transparency;\r
     }\r
 \r
     @Override\r
@@ -207,7 +349,9 @@ public final class NodeVisualData implements PhylogenyData {
 \r
     @Override\r
     public final void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {\r
-        throw new UnsupportedOperationException();\r
+        for( final Property p : toProperties() ) {\r
+            p.toPhyloXML( writer, level, indentation );\r
+        }\r
     }\r
 \r
     @Override\r
@@ -215,32 +359,113 @@ public final class NodeVisualData implements PhylogenyData {
         return asText().toString();\r
     }\r
 \r
+    private String colorToHex( final Color c ) {\r
+        return String.format( "#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue() );\r
+    }\r
+\r
     private final void init() {\r
-        setFont( null );\r
-        setFontType( FontType.NORMAL );\r
+        setFontName( null );\r
+        setFontStyle( FontType.PLAIN );\r
         setFontSize( DEFAULT_FONT_SIZE );\r
         setFontColor( null );\r
         setShape( NodeShape.DEFAULT );\r
         setFillType( NodeFill.DEFAULT );\r
-        setBorderColor( null );\r
-        setFillColor( null );\r
+        setNodeColor( null );\r
         setSize( DEFAULT_SIZE );\r
-        setTransparancy( DEFAULT_TRANSPARANCY );\r
+        setTransparency( DEFAULT_TRANSPARENCY );\r
+        _font = null;\r
     }\r
 \r
     private final List<Property> toProperties() {\r
         final List<Property> properties = new ArrayList<Property>();\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getSize() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getShape() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getFillType() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getTransparancy() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getFillColor() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
-        properties.add( new Property( SIZE_REF, String.valueOf( getBorderColor() ), "", SIZE_TYPE, AppliesTo.NODE ) );\r
+        if ( !ForesterUtil.isEmpty( getFontName() ) ) {\r
+            properties.add( new Property( FONT_REF, getFontName(), "", FONT_TYPE, AppliesTo.NODE ) );\r
+        }\r
+        if ( getFontSize() != DEFAULT_FONT_SIZE ) {\r
+            properties.add( new Property( FONT_SIZE_REF,\r
+                                          String.valueOf( getFontSize() ),\r
+                                          "",\r
+                                          FONT_SIZE_TYPE,\r
+                                          AppliesTo.NODE ) );\r
+        }\r
+        if ( getFontStyle() != FontType.PLAIN ) {\r
+            String font_style = "";\r
+            if ( getFontStyle() == FontType.ITALIC ) {\r
+                font_style = FONT_STYLE_ITALIC;\r
+            }\r
+            else if ( getFontStyle() == FontType.BOLD ) {\r
+                font_style = FONT_STYLE_BOLD;\r
+            }\r
+            else if ( getFontStyle() == FontType.BOLD_ITALIC ) {\r
+                font_style = FONT_STYLE_BOLD_ITALIC;\r
+            }\r
+            else {\r
+                throw new RuntimeException( "unknown font style" + getShape() );\r
+            }\r
+            properties.add( new Property( FONT_STYLE_REF, font_style, "", FONT_STYLE_TYPE, AppliesTo.NODE ) );\r
+        }\r
+        if ( getFontColor() != null ) {\r
+            properties.add( new Property( FONT_COLOR_REF,\r
+                                          colorToHex( getFontColor() ),\r
+                                          "",\r
+                                          FONT_COLOR_TYPE,\r
+                                          AppliesTo.NODE ) );\r
+        }\r
+        if ( getShape() != NodeShape.DEFAULT ) {\r
+            String shape = null;\r
+            if ( getShape() == NodeShape.RECTANGLE ) {\r
+                shape = NODE_SHAPE_RECTANGLE;\r
+            }\r
+            else if ( getShape() == NodeShape.CIRCLE ) {\r
+                shape = NODE_SHAPE_CIRCLE;\r
+            }\r
+            else {\r
+                throw new RuntimeException( "unknown node shape" + getShape() );\r
+            }\r
+            properties.add( new Property( NODE_SHAPE_REF, shape, "", NODE_SHAPE_TYPE, AppliesTo.NODE ) );\r
+        }\r
+        if ( getSize() != DEFAULT_SIZE ) {\r
+            properties.add( new Property( NODE_SIZE_REF,\r
+                                          String.valueOf( getSize() ),\r
+                                          "",\r
+                                          NODE_SIZE_TYPE,\r
+                                          AppliesTo.NODE ) );\r
+        }\r
+        if ( getNodeColor() != null ) {\r
+            properties.add( new Property( NODE_COLOR_REF,\r
+                                          colorToHex( getNodeColor() ),\r
+                                          "",\r
+                                          NODE_COLOR_TYPE,\r
+                                          AppliesTo.NODE ) );\r
+        }\r
+        if ( getFillType() != NodeFill.DEFAULT ) {\r
+            String fill = null;\r
+            if ( getFillType() == NodeFill.GRADIENT ) {\r
+                fill = NODE_FILL_GRADIENT;\r
+            }\r
+            else if ( getFillType() == NodeFill.NONE ) {\r
+                fill = NODE_FILL_NONE;\r
+            }\r
+            else if ( getFillType() == NodeFill.SOLID ) {\r
+                fill = NODE_FILL_SOLID;\r
+            }\r
+            else {\r
+                throw new RuntimeException( "unknown fill type " + getFillType() );\r
+            }\r
+            properties.add( new Property( NODE_FILL_TYPE_REF, fill, "", NODE_FILL_TYPE_TYPE, AppliesTo.NODE ) );\r
+        }\r
+        if ( getTransparency() != DEFAULT_TRANSPARENCY ) {\r
+            properties.add( new Property( NODE_TRANSPARENCY_REF,\r
+                                          String.valueOf( getTransparency() ),\r
+                                          "",\r
+                                          NODE_TRANSPARENCY_TYPE,\r
+                                          AppliesTo.NODE ) );\r
+        }\r
         return properties;\r
     }\r
 \r
     public enum FontType {\r
-        BOLD, BOLD_ITALIC, ITALIC, NORMAL\r
+        BOLD, BOLD_ITALIC, ITALIC, PLAIN\r
     }\r
 \r
     public enum NodeFill {\r