Friday, November 23, 2007

Learning WPF with F# - Stack and Wrap

Examples from Chapter 5 of Petzold's book "Applications = Code + Markup: A Guide to the Microsoft Windows Presentation Foundation"



StackTenButtons

#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.Controls
open System.Windows.Input
open System.Windows.Media


let addButtonToStack (stack:StackPanel) (rand:Random) i =
let btn = new Button()
btn.Name <- Char.chr((Char.code('A') + i)).ToString()
btn.FontSize <- btn.FontSize + Float.of_int (rand.Next(10))
btn.Content <- "Button " + btn.Name + " says 'Click me'"
btn.Click.Add
(fun _ ->
MessageBox.Show("Button " + btn.Name + " has been clicked", "Button Click")|>ignore)
stack.Children.Add(btn) |> ignore

(* From Chap 5 - StackTenButtons.cs *)
type StackTenButtons = class
inherit Window as base

new () as this = {} then
this.Title <- "Stack Ten Buttons"
let stack = new StackPanel()
this.Content <- stack
let rand = new Random()

let addButton = addButtonToStack stack rand
let list = [ 0 .. 9]
List.iter addButton list

end

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

StackThirtyButtons

#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.Controls
open System.Windows.Input
open System.Windows.Media

let addButtonToStackPanel (stack:StackPanel) (i:int) (j:int) =
let btn = new Button()
btn.Content <- "Button No. " + string_of_int (10*i + j+1)
btn.Margin <- new Thickness(5.0)
stack.Children.Add(btn)|>ignore

(* From Chap 5 - StackThirtyButtons.cs *)
type StackThirtyButtons = class
inherit Window as base

new () as this = {} then
this.Title <- "Stack Thirty Buttons"
this.SizeToContent <- SizeToContent.WidthAndHeight
this.ResizeMode <- ResizeMode.CanMinimize

// Define the handler
let ButtonOnClick _ (args:RoutedEventArgs) =
let (button:Button) = args.Source :?> Button
ignore(MessageBox.Show("You clicked the button labeled " + (button.Content :?> string)))

// Adding new handler
this.AddHandler(Button.ClickEvent,new RoutedEventHandler(ButtonOnClick))

let stackMain = new StackPanel()
stackMain.Orientation <- Orientation.Horizontal
stackMain.Margin <- new Thickness(5.0)
this.Content <- stackMain

for i in [0..2] do
let stackChild = new StackPanel()
stackMain.Children.Add(stackChild) |>ignore
let addButton = addButtonToStackPanel stackChild i
let list = [0..9]
List.iter addButton list

end

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

ScrollFiftyButtons

#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.Controls
open System.Windows.Input
open System.Windows.Media

let addButtonToStackPanel (stack:StackPanel) (i:int) =
let btn = new Button()
btn.Name <- "Button" + string_of_int (i+1)
btn.Content <- btn.Name + " says 'Click me!'"
btn.Margin <- new Thickness(5.0)
stack.Children.Add(btn)|>ignore

(* From Chap 5 - ScrollFiftyButtons.cs *)
type ScrollFiftyButtons = class
inherit Window as base

new () as this = {} then
this.Title <- "Stack Fifty Buttons"
this.SizeToContent <- SizeToContent.Width

// Define the handler
let ButtonOnClick _ (args:RoutedEventArgs) =
let (button:Button) = args.Source :?> Button
ignore(MessageBox.Show(button.Name + " has been clicked", "Button Click"))

// Adding new handler
this.AddHandler(Button.ClickEvent,new RoutedEventHandler(ButtonOnClick))

let scroll = new ScrollViewer()
this.Content <- scroll
let stack = new StackPanel()
stack.Margin <- new Thickness(5.0)
scroll.Content <- stack

let addButton = addButtonToStackPanel stack
let list = [0..49]
List.iter addButton list

end

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

DesignAButton

#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.Controls
open System.Windows.Input
open System.Windows.Media
open System.Windows.Media.Imaging
open System.Windows.Shapes

let AddPointToPointCollection (points:PointCollection) offset x =
points.Add(new Point(x,(x+offset)%20.0))


(* From Chap 5 - DesignAButton.cs *)
type DesignAButton = class
inherit Window as base

new () as this = {} then
this.Title <- "Design a Button"

let btn = new Button()
btn.HorizontalAlignment <- HorizontalAlignment.Center;
btn.VerticalAlignment <- VerticalAlignment.Center;
btn.Click.Add
(fun _ -> ignore(MessageBox.Show("The button has been clicked",this.Title)))

this.Content <- btn


let stack = new StackPanel()
btn.Content <- stack

