Planet JFX
Register
Advertisement

Summary

See this thread in the mailing lists.

Here is a pretty box widget. Adjust the color attribute of a SweetBox when you add it for different results.

Code Preview
Canvas {
    content: SweetBox {
        color: red
        roundness: 1
        x: 10
        y: 10
        w: 200
        h: 40
    }
}
Preview
Canvas {
    content: SweetBox {
        color: gray
        roundness: 1
        x: 10
        y: 10
        w: 200
        h: 40
    }
}

note: width and height are a bit off

Preview

Code

To work in JavaFXPad, add the following:

Canvas {
    content: SweetBox {
        color: red
        roundness: 1
        x: 10
        y: 10
        w: 200
        h: 40
    }
}

CustomNode

//new API
import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.Group;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.RadialGradient;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Stop;
import javafx.scene.paint.Color;
import javafx.scene.effect.GaussianBlur;



function lighter(c: Color, k: Number)
{
    Color
    {
        red: bind (1 - (1 - c.red) * k)
        green: bind (1 - (1 - c.green) * k)
        blue: bind (1 - (1 - c.blue) * k)
        opacity: bind c.opacity
    };
}

function darker(c: Color, k: Number) 
{
    Color
    {
        red: bind c.red * k
        green: bind c.green * k
        blue: bind c.blue * k
        opacity: bind c.opacity
    };
}
public class SweetBox extends CustomNode
{
    attribute color: Color;
    attribute roundness: Number;
    attribute inset: Number = 1;
    attribute x: Number;
    attribute y: Number;
    attribute w: Number;
    attribute h: Number;

    function frame(x:Number, y: Number, w:Number, h:Number)
    {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }
    
    public function create(): Node
    {
        Group
        {
            effect:GaussianBlur {radius: 2}
            content:
            [
                Rectangle
                {
                    x: bind x
                    y: bind y
                    width: bind w
                    height: bind h
                    arcHeight: bind roundness * h
                    arcWidth: bind roundness * h
                    fill: bind LinearGradient
                    {
                        startX: x, 
                        startY: y, 
                        endX: x, 
                        endY: y + h
                        proportional: false;
                        stops:
                        [
                            Stop {offset: 0.0 color: darker(color, 0.5)},
                            Stop {offset: 1.0 color: color}
                        ]
                        //spreadMethod: SpreadMethod.PAD
                    }
                    
                   
                        
                },
                Rectangle
                    {
                        x: bind x+inset
                        y: bind y+inset
                        width: bind w-2*inset
                        height: bind h-2*inset
                        arcHeight: bind roundness * h
                        arcWidth: bind roundness * h
                        opacity: 0.8
                        fill: bind LinearGradient
                        {
                            
                            //startX: 0, startY: 0, endX: 0, endY: 0.5
                            startX:x
                            startY:y
                            endX:x
                            endY:y + h
                            proportional: false;
                            stops:
                            [
                                Stop {offset: 0.0 color: Color.WHITE},
                                Stop {offset: 1.0 color: lighter(color, 0.8)}
                            ]
                            //spreadMethod: SpreadMethod.PAD
                        }
                         clip: Rectangle
                         {
                            x: bind x+inset
                            y: bind y+inset
                            width: bind w-2*inset
                            height: bind (h-2*inset) /2
                            arcHeight: bind roundness * h /3
                            arcWidth: bind roundness * h /3
                         }
                        
                       }
                
            ]
                    
        };
    }
    
}





    
public class Model
{
     public attribute boxColor:Color;
}

var model1 = Model{};
model1.boxColor = Color.LIME;
    
    
    Frame {
        visible: true
        stage:
            Stage
            {
                content:[SweetBox {
                    color: bind model1.boxColor
                    roundness: 1
                    x: 10
                    y: 10
                    w: 200
                    h: 40
                    }
                    ]
            }
    
    }


Rewritted with New syntax and binding.

package javafxapplication1;

import javafx.ui.*;
import javafx.ui.canvas.*;
import javafx.ui.filter.*;

//updated by devantor
function lighter(c: Color, k: Number)
{
    Color
    {
        red: bind (1 - (1 - c.red) * k)
        green: bind (1 - (1 - c.green) * k)
        blue: bind (1 - (1 - c.blue) * k)
        opacity: bind c.opacity
    };
}

function darker(c: Color, k: Number) 
{
    Color
    {
        red: bind c.red * k
        green: bind c.green * k
        blue: bind c.blue * k
        opacity: bind c.opacity
    };
}
public class SweetBox extends CompositeNode
{
    attribute color: Color;
    attribute roundness: Number;
    attribute inset: Number = 1;
    attribute x: Number;
    attribute y: Number;
    attribute w: Number;
    attribute h: Number;

