Fandom

Planet JFX

Sweet Button

118pages on
this wiki
Add New Page
Talk0 Share

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Summary Edit

This code is based on the SweetBox code, and adds centered text, rollover, and press effects.

Code Edit


import java.lang.*;
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
};

public class SizeableText
extends Text
{
  operation getBounds();
}

/**
Allows access to a protected variable in the parent class.
*/
operation SizeableText.getBounds()
{
  return this.bounds;
}

class SweetButton
extends CompositeNode
{
  public attribute text: String;
  public attribute fontFace: Font;
  public attribute fontColor: Color;
  
  public attribute color: Color;
  private attribute darkerColor: Color;
  private attribute lighterColor: Color;
  
  public attribute roundness: Number;
  public attribute inset: Number;
  public attribute x: Number;
  public attribute y: Number;
  public attribute w: Number;
  public attribute h: Number;
  
  private attribute _text: SizeableText;
  
  public attribute haloColor: Color;
  private attribute haloOffset: Number;
  private attribute haloOpacity: Number;
  private attribute storedHaloOpacity: Number;
  private attribute maxHaloOpacity: Number;
  
  public attribute onClickHaloColor: Color;
  private attribute onClickHaloOpacity: Number;
  
  public operation frame(x:Number, y: Number, w:Number, h:Number);
  public operation centerText();
  public operation getTextCenterY() : Number;
  public operation getTextCenterX() : Number;
  
  public operation onMouseEntered(e:CanvasMouseEvent);
  public operation onMouseExited(e:CanvasMouseEvent);
  public operation onMousePressed(e:CanvasMouseEvent);
  public operation onMouseReleased(e:CanvasMouseEvent);
  public operation onMouseClicked(e:CanvasMouseEvent);
  
  private operation doMouseEntered(e:CanvasMouseEvent);
  private operation doMouseExited(e:CanvasMouseEvent);
  private operation doMousePressed(e:CanvasMouseEvent);
  private operation doMouseReleased(e:CanvasMouseEvent);
  private operation doMouseClicked(e:CanvasMouseEvent);
}

attribute SweetButton.text = "";
attribute SweetButton.inset = 1;
attribute SweetButton.roundness = 1;
attribute SweetButton.w = 200;
attribute SweetButton.h = 40;
attribute SweetButton.fontFace = Font { face: VERDANA, size: 15 };
attribute SweetButton.fontColor = white;
attribute SweetButton.color = black;
attribute SweetButton.darkerColor = darker( color, 0.5  );
attribute SweetButton.lighterColor = lighter( color, 0.8  );
attribute SweetButton.haloColor = new Color( 1, 1, 1, 0.25);
attribute SweetButton.haloOffset = 2;
attribute SweetButton.haloOpacity = 0;
attribute SweetButton.storedHaloOpacity = 0;
attribute SweetButton.onClickHaloColor = new Color( 1, 1, 1, 0.25);
attribute SweetButton.onClickHaloOpacity = 0;

attribute SweetButton._text = SizeableText
{
  x: getTextCenterX()
  y: getTextCenterY()
  content: bind text
  font: bind fontFace
  fill: bind fontColor
};

trigger on SweetButton.color = newValue
{
  darkerColor = darker( color, 0.5  );
  lighterColor = lighter( color, 0.8  );
}

trigger on SweetButton.text = newValue
{
  centerText();
}

trigger on SweetButton._text = newValue
{
  centerText();
}

trigger on SweetButton.fontFace = newValue
{
  centerText();
}

trigger on SweetButton.w = newValue
{
  centerText();
}

trigger on SweetButton.h = newValue
{
  centerText();
}

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

operation SweetButton.centerText()
{
  _text.y = getTextCenterY();
  _text.x = getTextCenterX();
}

operation SweetButton.getTextCenterY() : Number
{
  var boxHeight = this.h;
  var textY = ( ( boxHeight - _text.getBounds().height ) / 2 );
  textY += this.y;
  return textY;
}

operation SweetButton.getTextCenterX() : Number
{
  var boxWidth = this.w;
  var textX = ( ( boxWidth - _text.getBounds().width ) / 2 );
  textX += this.x;
  return textX;
}

operation SweetButton.doMouseEntered(e:CanvasMouseEvent)
{
  if( onClickHaloOpacity == 0 )
  {
    haloOpacity = 1;
  }
  else
  {
    storedHaloOpacity = 1;
  }
  
  //forward this to any subclasses
  onMouseEntered(e);
}
operation SweetButton.doMouseExited(e:CanvasMouseEvent)
{
  haloOpacity = 0;
  storedHaloOpacity = 0;
  
  //forward this to any subclasses
  onMouseExited(e);
}

operation SweetButton.doMousePressed(e:CanvasMouseEvent)
{
  storedHaloOpacity = haloOpacity;
  haloOpacity = 0;
  onClickHaloOpacity = 1;
  
  //forward this to any subclasses
  onMousePressed(e);
}

operation SweetButton.doMouseReleased(e:CanvasMouseEvent)
{
  onClickHaloOpacity = 0;
  haloOpacity = storedHaloOpacity;
  
  //forward this to any subclasses
  onMouseReleased(e);
}

operation SweetButton.doMouseClicked(e:CanvasMouseEvent)
{
  //forward this to any subclasses
  onMouseClicked(e);
}

function SweetButton.composeNode() =
Group
{
  content:
  [
    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: bind darkerColor },
            Stop { offset: 1.0 color: bind color }
            ]
            spreadMethod: PAD
          }
          
          onMouseEntered: operation(e:CanvasMouseEvent)
          {
            doMouseEntered(e);
          }
          
          onMouseExited: operation(e:CanvasMouseEvent)
          {
            doMouseExited(e);
          }
          
          onMousePressed: operation(e:CanvasMouseEvent)
          {
            doMousePressed(e);
          }
          
          onMouseReleased: operation(e:CanvasMouseEvent)
          {
            doMouseReleased(e);
          }
          
          onMouseClicked: operation(e:CanvasMouseEvent)
          {
            doMouseClicked(e);
          }
        },
        
        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: bind lighterColor }
              ]
              spreadMethod: PAD
            }
          }
        },
        
        Rect
        {
          x: bind x + haloOffset
          y: bind y + haloOffset
          width: bind w
          height: bind h
          arcHeight: bind roundness * h
          arcWidth: bind roundness * h
          fill: bind haloColor
          opacity: bind haloOpacity
        },
        
        Rect
        {
          x: bind x + haloOffset
          y: bind y + haloOffset
          width: bind w
          height: bind h
          arcHeight: bind roundness * h
          arcWidth: bind roundness * h
          stroke: bind onClickHaloColor
          strokeWidth: 2
          opacity: bind onClickHaloOpacity
        },
      ]
    },
    
    _text
  ]
};

/*
This is an anoying hack.  I can't figure out how to get the mouse events
I need to know that this button has been hovered over,pressed, etc 
without eating the events that let me know it's been clicked.  For
some reason, this subclass works fine.
*/
class ClickedButton
extends SweetButton
{
}

attribute ClickedButton.text = "I'm a button!";
attribute ClickedButton.x = 25;
attribute ClickedButton.y = 25;
attribute ClickedButton.fontFace = Font { face: VERDANA, size: 24 };
operation ClickedButton.onMouseClicked(e:CanvasMouseEvent)
{
  System.out.println("Click!");
}

var sweetButton = ClickedButton;

var frame = Frame
{
  title: "Sweet Button"
  height: 500
  width: 500
  
  content: Canvas
  {
    background: new Color( 0.3, 0.3, 0.3, 1 )
    content: sweetButton
  }
  
  centerOnScreen: true
  visible: true
};

/*
Anoying hack #2: text can only be centered after the element is visible; adding
this to the on new trigger, etc, does nothing.
*/
sweetButton.centerText();


SweetButton

Note that this code is not designed to run in the JvaFX Tutorial window, but as a standalone app.

The event model is somewhat flawed, necessitating a subclass to detect mouse clicks.

The painting code also needs work; as it stands, text can only be entered after the component has been made visible.

Also on Fandom

Random Wiki