// Add a Polyline to the StackPanel
stack.Children.Add(this.ZigZig(10.0)) |> ignore

let uri = new Uri("file:///c:/dev/logo.ico")
let bitmap = new BitmapImage(uri)
let img = new Image()
img.Margin <- new Thickness(0.0,10.0,0.0,0.0)
img.Source <- bitmap
img.Stretch <- Stretch.None
stack.Children.Add(img) |> ignore

// Add a Label to the StackPanel
let lbl = new Label()
lbl.Content <- "_Read books!"
lbl.HorizontalContentAlignment <- HorizontalAlignment.Center
stack.Children.Add(lbl) |> ignore
stack.Children.Add(this.ZigZig(0.0)) |> ignore

member this.ZigZig offset =
let poly = new Polyline()
poly.Stroke <- SystemColors.ControlTextBrush
poly.Points <- new PointCollection()
let addpoints = AddPointToPointCollection poly.Points offset
let list = [0..10..100]
// Need to convert the list of ints to list of floats first
List.iter addpoints (List.map Float.of_int list)
// The following line sets the return value
poly


end

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

TuneTheRadio

#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.Controls
open System.Windows.Input
open System.Windows.Media

(* From Chap 5 - TuneTheRadio.cs *)
type TuneTheRadio = class
inherit Window as base

new () as this = {} then
this.Title <- "Tune the Radio"
this.SizeToContent <- SizeToContent.WidthAndHeight

let group = new GroupBox()
group.Header <- "Window Style"
group.Margin <- new Thickness(96.0)
group.Padding <- new Thickness(5.0)
this.Content <- group

let stack = new StackPanel()
group.Content <- stack

stack.Children.Add
(this.CreateRadioButton "No border or caption" WindowStyle.None)
|>ignore

stack.Children.Add
(this.CreateRadioButton "Single-border window" WindowStyle.SingleBorderWindow)
|>ignore

stack.Children.Add
(this.CreateRadioButton "3D-border window" WindowStyle.ThreeDBorderWindow)
|>ignore

stack.Children.Add
(this.CreateRadioButton "Tool window" WindowStyle.ToolWindow)
|>ignore

this.AddHandler(RadioButton.CheckedEvent,new RoutedEventHandler(this.RadioOnChecked))


member this.CreateRadioButton (strText:string) (winstyle:WindowStyle) =
let radio = new RadioButton()
radio.Content <- strText
radio.Tag <- winstyle
radio.Margin <- new Thickness(5.0)
radio.IsChecked <- new Nullable<bool>((winstyle=this.WindowStyle))
radio

member this.RadioOnChecked sender (args:RoutedEventArgs) =
let radio = args.Source :?> RadioButton
this.WindowStyle <- (radio.Tag :?> WindowStyle)

end

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

FileSystemInfoButton & ExploreDirectories

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

open System
open System.Diagnostics
open System.IO
open System.Windows
open System.Windows.Controls
open System.Windows.Input
open System.Windows.Media

(* From Chap 5 - FileSystemInfoButton.cs *)
type FileSystemInfoButton = class
inherit Button as base

val mutable info : FileSystemInfo

new () as this = {info=null} then
this.init(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)))

new (info:FileSystemInfo) as this = {info=null} then
this.init(info)

new ((info:FileSystemInfo),(str:string)) as this = {info=null} then
this.init(info)
this.Content <-str

member this.init(info:FileSystemInfo) =
this.info <- info
this.Content <- info.Name
if (info :? DirectoryInfo) then
this.FontWeight <- FontWeights.Bold
this.Margin <- new Thickness(1.0)

override this.OnClick() =
if (this.info :? FileInfo) then
Process.Start(this.info.FullName) |>ignore
else if (this.info :? DirectoryInfo) then
let dir = this.info :?> DirectoryInfo
Application.Current.MainWindow.Title <- dir.FullName

let pnl = this.Parent :?> Panel
pnl.Children.Clear()|>ignore

if (dir.Parent <> null) then
pnl.Children.Add(new FileSystemInfoButton(dir.Parent,".."))|>ignore

for inf in dir.GetFileSystemInfos() do
pnl.Children.Add(new FileSystemInfoButton(inf))|>ignore


base.OnClick()
end

(* From Chap 5 - ExploreDirectories.cs *)
type ExploreDirectories = class
inherit Window as base

new () as this = {} then
this.Title <- "Explore Directories"
let scroll = new ScrollViewer()
this.Content <- scroll

let wrap = new WrapPanel()
scroll.Content <- wrap

wrap.Children.Add(new FileSystemInfoButton()) |>ignore
end

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


No comments: