Add an about window.
[master-thesis.git] / Parasitemia / Parasitemia / GUI / GUI.fs
index 2132363..950afc9 100644 (file)
@@ -16,11 +16,10 @@ open Emgu.CV.WPF
 open Config
 open Types
 
-let run (defaultConfig: Config) =
+let run (defaultConfig: Config) (fileToOpen: string option) =
     let app = new Application()
     let mainWindow = Views.MainWindow()
-    let ctrl (name: string): 'a =
-        mainWindow.Root.FindName(name) :?> 'a
+    let ctrl (name: string): 'a = mainWindow.Root.FindName(name) :?> 'a
 
     let colorRBCHealthy = Brushes.YellowGreen
     let colorRBCInfected = Brushes.Red
@@ -34,8 +33,11 @@ let run (defaultConfig: Config) =
     let menuLoadFile: MenuItem = ctrl "menuOpen"
     let menuNewFile: MenuItem = ctrl "menuNew"
     let menuAddSourceImage: MenuItem = ctrl "menuAddSourceImage"
+    let menuAnalysis: MenuItem = ctrl "menuAnalysis"
     let menuStartAnalysis: MenuItem = ctrl "menuStartAnalysis"
+    let menuView: MenuItem = ctrl "menuView"
     let menuHightlightRBC: MenuItem = ctrl "menuHightlightRBC"
+    let menuAbout: MenuItem = ctrl "menuAbout"
 
     let txtPatient: TextBox = ctrl "txtPatient"
     let txtGlobalParasitemia: TextBox = ctrl "txtGlobalParasitemia"
@@ -61,7 +63,6 @@ let run (defaultConfig: Config) =
         let y = rbc.center.Y - rbcHeight / 2. |> Utils.roundInt
         let w = Utils.roundInt rbcWidth
         let h = Utils.roundInt rbcHeight
-        //Utils.dprintfn "w: %A, h: %A, cx: %A, cy: %A, img.w: %A, img.h: %A" w h x y img.Width img.Height
         img.GetSubRect(System.Drawing.Rectangle(System.Drawing.Point((if x < 0 then 0 else x), (if y < 0 then 0 else y)),
                                                 System.Drawing.Size((if x + w >= img.Width then img.Width - x else w),
                                                                     (if y + h >= img.Height then img.Height - y else h))))
@@ -115,8 +116,7 @@ let run (defaultConfig: Config) =
             txtImageInformation.Inlines.Add(Documents.LineBreak())
 
             txtImageInformation.Inlines.Add(Documents.Run("Average erytrocyte diameter: ", FontWeight = FontWeights.Bold))
-            txtImageInformation.Inlines.Add(Documents.Run(string (Utils.roundInt <| 2. * srcImg.rbcRadius)))
-            txtImageInformation.Inlines.Add(Documents.Run(" px"))
+            txtImageInformation.Inlines.Add(Documents.Run(srcImg.config.RBCRadius.ToString()))
             txtImageInformation.Inlines.Add(Documents.LineBreak())
 
             txtImageInformation.Inlines.Add(Documents.Run("Last analysis: ", FontWeight = FontWeights.Bold))
@@ -126,6 +126,31 @@ let run (defaultConfig: Config) =
     let updateGlobalParasitemia () =
         txtGlobalParasitemia.Text <- parasitemiaText state.GlobalParasitemia
 
+    let updateViewportPreview () =
+        for preview in stackPreviews.Children |> Seq.cast<Views.ImageSourcePreview> do
+            let srcImg = preview.Tag :?> SourceImage
+            if Some srcImg = state.CurrentImage then
+                preview.viewport.Visibility <- Visibility.Visible
+
+                let canvasWidth = canvasCurrentImage.ActualWidth * currentScale
+                let canvasHeight = canvasCurrentImage.ActualHeight * currentScale
+                let previewWidth = (preview.ActualWidth - preview.BorderThickness.Left - preview.BorderThickness.Right)
+                let previewHeight = (preview.ActualHeight - preview.BorderThickness.Top - preview.BorderThickness.Bottom)
+
+                let marginLeft = previewWidth * (scrollViewCurrentImage.HorizontalOffset - borderCurrentImage.BorderThickness.Left) / canvasWidth - 2.
+                let marginRight = previewWidth * (canvasWidth - (scrollViewCurrentImage.HorizontalOffset - borderCurrentImage.BorderThickness.Right) - scrollViewCurrentImage.ViewportWidth) / canvasWidth - 2.
+                let marginTop = previewHeight * (scrollViewCurrentImage.VerticalOffset - borderCurrentImage.BorderThickness.Top) / canvasHeight - 2.
+                let marginBottom = previewHeight * (canvasHeight - (scrollViewCurrentImage.VerticalOffset - borderCurrentImage.BorderThickness.Bottom) - scrollViewCurrentImage.ViewportHeight) / canvasHeight - 2.
+
+                preview.viewport.Margin <-
+                    Thickness(
+                        marginLeft,
+                        marginTop,
+                        marginRight,
+                        marginBottom)
+            else
+                preview.viewport.Visibility <- Visibility.Hidden
+
     let rec setAsInfected (rbc: RBC) (infected: bool) =
         state.SetAsInfected rbc infected
         canvasCurrentImage.Children
@@ -140,23 +165,24 @@ let run (defaultConfig: Config) =
         updateGlobalParasitemia ()
 
     and RBCFrame (rbc: RBC) : Views.RBCFrame =
-        let f = RBCFrameFromExisting rbc (Views.RBCFrame())
-        f.menuRBCSetAsHealthy.Click.AddHandler(fun obj args -> setAsInfected (f.Tag :?> RBC) false)
-        f.menuRBCSetAsInfected.Click.AddHandler(fun obj args -> setAsInfected (f.Tag :?> RBC) true)
-        f.ContextMenuOpening.AddHandler(
+        let frame = RBCFrameFromExisting rbc (Views.RBCFrame())
+        frame.SetValue(Panel.ZIndexProperty, Int32.MaxValue - rbc.num) // To be sure the
+        frame.menuRBCSetAsHealthy.Click.AddHandler(fun obj args -> setAsInfected (frame.Tag :?> RBC) false)
+        frame.menuRBCSetAsInfected.Click.AddHandler(fun obj args -> setAsInfected (frame.Tag :?> RBC) true)
+        frame.ContextMenuOpening.AddHandler(
             fun obj args ->
-                if (f.Tag :?> RBC).infected
+                if (frame.Tag :?> RBC).infected
                 then
-                    f.menuRBCSetAsHealthy.Visibility <- Visibility.Visible
-                    f.menuRBCSetAsInfected.Visibility <- Visibility.Collapsed
+                    frame.menuRBCSetAsHealthy.Visibility <- Visibility.Visible
+                    frame.menuRBCSetAsInfected.Visibility <- Visibility.Collapsed
                 else
-                    f.menuRBCSetAsHealthy.Visibility <- Visibility.Collapsed
-                    f.menuRBCSetAsInfected.Visibility <- Visibility.Visible)
+                    frame.menuRBCSetAsHealthy.Visibility <- Visibility.Collapsed
+                    frame.menuRBCSetAsInfected.Visibility <- Visibility.Visible)
 
-        f.ContextMenuClosing.AddHandler(fun obj args -> if not f.IsMouseOver then highlightRBCFrame f false )
-        f.MouseEnter.AddHandler(fun obj args -> highlightRBCFrame f true)
-        f.MouseLeave.AddHandler(fun obj args -> if not f.grid.ContextMenu.IsOpen then highlightRBCFrame f false)
-        f
+        frame.ContextMenuClosing.AddHandler(fun obj args -> if not frame.IsMouseOver then highlightRBCFrame frame false )
+        frame.MouseEnter.AddHandler(fun obj args -> highlightRBCFrame frame true)
+        frame.MouseLeave.AddHandler(fun obj args -> if not frame.grid.ContextMenu.IsOpen then highlightRBCFrame frame false)
+        frame
 
     and updateRBCFramesPreview () =
         match state.CurrentImage with
@@ -182,6 +208,8 @@ let run (defaultConfig: Config) =
             stackRBC.Children.RemoveRange(currentPreview, stackRBC.Children.Count - currentPreview)
         | _ -> ()
 
+        updateViewportPreview ()
+
     let updateRBCFramesCurrent () =
         match state.CurrentImage with
         | Some srcImg ->
@@ -193,6 +221,7 @@ let run (defaultConfig: Config) =
                         RBCFrameFromExisting rbc (canvasCurrentImage.Children.[currentCanvas] :?> Views.RBCFrame)
                     else
                         let f = RBCFrame rbc
+                        f.Root.Opacity <- 0.7
                         canvasCurrentImage.Children.Add(f) |> ignore
                         f
 
@@ -251,31 +280,6 @@ let run (defaultConfig: Config) =
             state.CurrentImage <- Some srcImg
             updateCurrentImage ()
 
-    let updateViewportPreview () =
-        for preview in stackPreviews.Children |> Seq.cast<Views.ImageSourcePreview> do
-            let srcImg = preview.Tag :?> SourceImage
-            if Some srcImg = state.CurrentImage then
-                preview.viewport.Visibility <- Visibility.Visible
-
-                let canvasWidth = canvasCurrentImage.ActualWidth * currentScale
-                let canvasHeight = canvasCurrentImage.ActualHeight * currentScale
-                let previewWidth = (preview.ActualWidth - preview.BorderThickness.Left - preview.BorderThickness.Right)
-                let previewHeight = (preview.ActualHeight - preview.BorderThickness.Top - preview.BorderThickness.Bottom)
-
-                let marginLeft = previewWidth * (scrollViewCurrentImage.HorizontalOffset - borderCurrentImage.BorderThickness.Left) / canvasWidth - 2.
-                let marginRight = previewWidth * (canvasWidth - (scrollViewCurrentImage.HorizontalOffset - borderCurrentImage.BorderThickness.Right) - scrollViewCurrentImage.ViewportWidth) / canvasWidth - 2.
-                let marginTop = previewHeight * (scrollViewCurrentImage.VerticalOffset - borderCurrentImage.BorderThickness.Top) / canvasHeight - 2.
-                let marginBottom = previewHeight * (canvasHeight - (scrollViewCurrentImage.VerticalOffset - borderCurrentImage.BorderThickness.Bottom) - scrollViewCurrentImage.ViewportHeight) / canvasHeight - 2.
-
-                preview.viewport.Margin <-
-                    Thickness(
-                        marginLeft,
-                        marginTop,
-                        marginRight,
-                        marginBottom)
-            else
-                preview.viewport.Visibility <- Visibility.Hidden
-
     let addPreview (srcImg: SourceImage) =
         let imgCtrl = Views.ImageSourcePreview(Margin = Thickness(3.))
 
@@ -321,7 +325,6 @@ let run (defaultConfig: Config) =
             then
                 imgCtrl.ReleaseMouseCapture())
 
-
     let updatePreviews () =
         stackPreviews.Children.Clear ()
         for srcImg in state.SourceImages do
@@ -333,7 +336,13 @@ let run (defaultConfig: Config) =
         updatePreviews ()
         updateGlobalParasitemia ()
 
-    txtPatient.TextChanged.AddHandler(fun obj args -> state.PatientID <- txtPatient.Text)
+    let loadFile (filepath: string) =
+        askSaveCurrent ()
+        state.FilePath <- filepath
+        state.Load()
+        updateGUI ()
+
+    txtPatient.LostFocus.AddHandler(fun obj args -> state.PatientID <- txtPatient.Text)
 
     menuExit.Click.AddHandler(fun obj args ->
         askSaveCurrent ()
@@ -346,11 +355,7 @@ let run (defaultConfig: Config) =
         let dialog = OpenFileDialog(Filter = PiaZ.filter)
         let res = dialog.ShowDialog()
         if res.HasValue && res.Value
-        then
-            askSaveCurrent ()
-            state.FilePath <- dialog.FileName
-            state.Load()
-            updateGUI ())
+        then loadFile dialog.FileName)
 
     menuNewFile.Click.AddHandler(fun obj args ->
         askSaveCurrent ()
@@ -358,19 +363,26 @@ let run (defaultConfig: Config) =
         updateGUI())
 
     menuAddSourceImage.Click.AddHandler(fun obj args ->
-        let dialog = OpenFileDialog(Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff")
+        let dialog = OpenFileDialog(Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff", Multiselect = true)
         let res = dialog.ShowDialog()
         if res.HasValue && res.Value
         then
-            let srcImg = state.AddSourceImage(dialog.FileName)
-            addPreview srcImg
+            let noSourceImage = state.SourceImages.Count() = 0
+
+            for filename in dialog.FileNames do
+                let srcImg = state.AddSourceImage filename defaultConfig
+                addPreview srcImg
+
             updateGlobalParasitemia ()
-            if state.SourceImages.Count() = 1
+
+            if noSourceImage
             then
                 updateCurrentImage ())
 
+    menuAnalysis.SubmenuOpened.AddHandler(fun obj args -> menuStartAnalysis.IsEnabled <- state.SourceImages.Count() > 0)
+
     menuStartAnalysis.Click.AddHandler(fun obj args ->
-        if Analysis.showWindow mainWindow.Root state defaultConfig
+        if Analysis.showWindow mainWindow.Root state
         then
             updateGlobalParasitemia ()
             updateCurrentImage ())
@@ -380,6 +392,8 @@ let run (defaultConfig: Config) =
         updateRBCFramesPreview ()
         updateRBCFramesCurrent ())
 
+    menuAbout.Click.AddHandler(fun obj args -> About.showWindow mainWindow.Root)
+
     // Zoom on the current image.
     let adjustCurrentImageBorders (deltaX: float) (deltaY: float) =
         borderCurrentImage.BorderThickness <-
@@ -466,4 +480,9 @@ let run (defaultConfig: Config) =
     scrollViewCurrentImage.ScrollChanged.AddHandler(fun obj args -> updateViewportPreview ())
 
     mainWindow.Root.Show()
+
+    match fileToOpen with
+    | Some filepath -> loadFile filepath
+    | None -> ()
+
     app.Run()
\ No newline at end of file