--- /dev/null
+module ParasitemiaUI.DPICalculator
+
+open System
+open System.Windows
+open System.Windows.Media
+open System.Windows.Markup
+open System.Windows.Shapes
+open System.Windows.Controls
+open System.Diagnostics
+
+open ParasitemiaCore.UnitsOfMeasure
+open ParasitemiaCore.Types
+
+type SensorSize = {
+ w: float<mm>
+ h: float<mm>
+ txt: string } with
+ override this.ToString () =
+ sprintf "%g mm × %g mm%s" this.w this.h (if this.txt = "" then "" else " (" + this.txt + ")")
+
+let showWindow (parent: Window) : int option =
+ let win = Views.DPICalculatorWindow()
+ win.Root.Owner <- parent
+ win.Root.Left <- parent.Left + parent.ActualWidth / 2. - win.Root.Width / 2.
+ win.Root.Top <- parent.Top + parent.ActualHeight / 2. - win.Root.Height / 2.
+
+ let sensorSizes = [
+ { w = 5.76<mm>; h = 4.29<mm>; txt = "1/2.5″" }
+ { w = 7.6<mm>; h = 5.7<mm>; txt = "1/1.7″" }
+ { w = 8.6<mm>; h = 6.6<mm>; txt = "2/3″" }
+ { w = 13.2<mm>; h = 8.8<mm>; txt = "1″" }
+ { w = 17.3<mm>; h = 13.<mm>; txt = "" }
+ { w = 20.7<mm>; h = 13.8<mm>; txt = "" }
+ { w = 22.2<mm>; h = 14.8<mm>; txt = "" }
+ { w = 23.6<mm>; h = 15.7<mm>; txt = "" }
+ { w = 28.7<mm>; h = 19.<mm>; txt = "" }
+ { w = 28.7<mm>; h = 19.<mm>; txt = "" } ]
+
+ for size in sensorSizes do
+ win.cmbSensorSize.Items.Add(size) |> ignore
+ win.cmbSensorSize.SelectedIndex <- 0
+
+ let resolution (w_p: float<px>) (w_mm: float<mm>) (zoom: float) : float<ppi> =
+ w_p * zoom / mmToInch w_mm
+
+ let updateCurrentResolution () =
+ let { w = w; h = h } = win.cmbSensorSize.SelectedValue :?> SensorSize
+ let ratio = h / w
+
+ let parseDouble txt errorMess = match Double.TryParse(txt) with true, value -> Success value | _ -> Fail errorMess
+
+ match result
+ { let! sensorResolution = parseDouble win.txtSensorResolution.Text "The sensor resolution is not valid"
+ let! zoom = parseDouble win.txtZoom.Text "The zoom is not valid"
+ let wPixel = 1.<px> * sqrt (sensorResolution * 1e6 / ratio)
+ return! Success (float <| resolution wPixel w zoom) } with
+ | Success res -> win.txtImageResolution.Text <- (int (res / 1000.) * 1000).ToString()
+ | Fail mess -> win.txtImageResolution.Text <- mess
+
+ win.butCancel.Click.AddHandler(fun obj args -> win.Root.DialogResult <- Nullable<bool>(false); win.Root.Close())
+ win.butOK.Click.AddHandler(fun obj args -> win.Root.DialogResult <- Nullable<bool>(true); win.Root.Close())
+
+ win.cmbSensorSize.SelectionChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
+ win.txtSensorResolution.TextChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
+ win.txtZoom.TextChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
+
+ let result = win.Root.ShowDialog()
+ if result.HasValue && result.Value
+ then
+ match Int32.TryParse win.txtImageResolution.Text with
+ | true, res -> Some res
+ | _ -> None
+ else
+ None
+