    function frame(x:Number, y: Number, w:Number, h:Number)
    {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }
    
    function composeNode() 
    {
        Group
        {
            filter: GaussianBlur {radius: 2}
            content:
            [
                Rect
                {
                    x: bind x
                    y: bind y
                    width: bind w
                    height: bind h
                    arcHeight: bind roundness * h
                    arcWidth: bind roundness * h
                    fill: bind LinearGradient
                    {
                        startX: x, 
                        startY: y, 
                        endX: x, 
                        endY: y + h
                        stops:
                        [
                            Stop {offset: 0.0 color: darker(color, 0.5)},
                            Stop {offset: 1.0 color: color}
                        ]
                        spreadMethod: SpreadMethod.PAD
                    }
                },
                Clip
                {
                    shape: Rect
                    {
                        x: bind x+inset
                        y: bind y+inset
                        width: bind w-2*inset
                        height: bind (h-2*inset) /2
                        arcHeight: bind roundness * h /3
                        arcWidth: bind roundness * h /3
                    }
                    content: Rect
                    {
                        x: bind x+inset
                        y: bind y+inset
                        width: bind w-2*inset
                        height: bind h-2*inset
                        arcHeight: bind roundness * h
                        arcWidth: bind roundness * h
                        opacity: 0.8
                        fill: bind LinearGradient
                        {
                            
                            //startX: 0, startY: 0, endX: 0, endY: 0.5
                            startX:x
                            startY:y
                            endX:x
                            endY:y + h
                            stops:
                            [
                                Stop {offset: 0.0 color: Color.WHITE},
                                Stop {offset: 1.0 color: lighter(color, 0.8)}
                            ]
                            spreadMethod: SpreadMethod.PAD
                        }
                    }
                }
            ]
        };
    }
    
}
    
public class Model
{
     public attribute boxColor:Color;
}

var model1 = Model{};
    
    Canvas {
    content: [SweetBox {
        color: bind model1.boxColor
        roundness: 1
        x: 10
        y: 10
        w: 200
        h: 40
        },
        View{ content: Button {
                   text: "Press Me"
                   action: function() {
                     model1.boxColor = Color.LIME;
                   }
                 }
            },
        
    ]
}

Old version

import javafx.ui.*;
import javafx.ui.canvas.*;
import javafx.ui.filter.*;

function lighter(c: Color, k: Number) =
    Color
    {
        red: (1 - (1 - c.red) * k)
        green: (1 - (1 - c.green) * k)
        blue: (1 - (1 - c.blue) * k)
        opacity: c.opacity
    };

function darker(c: Color, k: Number) =
    Color
    {
        red: c.red * k
        green: c.green * k
        blue: c.blue * k
        opacity: c.opacity
    };

class SweetBox extends CompositeNode
{
    attribute color: Color;
    attribute roundness: Number;
    attribute inset: Number;
    attribute x: Number;
    attribute y: Number;
    attribute w: Number;
    attribute h: Number;

    operation frame(x:Number, y: Number, w:Number, h:Number);
}

attribute SweetBox.inset = 1;

operation SweetBox.frame(x:Number, y: Number, w:Number, h:Number)
{
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
}

function SweetBox.composeNode() =
    Group
    {
        filter: [GaussianBlur {radius: 2}]
        content:
        [
            Rect
            {
                x: bind x
                y: bind y
                width: bind w
                height: bind h
                arcHeight: bind roundness * h
                arcWidth: bind roundness * h
                fill: bind LinearGradient
                {
                    x1: 0, y1: 0, x2: 0, y2: 1
                    stops:
                    [
                        Stop {offset: 0.0 color: darker(color, 0.5)},
                        Stop {offset: 1.0 color: color}
                    ]
                    spreadMethod: PAD
                }
            },
            Clip
            {
                shape: Rect
                {
                    x: bind x+inset
                    y: bind y+inset
                    width: bind w-2*inset
                    height: bind (h-2*inset) /2
                    arcHeight: bind roundness * h /3
                    arcWidth: bind roundness * h /3
                }
                content: Rect
                {
                    x: bind x+inset
                    y: bind y+inset
                    width: bind w-2*inset
                    height: bind h-2*inset
                    arcHeight: bind roundness * h
                    arcWidth: bind roundness * h
                    opacity: 0.8
                    fill: bind LinearGradient
                    {
                        x1: 0, y1: 0, x2: 0, y2: 0.5
                        stops:
                        [
                            Stop {offset: 0.0 color: white},
                            Stop {offset: 1.0 color: lighter(color, 0.8)}
                        ]
                        spreadMethod: PAD
                    }
                }
            }
        ]
    };
Advertisement