1 """GNUmed BMI calculator display widgets.
2
3 acknowledgments: Gui screen Design taken with permission from
4 DrsDesk BMICalc @ DrsDesk Software 1995-2002
5 and @ Dr.R Terry
6 Based on an early screen design by Michael Ireland
7 heavily commented for learning purposes by Dr. R Terry
8
9 copyright: authors
10
11 TODO:
12 - button QUIT
13 - patient related "normal" range
14 - factor out Algo parts
15 """
16
17
18
19 __version__ = "$Revision: 1.13 $"
20 __author__ = "Richard Terry <rterry@gnumed.net>,\
21 Michael Bonert <bonerti@mie.utoronto.ca>,\
22 Karsten Hilbert <Karsten.Hilbert@gmx.net>"
23 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
24
25 import os.path
26
27 try:
28 import wxversion
29 import wx
30 except ImportError:
31 from wxPython import wx
32
33 from Gnumed.pycommon import gmI18N
34
35
37
38 - def __init__(self, parent, color=wx.RED_BRUSH):
39 wx.Window.__init__(self, parent, -1, wx.DefaultPosition,size = (324,25))
40 wx.EVT_PAINT(self, self.OnPaint)
41
43 self.Draw(wx.PaintDC(self))
44
46 dc.BeginDrawing()
47 dc.Clear()
48
49
50
51
52 dc.SetBrush(wx.Brush(wx.Colour(194,194,197), wx.SOLID))
53 dc.SetPen(wx.Pen(wx.Colour(194,197,194), 1))
54 dc.DrawRectangle(0, 0, 324, 30)
55
56
57
58
59
60
61
62
63 dc.SetPen(wx.Pen(wx.Colour(0,0,0), 1))
64 dc.SetBrush(wx.Brush(wx.Colour(255,255,0), wx.SOLID))
65 dc.DrawEllipse(6, 5, 80,15)
66 dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
67 dc.SetTextForeground(wx.Colour(0,0,0))
68 te = dc.GetTextExtent(_("Underweight"))
69 dc.DrawText(_("Underweight"), 20,9)
70
71
72
73 dc.SetBrush(wx.Brush(wx.Colour(0,194,0), wx.SOLID))
74 dc.DrawEllipse(87, 5, 80,15)
75 dc.SetBrush(wx.Brush(wx.Colour(0,192,0), wx.SOLID))
76 dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
77 dc.SetTextForeground(wx.Colour(0,0,0))
78 te = dc.GetTextExtent(_("63< Normal >79"))
79 dc.DrawText(_("63 - Normal - 79"),95,8)
80
81
82
83 dc.SetBrush(wx.Brush(wx.Colour(255,128,0), wx.SOLID))
84 dc.DrawEllipse(168, 5, 80,15)
85 dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
86 dc.SetTextForeground(wx.Colour(0,0,0))
87 te = dc.GetTextExtent(_("Overweight"))
88 dc.DrawText(_("Overweight"), 180,9)
89
90
91
92
93 dc.SetBrush(wx.Brush(wx.Colour(192,0,0), wx.SOLID))
94 dc.DrawEllipse(250, 5, 60,15)
95 dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
96 dc.SetTextForeground(wx.Colour(0,0,0))
97 te = dc.GetTextExtent(_("Obese"))
98 dc.DrawText(_("Obese"), 267,9)
99 dc.EndDrawing()
100
102 self.color = color
103 self.Draw(wx.ClientDC(self))
104
107
108
109 self.low_norm_mass=''
110 self.upp_norm_mass=''
111 self.focus=0
112
113 wx.Panel.__init__ (
114 self,
115 parent = parent,
116 id = id,
117 pos = wx.DefaultPosition,
118 size = wx.DefaultSize,
119 style = wx.SIMPLE_BORDER | wx.TAB_TRAVERSAL
120 )
121
122
123
124 label = wx.StaticText(
125 self,
126 -1,
127 _("Current height/mass"),
128 wx.DefaultPosition,
129 wx.DefaultSize,
130 style = wx.ALIGN_CENTRE
131 )
132 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL, wx.BOLD,False,''))
133 label.SetForegroundColour(wx.Colour(0,0,131))
134 szr_upper_heading = wx.BoxSizer(wx.HORIZONTAL)
135 szr_upper_heading.Add(label,1,0)
136
137
138
139 label = wx.StaticText(self,-1,_("Height (cm)"),size = (1,20))
140 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
141 label.SetForegroundColour(wx.Colour(0,0,131))
142
143 self.txtheight = wx.TextCtrl(self,-1,"",size=(100,20))
144 self.txtheight.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
145
146 wx.EVT_TEXT(self, self.txtheight.GetId(), self.EvtText_height)
147 wx.EVT_SET_FOCUS(self.txtheight, self.OnSetFocus_height)
148 wx.EVT_CHAR(self.txtheight, self.EvtChar_height)
149
150 szr_height = wx.BoxSizer(wx.HORIZONTAL)
151 szr_height.Add((10,1),0,0)
152 szr_height.Add(label, 1, wx.ALIGN_CENTRE_VERTICAL, 0)
153 szr_height.Add(self.txtheight, 1, wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND, 0)
154
155
156
157 label = wx.StaticText(self,-1,_("Mass (kg)"),size = (20,20))
158 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
159 label.SetForegroundColour(wx.Colour(0,0,131))
160
161 self.txtmass = wx.TextCtrl(self,-1,"",size=(100,20))
162 self.txtmass.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
163
164 wx.EVT_TEXT(self, self.txtmass.GetId(), self.EvtText_mass)
165 wx.EVT_SET_FOCUS(self.txtmass, self.OnSetFocus_mass)
166 wx.EVT_CHAR(self.txtmass, self.EvtChar_mass)
167
168 szr_mass = wx.BoxSizer(wx.HORIZONTAL)
169 szr_mass.Add((10,1),0,0)
170 szr_mass.Add(label, 1, wx.ALIGN_CENTRE_VERTICAL, 0)
171 szr_mass.Add(self.txtmass, 1, wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND, 0)
172 szr_mass.Add((5,5),1,0)
173
174
175
176 label = wx.StaticText(self,-1,_("BMI"),size = (100,20))
177 label.SetFont(wx.Font(13,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
178 label.SetForegroundColour(wx.Colour(0,0,131))
179
180 self.txtbmi = wx.TextCtrl(self,-1,"",size=(100,20), style = wx.TE_READONLY)
181 self.txtbmi.Enable(False)
182 self.txtbmi.SetFont(wx.Font(13,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
183
184 szr_bmi = wx.BoxSizer(wx.HORIZONTAL)
185 szr_bmi.Add((10,1),0,0)
186 szr_bmi.Add(label,1,wx.ALIGN_CENTRE_VERTICAL|0,0)
187 szr_bmi.Add(self.txtbmi,1,wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND,0)
188 szr_bmi.Add((5,5),1,0)
189
190
191
192 bmi_colour_scale = BMI_Colour_Scale(self)
193 bmi_colour_scale.Enable(False)
194 szr_col_scale = wx.BoxSizer(wx.HORIZONTAL)
195 szr_col_scale.Add(bmi_colour_scale,1,wx.EXPAND)
196
197
198
199 self.slider = wx.Slider(self, -1, 15, 15, 34, wx.Point(30, 60),
200 wx.Size(324, -1),
201 wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
202 self.slider.SetTickFreq(1, 1)
203 wx.EVT_SCROLL(self.slider, self.SLIDER_EVT)
204 wx.EVT_CHAR(self.slider, self.EvtChar_slider)
205
206 szr_slider = wx.BoxSizer(wx.HORIZONTAL)
207 szr_slider.Add(self.slider,1,wx.EXPAND)
208
209
210
211
212 label = wx.StaticText(
213 self,
214 -1,
215 _("Adjusted Values"),
216 wx.DefaultPosition,
217 wx.DefaultSize,
218 style = wx.ALIGN_CENTRE
219 )
220 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL, wx.BOLD,False,''))
221 label.SetForegroundColour(wx.Colour(0,0,131))
222
223 szr_lower_heading = wx.BoxSizer(wx.HORIZONTAL)
224 szr_lower_heading.Add(label,1,wx.EXPAND)
225
226
227
228 label = wx.StaticText(self,-1,_("Goal mass"),size = (30,20))
229 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
230 label.SetForegroundColour(wx.Colour(0,0,131))
231
232 self.txtgoal= wx.TextCtrl(self,-1,"",size=(100,20))
233 self.txtgoal.SetFont(wx.Font(14,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
234
235 wx.EVT_TEXT(self, self.txtgoal.GetId(), self.EvtText_goal)
236 wx.EVT_SET_FOCUS(self.txtgoal, self.OnSetFocus_goal)
237 wx.EVT_CHAR(self.txtgoal, self.EvtChar_goal)
238
239 szr_goal_mass = wx.BoxSizer(wx.HORIZONTAL)
240 szr_goal_mass.Add((10,1),0,0)
241 szr_goal_mass.Add(label,1,wx.ALIGN_CENTRE_VERTICAL,0)
242 szr_goal_mass.Add(self.txtgoal,1,wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND, 0)
243
244
245
246 label = wx.StaticText(self,-1,_("kg to lose"),size = (30,20))
247 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
248 label.SetForegroundColour(wx.Colour(0,0,131))
249
250 self.txtloss= wx.TextCtrl(self,-1,"",size=(100,20))
251 self.txtloss.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
252
253 wx.EVT_TEXT(self, self.txtloss.GetId(), self.EvtText_loss)
254 wx.EVT_SET_FOCUS(self.txtloss, self.OnSetFocus_loss)
255 wx.EVT_CHAR(self.txtloss, self.EvtChar_loss)
256
257 szr_to_loose = wx.BoxSizer(wx.HORIZONTAL)
258 szr_to_loose.Add((10,1),0,0)
259 szr_to_loose.Add(label,1,wx.ALIGN_CENTRE_VERTICAL,0)
260 szr_to_loose.Add(self.txtloss,1,wx.ALIGN_CENTRE_VERTICAL | wx.EXPAND,0)
261
262
263
264 szr_main = wx.BoxSizer(wx.VERTICAL)
265 szr_main.Add((1,5),0,0)
266 szr_main.Add(szr_upper_heading,0,wx.EXPAND)
267 szr_main.Add((1,5),0,0)
268 szr_main.Add(szr_height,0,0)
269 szr_main.Add((1,5),0,0)
270 szr_main.Add(szr_mass,0,0)
271 szr_main.Add((1,5),0,0)
272 szr_main.Add(szr_bmi,0,0)
273 szr_main.Add((1,20),0,0)
274 szr_main.Add(szr_col_scale,0,0)
275 szr_main.Add(szr_slider,0,0)
276 szr_main.Add(szr_lower_heading,0,wx.EXPAND)
277 szr_main.Add((1,5),0,0)
278 szr_main.Add(szr_goal_mass,0,0)
279 szr_main.Add((1,5),0,0)
280 szr_main.Add(szr_to_loose,0,0)
281 szr_main.Add((1,20),0,0)
282
283
284
285 self.SetSizer(szr_main)
286 szr_main.Fit(self)
287 self.SetAutoLayout(True)
288 self.Show(True)
289
290
291
293 self.focus=1
294 event.Skip()
295
297 self.focus=2
298 event.Skip()
299
301 self.focus=4
302 event.Skip()
303
305 self.focus=5
306 event.Skip()
307
308 - def EvtText_height(self, event):
309 if(self.focus==1):
310 self.calc_ideal_mass_range()
311 self.CalcBMI()
312
313 - def EvtText_mass(self, event):
314 if(self.focus==2):
315 self.CalcBMI()
316
317 - def EvtText_goal(self, event):
318 if(self.focus==4):
319 if(self.txtgoal.GetValue()!=''):
320 try:
321 self.txtloss.SetValue(str(eval(self.txtmass.GetValue())-eval(self.txtgoal.GetValue())))
322 self.CalcNEWBMI()
323 except:
324 pass
325 else:
326 self.txtloss.SetValue('')
327
328 - def EvtText_loss(self, event):
329 if(self.focus==5):
330 self.loss=event.GetString()
331
332 if(self.txtloss.GetValue()!=''):
333 try:
334 self.txtgoal.SetValue(str(eval(self.txtmass.GetValue())-eval(self.txtloss.GetValue())))
335 self.CalcNEWBMI()
336 except:
337 pass
338 else:
339 self.txtgoal.SetValue('')
340
342
343 try:
344 self.low_norm_mass=20.*((eval(self.txtheight.GetValue())/100.)**2)
345 self.upp_norm_mass=25.*((eval(self.txtheight.GetValue())/100.)**2)
346
347
348
349 except:
350 pass
351
353 if(self.txtheight.GetValue()=='' or self.txtmass.GetValue()==''):
354 self.txtbmi.SetValue('')
355 else:
356 try:
357 self.txtbmi.SetValue(str(round(eval(self.txtmass.GetValue())/((eval(self.txtheight.GetValue())/100.)**2),1)))
358
359
360
361 self.NEWBMI=round(round(eval(self.txtmass.GetValue())/((eval(self.txtheight.GetValue())/100.)**2),1),0)
362 self.slider.SetValue(int (self.NEWBMI))
363
364
365
366
367
368
369
370
371
372 except:
373 pass
374
376 self.NEWBMI=round(eval(self.txtgoal.GetValue())/((eval(self.txtheight.GetValue())/100.)**2),0)
377 self.slider.SetValue(int (self.NEWBMI))
378
380 self.NEWBMI=self.slider.GetValue()
381 try:
382 self.txtgoal.SetValue(str(round(self.NEWBMI*(eval(self.txtheight.GetValue())/100.)**2,1)))
383 self.txtloss.SetValue(str(eval(self.txtmass.GetValue())-eval(self.txtgoal.GetValue())))
384 except:
385 pass
386
387
393
399
405
411
417
418
419
420
421
422
424
426
427
428 wx.Frame.__init__(
429 self,
430 parent,
431 -1,
432 _("BMI Calculator"),
433 style = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.CAPTION | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.TAB_TRAVERSAL | wx.STAY_ON_TOP
434 )
435 wx.EVT_CLOSE(self, self.OnCloseWindow)
436
437
438
439
440 self.pnl_bmi = BMICalc_Panel(self,-1)
441
442
443
444
445
446
447
448
449
450
451
452 text4graph = wx.TextCtrl(
453 self,
454 -1,
455 "Hi Guys, this is a prototype BMI Calculator + graph.\n\n"
456 "Comments please to rterry@gnumed.net..\n\n"
457 "Can someone tell me how to centre this frame on the screen...\n\n"
458 "This text box needs to be replaced by a graph class....\n"
459 "which amongst other things could show this patients mass trends!!!!\n\n"
460 "The mass range on the green epilpse would be calculated for each patient...\n\n"
461 "BTW, don't worry about your weight, the 'normal' range (63-79) is hardcoded.",
462 size=(200, 100),
463 style = wx.TE_MULTILINE | wx.TE_READONLY
464 )
465
466
467 gszr_right_buttons = wx.GridSizer(1, 4, 1, 4)
468 gszr_right_buttons.AddMany([
469 (wx.Button(self, 1010, _('&Reset')), 0, wx.EXPAND)
470
471
472
473
474 ])
475
476 wx.EVT_BUTTON(self,1010,self.EvtReset)
477
478
479
480
481
482 szr_right_col = wx.BoxSizer(wx.VERTICAL)
483 szr_right_col.Add(text4graph,1,wx.EXPAND)
484 szr_right_col.Add((1,5),0,wx.EXPAND)
485 szr_right_col.Add(gszr_right_buttons,0,wx.EXPAND)
486
487
488
489
490
491
492
493
494 szr_main = wx.BoxSizer(wx.HORIZONTAL)
495 szr_main.Add(self.pnl_bmi, 0, wx.EXPAND | wx.ALL, 10)
496 szr_main.Add((5, 0), 0, wx.EXPAND)
497 szr_main.Add(szr_right_col, 1, wx.EXPAND | wx.ALL, 10)
498
499 self.SetSizer(szr_main)
500 szr_main.Fit(self)
501 self.SetAutoLayout(True)
502
503
504 if __name__ == '__main__':
505 png_fname = os.path.join('..', 'bitmaps', 'bmi_calculator.png')
506 else:
507 from Gnumed.pycommon import gmGuiBroker
508 gb = gmGuiBroker.GuiBroker()
509 png_fname = os.path.join(gb['gnumed_dir'], 'bitmaps', 'bmi_calculator.png')
510 icon = wx.EmptyIcon()
511 icon.LoadFile(png_fname, wx.BITMAP_TYPE_PNG)
512 self.SetIcon(icon)
513
515
516 self.pnl_bmi.low_norm_mass=''
517 self.pnl_bmi.upp_norm_mass=''
518
519
520 self.pnl_bmi.txtheight.SetValue('')
521 self.pnl_bmi.txtmass.SetValue('')
522 self.pnl_bmi.txtbmi.SetValue('')
523 self.pnl_bmi.txtgoal.SetValue('')
524 self.pnl_bmi.txtloss.SetValue('')
525 self.pnl_bmi.slider.SetValue(0)
526
527
530
533
536
539
540
541 if __name__ == '__main__':
542
545 frame = BMI_Frame(None)
546 frame.Show(True)
547 return True
548
549 wx.InitAllImageHandlers()
550 app = TestApp()
551 app.MainLoop()
552
553
554