0 people like it.

Calculator

Simple Silverlight Calculator UI interactive sample runnable inside http://tryfsharp.org.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
#if INTERACTIVE
#else
namespace global
#endif

module Bindings = 

    open System.Windows
    open System.Windows.Data

    type DependencyPropertyBindingPair(dp:DependencyProperty,binding:Binding) =
        member this.Property = dp
        member this.Binding = binding
        static member (+) 
            (target:#FrameworkElement,pair:DependencyPropertyBindingPair) =
            target.SetBinding(pair.Property,pair.Binding) |> ignore
            target

    type DependencyPropertyValuePair(dp:DependencyProperty,value:obj) =
        member this.Property = dp
        member this.Value = value
        static member (+) 
            (target:#UIElement,pair:DependencyPropertyValuePair) =
            target.SetValue(pair.Property,pair.Value)
            target

    open System.Windows.Controls

    type Button with
        static member CommandBinding (binding:Binding) = 
            DependencyPropertyBindingPair(Button.CommandProperty,binding)
        static member EffectBinding (binding:Binding) =
            DependencyPropertyBindingPair(Button.EffectProperty,binding)

    type Grid with
        static member Column (value:int) =
            DependencyPropertyValuePair(Grid.ColumnProperty,value)
        static member Row (value:int) =
            DependencyPropertyValuePair(Grid.RowProperty,value)        

    type TextBox with
        static member TextBinding (binding:Binding) =
            DependencyPropertyBindingPair(TextBox.TextProperty,binding)

module ViewModel =

    type Operator =
        | Plus | Minus | Multiply | Divide
        static member Eval op (a:decimal) (b:decimal) =
            match op with
            | Plus -> a + b
            | Minus-> a - b
            | Multiply -> a * b
            | Divide -> a / b

    type Key =    
        | Digit of int
        | Dot
        | Operator of Operator
        | Evaluate

    let Command (action:'T -> unit) =
        let event = new DelegateEvent<System.EventHandler>()
        { new System.Windows.Input.ICommand with
            member this.Execute (param:obj) = action(param :?> 'T)
            member this.CanExecute (param:obj) = true
            [<CLIEvent>]
            member this.CanExecuteChanged = event.Publish
        }

    type Calculator() as this =   
        let propertyChanged = new Event<_,_>()
        let mutable display = 0M  
        let mutable acc = None    
        let mutable operation = None        
        let PropertyChanged name = 
            (this,System.ComponentModel.PropertyChangedEventArgs(name)) 
            |> propertyChanged.Trigger
        let SetOperation value =
            operation <- value
            PropertyChanged "Operator"
            PropertyChanged "Operand"
        let SetDisplay value =
            display <- value
            PropertyChanged "Display"        
        let Calculate () =
            match operation,acc with
            | Some(op,a), Some(b,_) -> 
                Operator.Eval op a b |> SetDisplay
            | _,_ -> ()
        let HandleKey = function
            | Digit(n) ->  
                let value,dp =       
                    match acc with
                    | Some(x,Some dp) ->                     
                        x + (dp * decimal n), Some(dp * 0.1M)                             
                    | Some(x,None) ->                                          
                        (x * 10M) + decimal n, None                    
                    | None -> decimal n, None
                acc <- Some(value,dp)
                value |> SetDisplay
            | Dot -> 
                acc <-
                    match acc with 
                    | Some(x,None) -> Some(x,Some(0.1M))
                    | Some(x,Some(dp)) -> acc
                    | None -> Some(0.0M,Some(0.1M))            
            | Operator(op) -> 
                Calculate ()
                SetOperation (Some(op,display))
                acc <- None     
            | Evaluate -> 
                Calculate ()
                SetOperation None
                acc <- None                      
        let command = Command(fun (param:Key) -> HandleKey (param))
        member this.KeyCommand = command                
        member this.Display = display 
        member this.Operator = operation |> Option.map fst
        member this.Operand = operation |> Option.map snd    
        interface System.ComponentModel.INotifyPropertyChanged with
            [<CLIEvent>]
            member this.PropertyChanged = propertyChanged.Publish

open Bindings
open ViewModel

open System
open System.Globalization
open System.Windows
open System.Windows.Controls
open System.Windows.Data
open System.Windows.Media
open System.Windows.Media.Effects

type CalculatorControl () as this =
    inherit UserControl (Width=240.0,Height=240.0) 

    let CreateTextBox (color,opactity) =
        TextBox(HorizontalContentAlignment=HorizontalAlignment.Right,
                Height=48.0,
                FontSize=32.0,
                Background=SolidColorBrush(color),
                Opacity=opactity,
                IsReadOnly=true)

    let display =
        let binding = 
            Binding("Display",Mode=BindingMode.OneWay,StringFormat="0.#####")    
        CreateTextBox (Colors.White,1.0) + TextBox.TextBinding(binding)
    
    let CreateValueConverter f =
        { new System.Windows.Data.IValueConverter with
            member this.Convert
                (value:obj,targetType:System.Type,parameter:obj,
                 culture:System.Globalization.CultureInfo) =
                f(value,parameter)
            member this.ConvertBack
                (value:obj,targetType:System.Type,parameter:obj,
                 culture:System.Globalization.CultureInfo) =
                raise (new System.NotImplementedException())
        } 

    let operationEffectConverter = 
        fun (value:obj,parameter:obj) -> 
            let op = value :?> Operator option
            let key = parameter :?> Key
            match op,key with
            | Some(op),Operator(x) when op = x -> DropShadowEffect() :> Effect
            | _ -> null :> Effect
            |> box
        |> CreateValueConverter     

    let keys =
        let grid = new Grid()
        for i = 1 to 4 do
            ColumnDefinition() |> grid.ColumnDefinitions.Add 
            RowDefinition() |> grid.RowDefinitions.Add
        [ 
        ['7',Digit(7);'8',Digit(8);'9',Digit(9);'/',Operator(Divide)]
        ['4',Digit(4);'5',Digit(5);'6',Digit(6);'*',Operator(Multiply)]
        ['1',Digit(1);'2',Digit(2);'3',Digit(3);'-',Operator(Minus)]
        ['0',Digit(0);'.',Dot;'=',Evaluate;'+',Operator(Plus)]
        ]    
        |> List.mapi (fun y ys ->
            ys |> List.mapi (fun x (c,key) ->
                let color =
                    match key with
                    | Operator(_) | Evaluate -> Colors.Yellow
                    | Digit(_) | Dot -> Colors.LightGray                        
                let effect =
                    Binding("Operator",
                            Converter=operationEffectConverter,
                            ConverterParameter=key)    
                Button(Content=c,CommandParameter=key,
                    Width=40.0,Height=40.0,Margin=Thickness(4.0),
                    Background=SolidColorBrush(color)) +                
                    Button.CommandBinding(Binding("KeyCommand")) +
                    Button.EffectBinding(effect) +
                    Grid.Column(x) + Grid.Row(y)                         
            )
        )
        |> List.concat
        |> List.iter (grid.Children.Add >> ignore)
        grid
           
    let (+.) (panel:#Panel) item = panel.Children.Add item |> ignore; panel                  
    let panel = StackPanel(Orientation=Orientation.Vertical) +. display +. keys        
    do this.Content <- panel
    let calculator = Calculator()           
    do this.DataContext <- calculator

#if INTERACTIVE
open Microsoft.TryFSharp
App.Dispatch (fun() -> 
    App.Console.ClearCanvas()
    CalculatorControl() |> App.Console.Canvas.Children.Add
    App.Console.CanvasPosition <- CanvasPosition.Right
)
#endif
namespace System
namespace System.Windows
namespace Microsoft.FSharp.Data
Multiple items
type DependencyPropertyBindingPair =
  new : dp:obj * binding:obj -> DependencyPropertyBindingPair
  member Binding : obj
  member Property : obj
  static member ( + ) : target:'a * pair:DependencyPropertyBindingPair -> 'a

Full name: Script.Bindings.DependencyPropertyBindingPair

--------------------
new : dp:obj * binding:obj -> DependencyPropertyBindingPair
val dp : obj
val binding : obj
val this : DependencyPropertyBindingPair
member DependencyPropertyBindingPair.Property : obj

Full name: Script.Bindings.DependencyPropertyBindingPair.Property
member DependencyPropertyBindingPair.Binding : obj

Full name: Script.Bindings.DependencyPropertyBindingPair.Binding
val target : 'a
val pair : DependencyPropertyBindingPair
property DependencyPropertyBindingPair.Property: obj
property DependencyPropertyBindingPair.Binding: obj
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
Multiple items
type DependencyPropertyValuePair =
  new : dp:obj * value:obj -> DependencyPropertyValuePair
  member Property : obj
  member Value : obj
  static member ( + ) : target:'a * pair:DependencyPropertyValuePair -> 'a

Full name: Script.Bindings.DependencyPropertyValuePair

--------------------
new : dp:obj * value:obj -> DependencyPropertyValuePair
val value : obj
type obj = System.Object

Full name: Microsoft.FSharp.Core.obj
val this : DependencyPropertyValuePair
member DependencyPropertyValuePair.Property : obj

Full name: Script.Bindings.DependencyPropertyValuePair.Property
member DependencyPropertyValuePair.Value : obj

Full name: Script.Bindings.DependencyPropertyValuePair.Value
val pair : DependencyPropertyValuePair
property DependencyPropertyValuePair.Property: obj
property DependencyPropertyValuePair.Value: obj
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
type Operator =
  | Plus
  | Minus
  | Multiply
  | Divide
  static member Eval : op:Operator -> a:decimal -> b:decimal -> decimal

Full name: Script.ViewModel.Operator
union case Operator.Plus: Operator
union case Operator.Minus: Operator
union case Operator.Multiply: Operator
union case Operator.Divide: Operator
static member Operator.Eval : op:Operator -> a:decimal -> b:decimal -> decimal

Full name: Script.ViewModel.Operator.Eval
val op : Operator
val a : decimal
Multiple items
val decimal : value:'T -> decimal (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.decimal

--------------------
type decimal = System.Decimal

Full name: Microsoft.FSharp.Core.decimal

--------------------
type decimal<'Measure> = decimal

Full name: Microsoft.FSharp.Core.decimal<_>
val b : decimal
type Key =
  | Digit of int
  | Dot
  | Operator of Operator
  | Evaluate

Full name: Script.ViewModel.Key
union case Key.Digit: int -> Key
union case Key.Dot: Key
Multiple items
union case Key.Operator: Operator -> Key

--------------------
type Operator =
  | Plus
  | Minus
  | Multiply
  | Divide
  static member Eval : op:Operator -> a:decimal -> b:decimal -> decimal

Full name: Script.ViewModel.Operator
union case Key.Evaluate: Key
val Command : action:('T -> unit) -> 'a

Full name: Script.ViewModel.Command
val action : ('T -> unit)
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val event : DelegateEvent<System.EventHandler>
Multiple items
type DelegateEvent<'Delegate (requires 'Delegate :> Delegate)> =
  new : unit -> DelegateEvent<'Delegate>
  member Trigger : args:obj [] -> unit
  member Publish : IDelegateEvent<'Delegate>

Full name: Microsoft.FSharp.Control.DelegateEvent<_>

--------------------
new : unit -> DelegateEvent<'Delegate>
Multiple items
type EventHandler<'TEventArgs (requires 'TEventArgs :> EventArgs)> =
  delegate of obj * 'TEventArgs -> unit

Full name: System.EventHandler<_>

--------------------
type EventHandler =
  delegate of obj * EventArgs -> unit

Full name: System.EventHandler
Multiple items
type CLIEventAttribute =
  inherit Attribute
  new : unit -> CLIEventAttribute

Full name: Microsoft.FSharp.Core.CLIEventAttribute

--------------------
new : unit -> CLIEventAttribute
property DelegateEvent.Publish: IDelegateEvent<System.EventHandler>
Multiple items
type Calculator =
  interface INotifyPropertyChanged
  new : unit -> Calculator
  member Display : decimal
  member KeyCommand : obj
  member Operand : decimal option
  member Operator : Operator option

Full name: Script.ViewModel.Calculator

--------------------
new : unit -> Calculator
val this : Calculator
val propertyChanged : Event<System.ComponentModel.PropertyChangedEventHandler,System.ComponentModel.PropertyChangedEventArgs>
Multiple items
module Event

from Microsoft.FSharp.Control

--------------------
type Event<'T> =
  new : unit -> Event<'T>
  member Trigger : arg:'T -> unit
  member Publish : IEvent<'T>

Full name: Microsoft.FSharp.Control.Event<_>

--------------------
type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
  new : unit -> Event<'Delegate,'Args>
  member Trigger : sender:obj * args:'Args -> unit
  member Publish : IEvent<'Delegate,'Args>

Full name: Microsoft.FSharp.Control.Event<_,_>

--------------------
new : unit -> Event<'T>

--------------------
new : unit -> Event<'Delegate,'Args>
val mutable display : decimal
val mutable acc : (decimal * decimal option) option
union case Option.None: Option<'T>
val mutable operation : (Operator * decimal) option
val PropertyChanged : (string -> unit)
val name : string
namespace System.ComponentModel
Multiple items
type PropertyChangedEventArgs =
  inherit EventArgs
  new : propertyName:string -> PropertyChangedEventArgs
  member PropertyName : string

Full name: System.ComponentModel.PropertyChangedEventArgs

--------------------
System.ComponentModel.PropertyChangedEventArgs(propertyName: string) : unit
member Event.Trigger : sender:obj * args:'Args -> unit
val SetOperation : ((Operator * decimal) option -> unit)
val value : (Operator * decimal) option
val SetDisplay : (decimal -> unit)
val value : decimal
val Calculate : (unit -> unit)
union case Option.Some: Value: 'T -> Option<'T>
static member Operator.Eval : op:Operator -> a:decimal -> b:decimal -> decimal
val HandleKey : (Key -> unit)
val n : int
val dp : decimal option
val x : decimal
val dp : decimal
val command : obj
val param : Key
member Calculator.KeyCommand : obj

Full name: Script.ViewModel.Calculator.KeyCommand
member Calculator.Display : decimal

Full name: Script.ViewModel.Calculator.Display
Multiple items
member Calculator.Operator : Operator option

Full name: Script.ViewModel.Calculator.Operator

--------------------
type Operator =
  | Plus
  | Minus
  | Multiply
  | Divide
  static member Eval : op:Operator -> a:decimal -> b:decimal -> decimal

Full name: Script.ViewModel.Operator
module Option

from Microsoft.FSharp.Core
val map : mapping:('T -> 'U) -> option:'T option -> 'U option

Full name: Microsoft.FSharp.Core.Option.map
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
member Calculator.Operand : decimal option

Full name: Script.ViewModel.Calculator.Operand
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
type INotifyPropertyChanged =
  event PropertyChanged : PropertyChangedEventHandler

Full name: System.ComponentModel.INotifyPropertyChanged
override Calculator.PropertyChanged : IEvent<System.ComponentModel.PropertyChangedEventHandler,System.ComponentModel.PropertyChangedEventArgs>

Full name: Script.ViewModel.Calculator.PropertyChanged
property Event.Publish: IEvent<System.ComponentModel.PropertyChangedEventHandler,System.ComponentModel.PropertyChangedEventArgs>
module Bindings

from Script
module ViewModel

from Script
namespace System.Globalization
Multiple items
namespace System.Data

--------------------
namespace Microsoft.FSharp.Data
namespace System.Media
Multiple items
type CalculatorControl =
  inherit obj
  new : unit -> CalculatorControl

Full name: Script.CalculatorControl

--------------------
new : unit -> CalculatorControl
val this : CalculatorControl
type Convert =
  static val DBNull : obj
  static member ChangeType : value:obj * typeCode:TypeCode -> obj + 3 overloads
  static member FromBase64CharArray : inArray:char[] * offset:int * length:int -> byte[]
  static member FromBase64String : s:string -> byte[]
  static member GetTypeCode : value:obj -> TypeCode
  static member IsDBNull : value:obj -> bool
  static member ToBase64CharArray : inArray:byte[] * offsetIn:int * length:int * outArray:char[] * offsetOut:int -> int + 1 overload
  static member ToBase64String : inArray:byte[] -> string + 3 overloads
  static member ToBoolean : value:obj -> bool + 17 overloads
  static member ToByte : value:obj -> byte + 18 overloads
  ...

Full name: System.Convert
type obj = Object

Full name: Microsoft.FSharp.Core.obj
type Type =
  inherit MemberInfo
  member Assembly : Assembly
  member AssemblyQualifiedName : string
  member Attributes : TypeAttributes
  member BaseType : Type
  member ContainsGenericParameters : bool
  member DeclaringMethod : MethodBase
  member DeclaringType : Type
  member Equals : o:obj -> bool + 1 overload
  member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
  member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
  ...

Full name: System.Type
Multiple items
type CultureInfo =
  new : name:string -> CultureInfo + 3 overloads
  member Calendar : Calendar
  member ClearCachedData : unit -> unit
  member Clone : unit -> obj
  member CompareInfo : CompareInfo
  member CultureTypes : CultureTypes
  member DateTimeFormat : DateTimeFormatInfo with get, set
  member DisplayName : string
  member EnglishName : string
  member Equals : value:obj -> bool
  ...

Full name: System.Globalization.CultureInfo

--------------------
CultureInfo(name: string) : unit
CultureInfo(culture: int) : unit
CultureInfo(name: string, useUserOverride: bool) : unit
CultureInfo(culture: int, useUserOverride: bool) : unit
val raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type NotImplementedException =
  inherit SystemException
  new : unit -> NotImplementedException + 2 overloads

Full name: System.NotImplementedException

--------------------
NotImplementedException() : unit
NotImplementedException(message: string) : unit
NotImplementedException(message: string, inner: exn) : unit
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
val box : value:'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val mapi : mapping:(int -> 'T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.mapi
type Converter<'TInput,'TOutput> =
  delegate of 'TInput -> 'TOutput

Full name: System.Converter<_,_>
val concat : lists:seq<'T list> -> 'T list

Full name: Microsoft.FSharp.Collections.List.concat
val iter : action:('T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iter
Raw view Test code New version

More information

Link:http://fssnip.net/4W
Posted:13 years ago
Author:Phillip Trelford
Tags: silverlight