Thursday, November 01, 2007

Learning WPF - Working with Brush Basics

Going through Chapter 2 of Charles Petzold's "Applications = Code + Markup" book. The RotateTheGradientOrigin code sample looks different from the example in the book because I'm leveraging F# anonymous functions, or also known as lambda functions in the functional programming circles. According to Robert Pickering in chapter 4 of the the book "Foundations of F#", all events exposes a method called Add and that its common to place the handler method inside the Add method itself.


VaryTheBackground


#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - VaryTheBackground.cs *)

type VaryTheBackground = class
inherit Window as base

val mutable brush : SolidColorBrush

new () as this = {brush=new SolidColorBrush(Colors.Black)} then
this.Title <- "Vary the Background"
this.Width <- 384.0
this.Height <- 384.0
this.Background <- this.brush


override this.OnMouseMove (args:MouseEventArgs) =
let width = this.ActualWidth
2.0 * SystemParameters.ResizeFrameVerticalBorderWidth
let height = this.ActualHeight
2.0 * SystemParameters.ResizeFrameHorizontalBorderHeight
SystemParameters.CaptionHeight
let ptMouse = args.GetPosition(this)
let ptCenter = new Point(width/2.0,height/2.0)
let vectMouse = ptMouse - ptCenter
let angle = Math.Atan2(vectMouse.Y, vectMouse.X)
let vectEllipse = new Vector (width/2.0*Math.Cos(angle),
height/2.0*Math.Sin(angle))
let ratio = vectMouse.Length/vectEllipse.Length
let byLevel:Byte = Byte.of_int(Float.to_int(255.0 * (1.0-Math.Min(1.0,ratio))))
let clr = Color.FromRgb(byLevel,byLevel,byLevel)
this.Title <- Byte.to_string(byLevel)
this.brush.Color <- clr

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new VaryTheBackground()) |> ignore
#endif

FlipThroughTheBrushes


#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Reflection
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - FlipThroughTheBrushes.cs *)
let indexcalc (keypress:Key) (props:PropertyInfo []) =
match keypress with
| Key.Up -> 1
| _ -> props.Length -1


type FlipThroughTheBrushes = class
inherit Window as base

val mutable index : int
val mutable props : PropertyInfo []

new () as this = {index=0;props=null} then
let brushtype = typeof<Brushes>
this.props <- brushtype.GetProperties(Enum.combine [BindingFlags.Public;
BindingFlags.Static ])
this.SetTitleAndBackground()

member this.SetTitleAndBackground() =
this.Title <- "Flip through the Brushes - " + this.props.[this.index].Name
this.Background <- unbox<Brush> (this.props.[this.index].GetValue(null,null))

override this.OnKeyDown (args:KeyEventArgs) =
if (args.Key = Key.Down || args.Key = Key.Up) then
this.index <- (this.index +
(indexcalc args.Key this.props)) % this.props.Length
this.SetTitleAndBackground()
base.OnKeyDown(args)

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new FlipThroughTheBrushes()) |> ignore
#endif

GradiateTheBrush

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - GradiateTheBrush.cs *)
type GradiateTheBrush = class
inherit Window as base

new () as this = {} then
this.Title <- "Gradiate the Brush"
let brush = new LinearGradientBrush(Colors.Red,
Colors.Blue,
new Point(0.0,0.0),
new Point(1.0,1.0))
this.Background <- brush

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new GradiateTheBrush()) |> ignore
#endif

AdjustTheGradient

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - AdjustTheGradient.cs *)
type AdjustTheGradient = class
inherit Window as base

val mutable brush : LinearGradientBrush

new () as this = {brush=null} then
this.Title <- "Adjust the Gradient"
this.add_SizeChanged(new SizeChangedEventHandler(this.WindowOnSizeChanged))
this.brush <- new LinearGradientBrush(Colors.Red,Colors.Blue,0.0)
this.brush.MappingMode <- BrushMappingMode.Absolute
this.Background <- this.brush

member this.WindowOnSizeChanged sender (args:SizeChangedEventArgs) =
let width = this.ActualWidth -
2.0 * SystemParameters.ResizeFrameVerticalBorderWidth
let height = this.ActualHeight -
2.0 * SystemParameters.ResizeFrameHorizontalBorderHeight
- SystemParameters.CaptionHeight
let ptCenter = new Point(width/2.0, height/2.0)
let vectDiag = new Vector(width,-height)
let mutable vectPerp = new Vector(vectDiag.Y, -vectDiag.X)
vectPerp.Normalize()
vectPerp <- vectPerp * width * height / vectDiag.Length
this.brush.StartPoint <- ptCenter + vectPerp
this.brush.EndPoint <- ptCenter - vectPerp

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new AdjustTheGradient()) |> ignore
#endif

FollowTheRainbow

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - FollowTheRainbow.cs *)

type FollowTheRainbow = class
inherit Window as base

new () as this = {} then
this.Title <- "Follow the Rainbow"
let mutable brush = new LinearGradientBrush()
brush.StartPoint <- new Point(0.0,0.0)
brush.EndPoint <- new Point (1.0,0.0)
this.Background <- brush
brush.GradientStops.Add(new GradientStop(Colors.Red, 0.0));
brush.GradientStops.Add(new GradientStop(Colors.Orange, 0.17));
brush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.33));
brush.GradientStops.Add(new GradientStop(Colors.Green, 0.5));
brush.GradientStops.Add(new GradientStop(Colors.Blue, 0.67));
brush.GradientStops.Add(new GradientStop(Colors.Indigo, 0.84));
brush.GradientStops.Add(new GradientStop(Colors.Violet, 1.0));

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new FollowTheRainbow()) |> ignore
#endif

CircleTheRainbow

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - CircleTheRainbow .cs *)

type CircleTheRainbow = class
inherit Window as base

new () as this = {} then
this.Title <- "Circle the Rainbow"
let mutable brush = new RadialGradientBrush()
this.Background <- brush
brush.GradientStops.Add(new GradientStop(Colors.Red, 0.0));
brush.GradientStops.Add(new GradientStop(Colors.Orange, 0.17));
brush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.33));
brush.GradientStops.Add(new GradientStop(Colors.Green, 0.5));
brush.GradientStops.Add(new GradientStop(Colors.Blue, 0.67));
brush.GradientStops.Add(new GradientStop(Colors.Indigo, 0.84));
brush.GradientStops.Add(new GradientStop(Colors.Violet, 1.0));

end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new CircleTheRainbow ()) |> ignore
#endif

ClickTheGradientCenter

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media

(* From Chap 2 - ClickTheGradientCenter .cs *)

type ClickTheGradientCenter = class
inherit Window as base

val mutable brush : RadialGradientBrush

new () as this = {brush=null} then
this.Title <- "Click the "
this.brush <- new RadialGradientBrush(Colors.White, Colors.Red)
this.brush.RadiusX <- 0.10
this.brush.RadiusY <- 0.10
this.brush.SpreadMethod <- GradientSpreadMethod.Repeat;
this.Background <- this.brush

override this.OnMouseDown (args:MouseButtonEventArgs) =
let width = this.ActualWidth -
2.0 * SystemParameters.ResizeFrameVerticalBorderWidth
let height = this.ActualHeight -
2.0 * SystemParameters.ResizeFrameHorizontalBorderHeight -
SystemParameters.CaptionHeight
let currentPt = args.GetPosition(this)
let ptMouse = new Point(currentPt.X/width,currentPt.Y/height)
if (args.ChangedButton = MouseButton.Left) then
this.brush.Center <- ptMouse
this.brush.GradientOrigin <- ptMouse
else if (args.ChangedButton = MouseButton.Right) then
this.brush.GradientOrigin <- ptMouse


end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new ClickTheGradientCenter()) |> ignore
#endif

RotateTheGradientOrigin

#light
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
#r @"WindowsBase.dll"
#r @"PresentationCore.dll"
#r @"PresentationFramework.dll"

open System
open System.Windows
open System.Windows.Input
open System.Windows.Media
open System.Windows.Threading

(* From Chap 2 - RotateTheGradientOrigin.cs *)

type RotateTheGradientOrigin = class
inherit Window as base

val mutable brush : RadialGradientBrush
val mutable angle : double

new () as this = {brush=null;angle=0.0} then
this.Title <- "Rotate the Gradient Origin"
this.WindowStartupLocation <- WindowStartupLocation.CenterScreen
this.Height <- 384.0
this.Width <- 384.0
this.brush <- new RadialGradientBrush(Colors.White, Colors.Red)
this.brush.Center <- new Point(0.5,0.5)
this.brush.GradientOrigin <- new Point(0.5,0.5)
this.brush.RadiusX <- 0.10
this.brush.RadiusY <- 0.10
this.brush.SpreadMethod <- GradientSpreadMethod.Repeat;
this.Background <- this.brush

let tmr = new DispatcherTimer()
tmr.Interval <- TimeSpan.FromMilliseconds(100.0)

// Using anonymous function (aka lambda functions) instead of explicitly
// defining a TimerOnTick member method
tmr.Tick.Add
(fun e ->
let pt = new Point(0.5 + 0.05 * Math.Cos(this.angle),
0.5 + 0.05 * Math.Sin(this.angle))
this.brush.GradientOrigin <- pt
this.angle <- this.angle + Math.PI/6.0)

tmr.Start()


end

#if COMPILED
[<STAThread()>]
do
let app = new Application() in
app.Run(new RotateTheGradientOrigin()) |> ignore
#endif

No comments: