GUI (work in progress..)
[master-thesis.git] / Parasitemia / Parasitemia / GUI / GUI.fs
1 module Parasitemia.GUI.Main
2
3 open System.IO
4 open System.Linq
5 open System.Windows
6 open System.Windows.Media
7 open System.Windows.Markup
8 open System.Windows.Shapes
9 open System.Windows.Controls
10 open System.Diagnostics
11 open Microsoft.Win32 // For the common dialogs.
12
13 //open Emgu.CV
14 //open Emgu.CV.Structure
15 open Emgu.CV.WPF
16
17 open Config
18 open Types
19
20 let run (defaultConfig: Config) =
21 let app = new Application()
22 let mainWindow = Views.MainWindow()
23 let ctrl (name: string): 'a =
24 mainWindow.Root.FindName(name) :?> 'a
25
26 // Utils.log <- (fun m -> log mainWindow m)
27
28 let currentImageMargin = 0.1 // 10 %.
29
30 let state = State.State()
31
32 let exit: MenuItem = ctrl "menuExit"
33 let saveFile: MenuItem = ctrl "menuSave"
34 let loadFile: MenuItem = ctrl "menuOpen"
35 let newFile: MenuItem = ctrl "menuNew"
36
37 let addSourceImage: MenuItem = ctrl "menuAddSourceImage"
38 let txtPatient: TextBox = ctrl "txtPatient"
39 let stackPreviews: StackPanel = ctrl "stackPreviews"
40 let butStartAnalysis: Button = ctrl "butStartAnalysis"
41
42 let scrollViewCurrentImage: ScrollViewer = ctrl "scrollViewCurrentImage"
43 let borderCurrentImage: Border = ctrl "borderCurrentImage"
44 let canvasCurrentImage: Canvas = ctrl "canvasCurrentImage"
45
46 // Initializations.
47
48 // Operations.
49 let synchronizeState () =
50 state.PatientID <- txtPatient.Text
51
52 let setCurrentImage (srcImg: SourceImage) =
53 canvasCurrentImage.Height <- float srcImg.img.Height
54 canvasCurrentImage.Width <- float srcImg.img.Width
55 canvasCurrentImage.Background <- ImageBrush(BitmapSourceConvert.ToBitmapSource(srcImg.img))
56 (*for rbc in srcImg.rbcs do
57 let rectangle = Rectangle(Height = float rbc.size.Height, Width = float rbc.size.Width, )*)
58
59 let addPreview (srcImg: SourceImage) =
60 let imgCtrl = Views.ImageSourcePreview(Margin = Thickness(3.))
61 imgCtrl.lblImageNumber.Content <- srcImg.num
62 let width = 200
63 let height = srcImg.img.Height * width / srcImg.img.Width
64 imgCtrl.imagePreview.Source <- BitmapSourceConvert.ToBitmapSource(srcImg.img.Resize(width, height, Emgu.CV.CvEnum.Inter.Cubic))
65 stackPreviews.Children.Add(imgCtrl) |> ignore
66
67 let updatePreviews () =
68 stackPreviews.Children.Clear ()
69 for srcImg in state.SourceImages do
70 addPreview srcImg
71
72 let updateGUI () =
73 txtPatient.Text <- state.PatientID
74 updatePreviews ()
75
76 exit.Click.AddHandler(fun obj args -> mainWindow.Root.Close())
77 saveFile.Click.AddHandler(fun obj args ->
78 synchronizeState ()
79 if state.FilePath = ""
80 then
81 let dialog = SaveFileDialog(AddExtension = true, DefaultExt = Pia.extension, Filter = Pia.filter);
82 let res = dialog.ShowDialog()
83 if res.HasValue && res.Value
84 then
85 state.FilePath <- dialog.FileName
86 state.Save()
87 else
88 state.Save())
89
90 loadFile.Click.AddHandler(fun obj args ->
91 // TODO: if current state not saved and not empty, ask to save it.
92 let dialog = OpenFileDialog(Filter = Pia.filter)
93 let res = dialog.ShowDialog()
94 if res.HasValue && res.Value
95 then
96 state.FilePath <- dialog.FileName
97 state.Load()
98 updateGUI ())
99
100 newFile.Click.AddHandler(fun obj args ->
101 // TODO: if current state not saved and not empty, ask to save it.
102 state.Reset()
103 updateGUI())
104
105 addSourceImage.Click.AddHandler(fun obj args ->
106 let dialog = OpenFileDialog(Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff")
107 let res = dialog.ShowDialog()
108 if res.HasValue && res.Value
109 then
110 let srcImg = state.AddSourceImage(dialog.FileName)
111 addPreview srcImg
112 if state.SourceImages.Count() = 1
113 then
114 setCurrentImage srcImg)
115
116 butStartAnalysis.Click.AddHandler(fun obj args -> ())
117
118 // Zoom on the current image.
119 let adjustCurrentImageMargins () =
120 borderCurrentImage.BorderThickness <-
121 Thickness(scrollViewCurrentImage.ViewportWidth / 2., scrollViewCurrentImage.ViewportHeight / 2., scrollViewCurrentImage.ViewportWidth / 2., scrollViewCurrentImage.ViewportHeight / 2.)
122
123 scrollViewCurrentImage.Loaded.AddHandler(fun obj args -> adjustCurrentImageMargins ())
124 scrollViewCurrentImage.SizeChanged.AddHandler(fun obj args -> adjustCurrentImageMargins ())
125
126 let mutable currentScale = 1.
127 let mutable maxScale = 5.
128 let mutable minScale = 0.1
129 let currentImageScaleTransform = ScaleTransform()
130 borderCurrentImage.LayoutTransform <- currentImageScaleTransform
131 borderCurrentImage.PreviewMouseWheel.AddHandler(fun obj args ->
132 let scaleFactor = if args.Delta > 0 then 2.0 else 0.5
133 if scaleFactor > 1. && currentScale < maxScale || scaleFactor < 1. && currentScale > minScale
134 then
135 let previousScale = currentScale
136 currentScale <-
137 let newScale = currentScale * scaleFactor
138 if newScale > maxScale then maxScale elif newScale < minScale then minScale else newScale
139 let realScaleFactor = currentScale / previousScale
140
141 let centerX = scrollViewCurrentImage.HorizontalOffset + scrollViewCurrentImage.ViewportWidth / 2. - canvasCurrentImage.Margin.Left
142 let centerY = scrollViewCurrentImage.VerticalOffset + scrollViewCurrentImage.ViewportHeight / 2. - canvasCurrentImage.Margin.Top
143
144 canvasCurrentImage.Margin <- Thickness(canvasCurrentImage.Margin.Top * realScaleFactor)
145 currentImageScaleTransform.ScaleX <- currentScale
146 currentImageScaleTransform.ScaleY <- currentScale
147
148 scrollViewCurrentImage.ScrollToHorizontalOffset(centerX * realScaleFactor - scrollViewCurrentImage.ViewportWidth / 2. + canvasCurrentImage.Margin.Left)
149 scrollViewCurrentImage.ScrollToVerticalOffset(centerY * realScaleFactor - scrollViewCurrentImage.ViewportHeight / 2. + canvasCurrentImage.Margin.Top)
150 args.Handled <- true)
151
152 // Pan on the current image.
153 let mutable scrollStartPosition = Point(0., 0.)
154 let mutable scrollStartOffsetX = 0.
155 let mutable scrollStartOffsetY = 0.
156 borderCurrentImage.PreviewMouseLeftButtonDown.AddHandler(fun obj args ->
157 scrollStartPosition <- args.GetPosition(scrollViewCurrentImage)
158 scrollStartOffsetX <- scrollViewCurrentImage.HorizontalOffset
159 scrollStartOffsetY <- scrollViewCurrentImage.VerticalOffset
160 borderCurrentImage.Cursor <- Input.Cursors.ScrollAll
161 borderCurrentImage.CaptureMouse() |> ignore
162 args.Handled <- true)
163
164 borderCurrentImage.PreviewMouseMove.AddHandler(fun obj args ->
165 if borderCurrentImage.IsMouseCaptured
166 then
167 let position = args.GetPosition(scrollViewCurrentImage)
168 let deltaX = scrollStartPosition.X - position.X
169 let deltaY = scrollStartPosition.Y - position.Y
170 scrollViewCurrentImage.ScrollToHorizontalOffset(deltaX + scrollStartOffsetX)
171 scrollViewCurrentImage.ScrollToVerticalOffset(deltaY + scrollStartOffsetY)
172 args.Handled <- true)
173
174 borderCurrentImage.PreviewMouseLeftButtonUp.AddHandler(fun obj args ->
175 if borderCurrentImage.IsMouseCaptured
176 then
177 borderCurrentImage.Cursor <- Input.Cursors.Arrow
178 borderCurrentImage.ReleaseMouseCapture()
179 args.Handled <- true)
180
181
182 (*let txtPatient: Controls.TextBox = ctrl "txtPatient"
183 txtPatient.TextChanged.AddHandler(fun obj args ->
184 state.PatientID <- txtPatient.Text)*)
185
186 (*saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;
187 saveFileDialog1.FilterIndex = 2 ;
188 saveFileDialog1.RestoreDirectory = true ;*)
189
190 // display mainWindow img
191 mainWindow.Root.Show()
192 app.Run()