1
2
3
4 __license__ = 'GPL'
5 __author__ = "R.Terry, K.Hilbert"
6
7
8 import sys
9 import logging
10 import datetime as pydt
11
12
13 import wx
14
15
16 if __name__ == '__main__':
17 sys.path.insert(0, '../../')
18 from Gnumed.pycommon import gmDispatcher
19 from Gnumed.pycommon.gmTools import decorate_window_title
20
21
22 _log = logging.getLogger('gm.ui')
23
24 edit_area_modes = ['new', 'edit', 'new_from_existing']
25
27 """Mixin for edit area panels providing generic functionality.
28
29 **************** start of template ****************
30
31 #====================================================================
32 # Class definition:
33
34 from Gnumed.wxGladeWidgets import wxgXxxEAPnl
35
36 class cXxxEAPnl(wxgXxxEAPnl.wxgXxxEAPnl, gmEditArea.cGenericEditAreaMixin):
37
38 def __init__(self, *args, **kwargs):
39
40 try:
41 data = kwargs['xxx']
42 del kwargs['xxx']
43 except KeyError:
44 data = None
45
46 wxgXxxEAPnl.wxgXxxEAPnl.__init__(self, *args, **kwargs)
47 gmEditArea.cGenericEditAreaMixin.__init__(self)
48
49 # Code using this mixin should set mode and data
50 # after instantiating the class:
51 self.mode = 'new'
52 self.data = data
53 if data is not None:
54 self.mode = 'edit'
55
56 #self.__init_ui()
57
58 #----------------------------------------------------------------
59 # def __init_ui(self):
60 # # adjust phrasewheels etc
61
62 #----------------------------------------------------------------
63 # generic Edit Area mixin API
64 #----------------------------------------------------------------
65 def _valid_for_save(self):
66
67 # its best to validate bottom -> top such that the
68 # cursor ends up in the topmost failing field
69
70 # remove when implemented:
71 return False
72
73 validity = True
74
75 if self._TCTRL_xxx.GetValue().strip() == u'':
76 validity = False
77 self.display_tctrl_as_valid(tctrl = self._TCTRL_xxx, valid = False)
78 self.StatusText = _('No entry in field xxx.')
79 self._TCTRL_xxx.SetFocus()
80 else:
81 self.display_tctrl_as_valid(tctrl = self._TCTRL_xxx, valid = True)
82
83 if self._PRW_xxx.GetData() is None:
84 validity = False
85 self._PRW_xxx.display_as_valid(False)
86 self.StatusText = _('No entry in field xxx.')
87 self._PRW_xxx.SetFocus()
88 else:
89 self._PRW_xxx.display_as_valid(True)
90
91 return validity
92
93 #----------------------------------------------------------------
94 def _save_as_new(self):
95
96 # remove when implemented:
97 return False
98
99 # save the data as a new instance
100 data = gmXXXX.create_xxxx()
101
102 data[''] = self._
103 data[''] = self._
104
105 data.save()
106
107 # must be done very late or else the property access
108 # will refresh the display such that later field
109 # access will return empty values
110 self.data = data
111 return False
112 return True
113
114 #----------------------------------------------------------------
115 def _save_as_update(self):
116
117 # remove when implemented:
118 return False
119
120 # update self.data and save the changes
121 self.data[''] = self._TCTRL_xxx.GetValue().strip()
122 self.data[''] = self._PRW_xxx.GetData()
123 self.data[''] = self._CHBOX_xxx.GetValue()
124 self.data.save()
125 return True
126
127 #----------------------------------------------------------------
128 def _refresh_as_new(self):
129 pass
130
131 #----------------------------------------------------------------
132 def _refresh_as_new_from_existing(self):
133 self._refresh_as_new()
134
135 #----------------------------------------------------------------
136 def _refresh_from_existing(self):
137 pass
138
139 #----------------------------------------------------------------
140 def set_fields(self, fields):
141 # <fields> must be a dict compatible with the
142 # structure of the business object this edit
143 # area is for,
144 # thusly, the edit area knows how to set its
145 # controls from it,
146 # <fields> doesn't have to contain all keys, rather:
147 # - missing ones are skipped
148 # - unknown ones are ignored
149 # each key must hold a dict with at least a key 'value'
150 # and _can_ contain another key 'data',
151 # 'value' and 'data' must be compatible with the
152 # control they go into,
153 # controls which don't require 'data' (say, RadioButton)
154 # will ignore an existing 'data' key
155 pass
156
157 #----------------------------------------------------------------
158
159 **************** end of template ****************
160 """
162 self.__mode = 'new'
163 self.__data = None
164 self.successful_save_msg = None
165 self.__tctrl_validity_colors = {
166 True: wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW),
167 False: 'pink'
168 }
169 self._refresh_as_new()
170
171
172
173
176
178 if mode not in edit_area_modes:
179 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
180 if mode == 'edit':
181 if self.__data is None:
182 raise ValueError('[%s] <mode> "edit" needs data value' % self.__class__.__name__)
183
184 prev_mode = self.__mode
185 self.__mode = mode
186 if mode != prev_mode:
187 self.refresh()
188
189 mode = property(_get_mode, _set_mode)
190
191
194
196 if data is None:
197 if self.__mode == 'edit':
198 raise ValueError('[%s] <mode> "edit" needs data value' % self.__class__.__name__)
199 self.__data = data
200 self.refresh()
201
202 data = property(_get_data, _set_data)
203
204
205 - def _set_status_text(self, msg, beep=False):
206 gmDispatcher.send(signal = 'statustext_ea', msg = msg, beep = beep)
207
208 StatusText = property(lambda x:x, _set_status_text)
209
210
211
212
214 """Invoked from the generic edit area dialog.
215
216 Invokes
217 _valid_for_save,
218 _save_as_new,
219 _save_as_update
220 on the implementing edit area as needed.
221
222 _save_as_* must set self.__data and return True/False
223 """
224 if not self._valid_for_save():
225 return False
226
227
228 gmDispatcher.send(signal = 'statustext_ea', msg = '')
229
230 if self.__mode in ['new', 'new_from_existing']:
231 if self._save_as_new():
232 self.mode = 'edit'
233 return True
234 return False
235
236 elif self.__mode == 'edit':
237 return self._save_as_update()
238
239 else:
240 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
241
242
244 """Invoked from the generic edit area dialog.
245
246 Invokes
247 _refresh_as_new()
248 _refresh_from_existing()
249 _refresh_as_new_from_existing()
250 on the implementing edit area as needed.
251
252 Then calls _valid_for_save().
253 """
254 if self.__mode == 'new':
255 result = self._refresh_as_new()
256 self._valid_for_save()
257 return result
258 elif self.__mode == 'edit':
259 result = self._refresh_from_existing()
260 self._valid_for_save()
261 return result
262 elif self.__mode == 'new_from_existing':
263 result = self._refresh_as_new_from_existing()
264 self._valid_for_save()
265 return result
266 else:
267 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
268
269
272
273
277
278
279 from Gnumed.wxGladeWidgets import wxgGenericEditAreaDlg2
280
282 """Dialog for parenting edit area panels with save/clear/next/cancel"""
283
284 _lucky_day = 1
285 _lucky_month = 4
286 _today = pydt.date.today()
287
289
290 new_ea = kwargs['edit_area']
291 del kwargs['edit_area']
292
293 if not isinstance(new_ea, cGenericEditAreaMixin):
294 raise TypeError('[%s]: edit area instance must be child of cGenericEditAreaMixin')
295
296 try:
297 single_entry = kwargs['single_entry']
298 del kwargs['single_entry']
299 except KeyError:
300 single_entry = False
301
302 try:
303 title = kwargs['title']
304 except KeyError:
305 title = self.__class__.__name__
306 kwargs['title'] = decorate_window_title(title)
307
308 wxgGenericEditAreaDlg2.wxgGenericEditAreaDlg2.__init__(self, *args, **kwargs)
309
310 self.left_extra_button = None
311
312 if cGenericEditAreaDlg2._today.day != cGenericEditAreaDlg2._lucky_day:
313 self._BTN_lucky.Enable(False)
314 self._BTN_lucky.Hide()
315 else:
316 if cGenericEditAreaDlg2._today.month != cGenericEditAreaDlg2._lucky_month:
317 self._BTN_lucky.Enable(False)
318 self._BTN_lucky.Hide()
319
320
321 dummy_ea_pnl = self._PNL_ea
322 ea_pnl_szr = dummy_ea_pnl.GetContainingSizer()
323 ea_pnl_parent = dummy_ea_pnl.GetParent()
324
325 dummy_ea_pnl.DestroyLater()
326 del dummy_ea_pnl
327 new_ea_min_size = new_ea.GetMinSize()
328 new_ea.Reparent(ea_pnl_parent)
329 self._PNL_ea = new_ea
330 ea_pnl_szr.Add(self._PNL_ea, 1, wx.EXPAND, 0)
331 ea_pnl_szr.SetMinSize(new_ea_min_size)
332 ea_pnl_szr.Fit(new_ea)
333
334
335 if single_entry:
336 self._BTN_forward.Enable(False)
337 self._BTN_forward.Hide()
338
339 self._adjust_clear_revert_buttons()
340
341
342 self._TCTRL_status.SetValue('')
343 gmDispatcher.connect(signal = 'statustext_ea', receiver = self._on_set_statustext)
344
345
346 main_szr = self.GetSizer()
347 main_szr.Fit(self)
348 self.Layout()
349
350
351 self._PNL_ea.refresh()
352
353
354 - def _on_set_statustext(self, msg=None, loglevel=None, beep=False):
355 if msg is None:
356 msg = ''
357 try:
358 self._TCTRL_status.SetValue(msg.strip())
359 if beep:
360 wx.Bell()
361 except RuntimeError:
362
363 pass
364
365
377
378
386
387
390
391
394
395
410
421
430
431
434
435
436
437
453
454 left_extra_button = property(lambda x:x, _set_left_extra_button)
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475 from Gnumed.pycommon import gmGuiBroker
476
477
478 _gb = gmGuiBroker.GuiBroker()
479
480 gmSECTION_SUMMARY = 1
481 gmSECTION_DEMOGRAPHICS = 2
482 gmSECTION_CLINICALNOTES = 3
483 gmSECTION_FAMILYHISTORY = 4
484 gmSECTION_PASTHISTORY = 5
485 gmSECTION_SCRIPT = 8
486 gmSECTION_REQUESTS = 9
487 gmSECTION_REFERRALS = 11
488 gmSECTION_RECALLS = 12
489
490 richards_blue = wx.Colour(0,0,131)
491 richards_aqua = wx.Colour(0,194,197)
492 richards_dark_gray = wx.Colour(131,129,131)
493 richards_light_gray = wx.Colour(255,255,255)
494 richards_coloured_gray = wx.Colour(131,129,131)
495
496
497 CONTROLS_WITHOUT_LABELS =['wxTextCtrl', 'cEditAreaField', 'wx.SpinCtrl', 'gmPhraseWheel', 'wx.ComboBox']
498
500 widget.SetForegroundColour(wx.Colour(255, 0, 0))
501 widget.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
502
515 if not isinstance(edit_area, cEditArea2):
516 raise TypeError('<edit_area> must be of type cEditArea2 but is <%s>' % type(edit_area))
517 wx.Dialog.__init__(self, parent, id, title, pos, size, style, name)
518 self.__wxID_BTN_SAVE = wx.NewId()
519 self.__wxID_BTN_RESET = wx.NewId()
520 self.__editarea = edit_area
521 self.__do_layout()
522 self.__register_events()
523
524
525
528
530 self.__editarea.Reparent(self)
531
532 self.__btn_SAVE = wx.Button(self, self.__wxID_BTN_SAVE, _("Save"))
533 self.__btn_SAVE.SetToolTip(_('save entry into medical record'))
534 self.__btn_RESET = wx.Button(self, self.__wxID_BTN_RESET, _("Reset"))
535 self.__btn_RESET.SetToolTip(_('reset entry'))
536 self.__btn_CANCEL = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
537 self.__btn_CANCEL.SetToolTip(_('discard entry and cancel'))
538
539 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
540 szr_buttons.Add(self.__btn_SAVE, 1, wx.EXPAND | wx.ALL, 1)
541 szr_buttons.Add(self.__btn_RESET, 1, wx.EXPAND | wx.ALL, 1)
542 szr_buttons.Add(self.__btn_CANCEL, 1, wx.EXPAND | wx.ALL, 1)
543
544 szr_main = wx.BoxSizer(wx.VERTICAL)
545 szr_main.Add(self.__editarea, 1, wx.EXPAND)
546 szr_main.Add(szr_buttons, 0, wx.EXPAND)
547
548 self.SetSizerAndFit(szr_main)
549
550
551
553
554 wx.EVT_BUTTON(self.__btn_SAVE, self.__wxID_BTN_SAVE, self._on_SAVE_btn_pressed)
555 wx.EVT_BUTTON(self.__btn_RESET, self.__wxID_BTN_RESET, self._on_RESET_btn_pressed)
556 wx.EVT_BUTTON(self.__btn_CANCEL, wx.ID_CANCEL, self._on_CANCEL_btn_pressed)
557
558 wx.EVT_CLOSE(self, self._on_CANCEL_btn_pressed)
559
560
561
562
563
564
565 return 1
566
568 if self.__editarea.save_data():
569 self.__editarea.Close()
570 self.EndModal(wx.ID_OK)
571 return
572 short_err = self.__editarea.get_short_error()
573 long_err = self.__editarea.get_long_error()
574 if (short_err is None) and (long_err is None):
575 long_err = _(
576 'Unspecified error saving data in edit area.\n\n'
577 'Programmer forgot to specify proper error\n'
578 'message in [%s].'
579 ) % self.__editarea.__class__.__name__
580 if short_err is not None:
581 gmDispatcher.send(signal = 'statustext', msg = short_err)
582 if long_err is not None:
583 gmGuiHelpers.gm_show_error(long_err, _('saving clinical data'))
584
586 self.__editarea.Close()
587 self.EndModal(wx.ID_CANCEL)
588
591
593 - def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL):
594
595 wx.Panel.__init__ (
596 self,
597 parent,
598 id,
599 pos = pos,
600 size = size,
601 style = style | wx.TAB_TRAVERSAL
602 )
603 self.SetBackgroundColour(wx.Colour(222,222,222))
604
605 self.data = None
606 self.fields = {}
607 self.prompts = {}
608 self._short_error = None
609 self._long_error = None
610 self._summary = None
611 self._patient = gmPerson.gmCurrentPatient()
612 self.__wxID_BTN_OK = wx.NewId()
613 self.__wxID_BTN_CLEAR = wx.NewId()
614 self.__do_layout()
615 self.__register_events()
616 self.Show()
617
618
619
621 """This needs to be overridden by child classes."""
622 self._long_error = _(
623 'Cannot save data from edit area.\n\n'
624 'Programmer forgot to override method:\n'
625 ' <%s.save_data>'
626 ) % self.__class__.__name__
627 return False
628
630 msg = _(
631 'Cannot reset fields in edit area.\n\n'
632 'Programmer forgot to override method:\n'
633 ' <%s.reset_ui>'
634 ) % self.__class__.__name__
635 gmGuiHelpers.gm_show_error(msg)
636
638 tmp = self._short_error
639 self._short_error = None
640 return tmp
641
643 tmp = self._long_error
644 self._long_error = None
645 return tmp
646
648 return _('<No embed string for [%s]>') % self.__class__.__name__
649
650
651
663
668
669
670
672 self.__deregister_events()
673 event.Skip()
674
676 """Only active if _make_standard_buttons was called in child class."""
677
678 try:
679 event.Skip()
680 if self.data is None:
681 self._save_new_entry()
682 self.reset_ui()
683 else:
684 self._save_modified_entry()
685 self.reset_ui()
686 except Exception as err:
687
688
689 gmGuiHelpers.gm_show_error (err, _("Invalid Input"))
690 except:
691 _log.exception( "save data problem in [%s]" % self.__class__.__name__)
692
694 """Only active if _make_standard_buttons was called in child class."""
695
696 self.reset_ui()
697 event.Skip()
698
700 self.__deregister_events()
701
702 if not self._patient.connected:
703 return True
704
705
706
707
708 return True
709 _log.error('[%s] lossage' % self.__class__.__name__)
710 return False
711
713 """Just before new patient becomes active."""
714
715 if not self._patient.connected:
716 return True
717
718
719
720
721 return True
722 _log.error('[%s] lossage' % self.__class__.__name__)
723 return False
724
726 """Just after new patient became active."""
727
728 self.reset_ui()
729
730
731
733
734
735 self._define_prompts()
736 self._define_fields(parent = self)
737 if len(self.fields) != len(self.prompts):
738 _log.error('[%s]: #fields != #prompts' % self.__class__.__name__)
739 return None
740
741
742 szr_main_fgrid = wx.FlexGridSizer(rows = len(self.prompts), cols=2)
743 color = richards_aqua
744 lines = self.prompts.keys()
745 lines.sort()
746 for line in lines:
747
748 label, color, weight = self.prompts[line]
749
750 prompt = wx.StaticText (
751 parent = self,
752 id = -1,
753 label = label,
754 style = wx.ALIGN_CENTRE
755 )
756
757 prompt.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
758 prompt.SetForegroundColour(color)
759 prompt.SetBackgroundColour(richards_light_gray)
760 szr_main_fgrid.Add(prompt, flag=wx.EXPAND | wx.ALIGN_RIGHT)
761
762
763 szr_line = wx.BoxSizer(wx.HORIZONTAL)
764 positions = self.fields[line].keys()
765 positions.sort()
766 for pos in positions:
767 field, weight = self.fields[line][pos]
768
769 szr_line.Add(field, weight, wx.EXPAND)
770 szr_main_fgrid.Add(szr_line, flag=wx.GROW | wx.ALIGN_LEFT)
771
772
773 szr_main_fgrid.AddGrowableCol(1)
774
775
776
777
778
779
780
781 self.SetSizerAndFit(szr_main_fgrid)
782
783
784
785
787 """Child classes override this to define their prompts using _add_prompt()"""
788 _log.error('missing override in [%s]' % self.__class__.__name__)
789
791 """Add a new prompt line.
792
793 To be used from _define_fields in child classes.
794
795 - label, the label text
796 - color
797 - weight, the weight given in sizing the various rows. 0 means the row
798 always has minimum size
799 """
800 self.prompts[line] = (label, color, weight)
801
803 """Defines the fields.
804
805 - override in child classes
806 - mostly uses _add_field()
807 """
808 _log.error('missing override in [%s]' % self.__class__.__name__)
809
810 - def _add_field(self, line=None, pos=None, widget=None, weight=0):
811 if None in (line, pos, widget):
812 _log.error('argument error in [%s]: line=%s, pos=%s, widget=%s' % (self.__class__.__name__, line, pos, widget))
813 if line not in self.fields:
814 self.fields[line] = {}
815 self.fields[line][pos] = (widget, weight)
816
834
835
836
837
839 - def __init__ (self, parent, id = -1, pos = wx.DefaultPosition, size=wx.DefaultSize):
842
844 - def __init__(self, parent, id, pos, size, style):
845
846 print("class [%s] is deprecated, use cEditArea2 instead" % self.__class__.__name__)
847
848
849 wx.Panel.__init__(self, parent, id, pos=pos, size=size, style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
850 self.SetBackgroundColour(wx.Colour(222,222,222))
851
852 self.data = None
853 self.fields = {}
854 self.prompts = {}
855
856 ID_BTN_OK = wx.NewId()
857 ID_BTN_CLEAR = wx.NewId()
858
859 self.__do_layout()
860
861
862
863
864
865
866 self._patient = gmPerson.gmCurrentPatient()
867 self.__register_events()
868 self.Show(True)
869
870
871
873
874 self._define_prompts()
875 self.fields_pnl = wx.Panel(self, -1, style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
876 self._define_fields(parent = self.fields_pnl)
877
878 szr_prompts = self.__generate_prompts()
879 szr_fields = self.__generate_fields()
880
881
882 self.szr_main_panels = wx.BoxSizer(wx.HORIZONTAL)
883 self.szr_main_panels.Add(szr_prompts, 11, wx.EXPAND)
884 self.szr_main_panels.Add(5, 0, 0, wx.EXPAND)
885 self.szr_main_panels.Add(szr_fields, 90, wx.EXPAND)
886
887
888
889 self.szr_central_container = wx.BoxSizer(wx.HORIZONTAL)
890 self.szr_central_container.Add(self.szr_main_panels, 1, wx.EXPAND | wx.ALL, 5)
891
892
893 self.SetAutoLayout(True)
894 self.SetSizer(self.szr_central_container)
895 self.szr_central_container.Fit(self)
896
898 if len(self.fields) != len(self.prompts):
899 _log.error('[%s]: #fields != #prompts' % self.__class__.__name__)
900 return None
901
902 prompt_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
903 prompt_pnl.SetBackgroundColour(richards_light_gray)
904
905 color = richards_aqua
906 lines = self.prompts.keys()
907 lines.sort()
908 self.prompt_widget = {}
909 for line in lines:
910 label, color, weight = self.prompts[line]
911 self.prompt_widget[line] = self.__make_prompt(prompt_pnl, "%s " % label, color)
912
913 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
914 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
915 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
916 szr_shadow_below_prompts.Add(5, 0, 0, wx.EXPAND)
917 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
918
919
920 vszr_prompts = wx.BoxSizer(wx.VERTICAL)
921 vszr_prompts.Add(prompt_pnl, 97, wx.EXPAND)
922 vszr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
923
924
925 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
926 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
927 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
928 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
929 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts, 1, wx.EXPAND)
930
931
932 hszr_prompts = wx.BoxSizer(wx.HORIZONTAL)
933 hszr_prompts.Add(vszr_prompts, 10, wx.EXPAND)
934 hszr_prompts.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
935
936 return hszr_prompts
937
939 self.fields_pnl.SetBackgroundColour(wx.Colour(222,222,222))
940
941 vszr = wx.BoxSizer(wx.VERTICAL)
942 lines = self.fields.keys()
943 lines.sort()
944 self.field_line_szr = {}
945 for line in lines:
946 self.field_line_szr[line] = wx.BoxSizer(wx.HORIZONTAL)
947 positions = self.fields[line].keys()
948 positions.sort()
949 for pos in positions:
950 field, weight = self.fields[line][pos]
951 self.field_line_szr[line].Add(field, weight, wx.EXPAND)
952 try:
953 vszr.Add(self.field_line_szr[line], self.prompts[line][2], flag = wx.EXPAND)
954 except KeyError:
955 _log.error("Error with line=%s, self.field_line_szr has key:%s; self.prompts has key: %s" % (
956 line,
957 (line in self.field_line_szr),
958 (line in self.prompts)
959 ))
960
961 self.fields_pnl.SetSizer(vszr)
962 vszr.Fit(self.fields_pnl)
963
964
965 shadow_below_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
966 shadow_below_edit_fields.SetBackgroundColour(richards_coloured_gray)
967 szr_shadow_below_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
968 szr_shadow_below_edit_fields.Add(5, 0, 0, wx.EXPAND)
969 szr_shadow_below_edit_fields.Add(shadow_below_edit_fields, 12, wx.EXPAND)
970
971
972 vszr_edit_fields = wx.BoxSizer(wx.VERTICAL)
973 vszr_edit_fields.Add(self.fields_pnl, 92, wx.EXPAND)
974 vszr_edit_fields.Add(szr_shadow_below_edit_fields, 5, wx.EXPAND)
975
976
977 shadow_rightof_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
978 shadow_rightof_edit_fields.SetBackgroundColour(richards_coloured_gray)
979 szr_shadow_rightof_edit_fields = wx.BoxSizer(wx.VERTICAL)
980 szr_shadow_rightof_edit_fields.Add(0, 5, 0, wx.EXPAND)
981 szr_shadow_rightof_edit_fields.Add(shadow_rightof_edit_fields, 1, wx.EXPAND)
982
983
984 hszr_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
985 hszr_edit_fields.Add(vszr_edit_fields, 89, wx.EXPAND)
986 hszr_edit_fields.Add(szr_shadow_rightof_edit_fields, 1, wx.EXPAND)
987
988 return hszr_edit_fields
989
991
992 prompt = wx.StaticText(
993 parent,
994 -1,
995 aLabel,
996 style = wx.ALIGN_RIGHT
997 )
998 prompt.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
999 prompt.SetForegroundColour(aColor)
1000 return prompt
1001
1002
1003
1005 """Add a new prompt line.
1006
1007 To be used from _define_fields in child classes.
1008
1009 - label, the label text
1010 - color
1011 - weight, the weight given in sizing the various rows. 0 means the rwo
1012 always has minimum size
1013 """
1014 self.prompts[line] = (label, color, weight)
1015
1016 - def _add_field(self, line=None, pos=None, widget=None, weight=0):
1017 if None in (line, pos, widget):
1018 _log.error('argument error in [%s]: line=%s, pos=%s, widget=%s' % (self.__class__.__name__, line, pos, widget))
1019 if line not in self.fields:
1020 self.fields[line] = {}
1021 self.fields[line][pos] = (widget, weight)
1022
1024 """Defines the fields.
1025
1026 - override in child classes
1027 - mostly uses _add_field()
1028 """
1029 _log.error('missing override in [%s]' % self.__class__.__name__)
1030
1032 _log.error('missing override in [%s]' % self.__class__.__name__)
1033
1047
1050
1052 _log.error('[%s] programmer forgot to define _save_data()' % self.__class__.__name__)
1053 _log.info('child classes of cEditArea *must* override this function')
1054 return False
1055
1056
1057
1059
1060 wx.EVT_BUTTON(self.btn_OK, ID_BTN_OK, self._on_OK_btn_pressed)
1061 wx.EVT_BUTTON(self.btn_Clear, ID_BTN_CLEAR, self._on_clear_btn_pressed)
1062
1063 wx.EVT_SIZE (self.fields_pnl, self._on_resize_fields)
1064
1065
1066 gmDispatcher.connect(signal = 'pre_patient_unselection', receiver = self._on_pre_patient_unselection)
1067 gmDispatcher.connect(signal = 'application_closing', receiver = self._on_application_closing)
1068 gmDispatcher.connect(signal = 'post_patient_selection', receiver = self.on_post_patient_selection)
1069
1070 return 1
1071
1072
1073
1075
1076 try:
1077 event.Skip()
1078 if self.data is None:
1079 self._save_new_entry()
1080 self.set_data()
1081 else:
1082 self._save_modified_entry()
1083 self.set_data()
1084 except Exception as err:
1085
1086
1087 gmGuiHelpers.gm_show_error (err, _("Invalid Input"))
1088 except:
1089 _log.exception( "save data problem in [%s]" % self.__class__.__name__)
1090
1095
1096 - def on_post_patient_selection( self, **kwds):
1097
1098 self.set_data()
1099
1101
1102 if not self._patient.connected:
1103 return True
1104 if self._save_data():
1105 return True
1106 _log.error('[%s] lossage' % self.__class__.__name__)
1107 return False
1108
1110
1111 if not self._patient.connected:
1112 return True
1113 if self._save_data():
1114 return True
1115 _log.error('[%s] lossage' % self.__class__.__name__)
1116 return False
1117
1119 self.fields_pnl.Layout()
1120
1121 for i in self.field_line_szr.keys():
1122
1123 pos = self.field_line_szr[i].GetPosition()
1124
1125 self.prompt_widget[i].SetPosition((0, pos.y))
1126
1128 - def __init__(self, parent, id, aType = None):
1129
1130 print("class [%s] is deprecated, use cEditArea2 instead" % self.__class__.__name__)
1131
1132
1133 if aType not in _known_edit_area_types:
1134 _log.error('unknown edit area type: [%s]' % aType)
1135 raise gmExceptions.ConstructorError('unknown edit area type: [%s]' % aType)
1136 self._type = aType
1137
1138
1139 cEditArea.__init__(self, parent, id)
1140
1141 self.input_fields = {}
1142
1143 self._postInit()
1144 self.old_data = {}
1145
1146 self._patient = gmPerson.gmCurrentPatient()
1147 self.Show(True)
1148
1149
1150
1151
1152
1153
1155
1156 prompt_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
1157 prompt_pnl.SetBackgroundColour(richards_light_gray)
1158
1159 gszr = wx.FlexGridSizer (len(prompt_labels)+1, 1, 2, 2)
1160 color = richards_aqua
1161 for prompt in prompt_labels:
1162 label = self.__make_prompt(prompt_pnl, "%s " % prompt, color)
1163 gszr.Add(label, 0, wx.EXPAND | wx.ALIGN_RIGHT)
1164 color = richards_blue
1165 gszr.RemoveGrowableRow (line-1)
1166
1167 prompt_pnl.SetSizer(gszr)
1168 gszr.Fit(prompt_pnl)
1169 prompt_pnl.SetAutoLayout(True)
1170
1171
1172 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1173 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
1174 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
1175 szr_shadow_below_prompts.Add(5, 0, 0, wx.EXPAND)
1176 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
1177
1178
1179 vszr_prompts = wx.BoxSizer(wx.VERTICAL)
1180 vszr_prompts.Add(prompt_pnl, 97, wx.EXPAND)
1181 vszr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
1182
1183
1184 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1185 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
1186 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
1187 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
1188 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts,1,wx.EXPAND)
1189
1190
1191 hszr_prompts = wx.BoxSizer(wx.HORIZONTAL)
1192 hszr_prompts.Add(vszr_prompts, 10, wx.EXPAND)
1193 hszr_prompts.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
1194
1195 return hszr_prompts
1196
1198 _log.error('programmer forgot to define edit area lines for [%s]' % self._type)
1199 _log.info('child classes of gmEditArea *must* override this function')
1200 return []
1201
1203
1204 fields_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
1205 fields_pnl.SetBackgroundColour(wx.Colour(222,222,222))
1206
1207 gszr = wx.GridSizer(len(_prompt_defs[self._type]), 1, 2, 2)
1208
1209
1210 lines = self._make_edit_lines(parent = fields_pnl)
1211
1212 self.lines = lines
1213 if len(lines) != len(_prompt_defs[self._type]):
1214 _log.error('#(edit lines) not equal #(prompts) for [%s], something is fishy' % self._type)
1215 for line in lines:
1216 gszr.Add(line, 0, wx.EXPAND | wx.ALIGN_LEFT)
1217
1218 fields_pnl.SetSizer(gszr)
1219 gszr.Fit(fields_pnl)
1220 fields_pnl.SetAutoLayout(True)
1221
1222
1223 shadow_below_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1224 shadow_below_edit_fields.SetBackgroundColour(richards_coloured_gray)
1225 szr_shadow_below_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
1226 szr_shadow_below_edit_fields.Add(5, 0, 0, wx.EXPAND)
1227 szr_shadow_below_edit_fields.Add(shadow_below_edit_fields, 12, wx.EXPAND)
1228
1229
1230 vszr_edit_fields = wx.BoxSizer(wx.VERTICAL)
1231 vszr_edit_fields.Add(fields_pnl, 92, wx.EXPAND)
1232 vszr_edit_fields.Add(szr_shadow_below_edit_fields, 5, wx.EXPAND)
1233
1234
1235 shadow_rightof_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1236 shadow_rightof_edit_fields.SetBackgroundColour(richards_coloured_gray)
1237 szr_shadow_rightof_edit_fields = wx.BoxSizer(wx.VERTICAL)
1238 szr_shadow_rightof_edit_fields.Add(0, 5, 0, wx.EXPAND)
1239 szr_shadow_rightof_edit_fields.Add(shadow_rightof_edit_fields, 1, wx.EXPAND)
1240
1241
1242 hszr_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
1243 hszr_edit_fields.Add(vszr_edit_fields, 89, wx.EXPAND)
1244 hszr_edit_fields.Add(szr_shadow_rightof_edit_fields, 1, wx.EXPAND)
1245
1246 return hszr_edit_fields
1247
1250
1255
1257 map = {}
1258 for k in self.input_fields.keys():
1259 map[k] = ''
1260 return map
1261
1262
1264 self._default_init_fields()
1265
1266
1267
1268
1269
1271 _log.warning("you may want to override _updateUI for [%s]" % self.__class__.__name__)
1272
1273
1274 - def _postInit(self):
1275 """override for further control setup"""
1276 pass
1277
1278
1280 szr = wx.BoxSizer(wx.HORIZONTAL)
1281 szr.Add( widget, weight, wx.EXPAND)
1282 szr.Add( 0,0, spacerWeight, wx.EXPAND)
1283 return szr
1284
1286
1287 cb = wx.CheckBox( parent, -1, _(title))
1288 cb.SetForegroundColour( richards_blue)
1289 return cb
1290
1291
1292
1294 """this is a utlity method to add extra columns"""
1295
1296 if "extraColumns" in self.__class__.__dict__:
1297 for x in self.__class__.extraColumns:
1298 lines = self._addColumn(parent, lines, x, weightMap)
1299 return lines
1300
1301
1302 - def _addColumn(self, parent, lines, extra, weightMap = {}, existingWeight = 5 , extraWeight = 2):
1303 """
1304 # add ia extra column in the edit area.
1305 # preconditions:
1306 # parent is fields_pnl (weak);
1307 # self.input_fields exists (required);
1308 # ; extra is a list of tuples of format -
1309 # ( key for input_fields, widget label , widget class to instantiate )
1310 """
1311 newlines = []
1312 i = 0
1313 for x in lines:
1314
1315 if x in weightMap:
1316 (existingWeight, extraWeight) = weightMap[x]
1317
1318 szr = wx.BoxSizer(wx.HORIZONTAL)
1319 szr.Add( x, existingWeight, wx.EXPAND)
1320 if i < len(extra) and extra[i] is not None:
1321 (inputKey, widgetLabel, aclass) = extra[i]
1322 if aclass.__name__ in CONTROLS_WITHOUT_LABELS:
1323 szr.Add( self._make_prompt(parent, widgetLabel, richards_blue) )
1324 widgetLabel = ""
1325
1326 w = aclass( parent, -1, widgetLabel)
1327 if not aclass.__name__ in CONTROLS_WITHOUT_LABELS:
1328 w.SetForegroundColour(richards_blue)
1329
1330 szr.Add(w, extraWeight , wx.EXPAND)
1331
1332
1333 self.input_fields[inputKey] = w
1334
1335 newlines.append(szr)
1336 i += 1
1337 return newlines
1338
1358
1361
1364
1370
1381
1382 -class gmPastHistoryEditArea(gmEditArea):
1383
1384 - def __init__(self, parent, id):
1385 gmEditArea.__init__(self, parent, id, aType = 'past history')
1386
1387 - def _define_prompts(self):
1388 self._add_prompt(line = 1, label = _("When Noted"))
1389 self._add_prompt(line = 2, label = _("Laterality"))
1390 self._add_prompt(line = 3, label = _("Condition"))
1391 self._add_prompt(line = 4, label = _("Notes"))
1392 self._add_prompt(line = 6, label = _("Status"))
1393 self._add_prompt(line = 7, label = _("Progress Note"))
1394 self._add_prompt(line = 8, label = '')
1395
1396 - def _define_fields(self, parent):
1397
1398 self.fld_date_noted = gmDateTimeInput.gmDateInput(
1399 parent = parent,
1400 id = -1,
1401 style = wx.SIMPLE_BORDER
1402 )
1403 self._add_field(
1404 line = 1,
1405 pos = 1,
1406 widget = self.fld_date_noted,
1407 weight = 2
1408 )
1409 self._add_field(
1410 line = 1,
1411 pos = 2,
1412 widget = cPrompt_edit_area(parent,-1, _("Age")),
1413 weight = 0)
1414
1415 self.fld_age_noted = cEditAreaField(parent)
1416 self._add_field(
1417 line = 1,
1418 pos = 3,
1419 widget = self.fld_age_noted,
1420 weight = 2
1421 )
1422
1423
1424 self.fld_laterality_none= wx.RadioButton(parent, -1, _("N/A"))
1425 self.fld_laterality_left= wx.RadioButton(parent, -1, _("L"))
1426 self.fld_laterality_right= wx.RadioButton(parent, -1, _("R"))
1427 self.fld_laterality_both= wx.RadioButton(parent, -1, _("both"))
1428 self._add_field(
1429 line = 2,
1430 pos = 1,
1431 widget = self.fld_laterality_none,
1432 weight = 0
1433 )
1434 self._add_field(
1435 line = 2,
1436 pos = 2,
1437 widget = self.fld_laterality_left,
1438 weight = 0
1439 )
1440 self._add_field(
1441 line = 2,
1442 pos = 3,
1443 widget = self.fld_laterality_right,
1444 weight = 1
1445 )
1446 self._add_field(
1447 line = 2,
1448 pos = 4,
1449 widget = self.fld_laterality_both,
1450 weight = 1
1451 )
1452
1453 self.fld_condition= cEditAreaField(parent)
1454 self._add_field(
1455 line = 3,
1456 pos = 1,
1457 widget = self.fld_condition,
1458 weight = 6
1459 )
1460
1461 self.fld_notes= cEditAreaField(parent)
1462 self._add_field(
1463 line = 4,
1464 pos = 1,
1465 widget = self.fld_notes,
1466 weight = 6
1467 )
1468
1469 self.fld_significant= wx.CheckBox(
1470 parent,
1471 -1,
1472 _("significant"),
1473 style = wx.NO_BORDER
1474 )
1475 self.fld_active= wx.CheckBox(
1476 parent,
1477 -1,
1478 _("active"),
1479 style = wx.NO_BORDER
1480 )
1481
1482 self._add_field(
1483 line = 5,
1484 pos = 1,
1485 widget = self.fld_significant,
1486 weight = 0
1487 )
1488 self._add_field(
1489 line = 5,
1490 pos = 2,
1491 widget = self.fld_active,
1492 weight = 0
1493 )
1494
1495 self.fld_progress= cEditAreaField(parent)
1496 self._add_field(
1497 line = 6,
1498 pos = 1,
1499 widget = self.fld_progress,
1500 weight = 6
1501 )
1502
1503
1504 self._add_field(
1505 line = 7,
1506 pos = 4,
1507 widget = self._make_standard_buttons(parent),
1508 weight = 2
1509 )
1510
1511 - def _postInit(self):
1512 return
1513
1514 wx.EVT_KILL_FOCUS( self.fld_age_noted, self._ageKillFocus)
1515 wx.EVT_KILL_FOCUS( self.fld_date_noted, self._yearKillFocus)
1516
1517 - def _ageKillFocus( self, event):
1518
1519 event.Skip()
1520 try :
1521 year = self._getBirthYear() + int(self.fld_age_noted.GetValue().strip() )
1522 self.fld_date_noted.SetValue( str (year) )
1523 except:
1524 pass
1525
1526 - def _getBirthYear(self):
1527 try:
1528 birthyear = int(str(self._patient['dob']).split('-')[0])
1529 except:
1530
1531 birthyear = 1
1532
1533 return birthyear
1534
1535 - def _yearKillFocus( self, event):
1536 event.Skip()
1537 try:
1538 age = int(self.fld_date_noted.GetValue().strip() ) - self._getBirthYear()
1539 self.fld_age_noted.SetValue( str (age) )
1540 except:
1541 pass
1542
1543 __init_values = {
1544 "condition": "",
1545 "notes1": "",
1546 "notes2": "",
1547 "age": "",
1548
1549 "progress": "",
1550 "active": 1,
1551 "operation": 0,
1552 "confidential": 0,
1553 "significant": 1,
1554 "both": 0,
1555 "left": 0,
1556 "right": 0,
1557 "none" : 1
1558 }
1559
1560 - def _getDefaultAge(self):
1561 try:
1562
1563 return 1
1564 except:
1565 return 0
1566
1567 - def _get_init_values(self):
1568 values = gmPastHistoryEditArea.__init_values
1569 values["age"] = str( self._getDefaultAge())
1570 return values
1571
1572 - def _save_data(self):
1573 clinical = self._patient.emr.get_past_history()
1574 if self.getDataId() is None:
1575 id = clinical.create_history( self.get_fields_formatting_values() )
1576 self.setDataId(id)
1577 return
1578
1579 clinical.update_history( self.get_fields_formatting_values(), self.getDataId() )
1580
1581
1591
1593 self._add_prompt (line = 1, label = _ ("Specialty"))
1594 self._add_prompt (line = 2, label = _ ("Name"))
1595 self._add_prompt (line = 3, label = _ ("Address"))
1596 self._add_prompt (line = 4, label = _ ("Options"))
1597 self._add_prompt (line = 5, label = _("Text"), weight =6)
1598 self._add_prompt (line = 6, label = "")
1599
1601 self.fld_specialty = gmPhraseWheel.cPhraseWheel (
1602 parent = parent,
1603 id = -1,
1604 style = wx.SIMPLE_BORDER
1605 )
1606
1607 self._add_field (
1608 line = 1,
1609 pos = 1,
1610 widget = self.fld_specialty,
1611 weight = 1
1612 )
1613 self.fld_name = gmPhraseWheel.cPhraseWheel (
1614 parent = parent,
1615 id = -1,
1616 style = wx.SIMPLE_BORDER
1617 )
1618
1619 self._add_field (
1620 line = 2,
1621 pos = 1,
1622 widget = self.fld_name,
1623 weight = 1
1624 )
1625 self.fld_address = wx.ComboBox (parent, -1, style = wx.CB_READONLY)
1626
1627 self._add_field (
1628 line = 3,
1629 pos = 1,
1630 widget = self.fld_address,
1631 weight = 1
1632 )
1633
1634
1635 self.fld_name.add_callback_on_selection(self.setAddresses)
1636
1637 self.fld_med = wx.CheckBox (parent, -1, _("Meds"), style=wx.NO_BORDER)
1638 self._add_field (
1639 line = 4,
1640 pos = 1,
1641 widget = self.fld_med,
1642 weight = 1
1643 )
1644 self.fld_past = wx.CheckBox (parent, -1, _("Past Hx"), style=wx.NO_BORDER)
1645 self._add_field (
1646 line = 4,
1647 pos = 4,
1648 widget = self.fld_past,
1649 weight = 1
1650 )
1651 self.fld_text = wx.TextCtrl (parent, -1, style= wx.TE_MULTILINE)
1652 self._add_field (
1653 line = 5,
1654 pos = 1,
1655 widget = self.fld_text,
1656 weight = 1)
1657
1658 self._add_field(
1659 line = 6,
1660 pos = 1,
1661 widget = self._make_standard_buttons(parent),
1662 weight = 1
1663 )
1664 return 1
1665
1667 """
1668 Doesn't accept any value as this doesn't make sense for this edit area
1669 """
1670 self.fld_specialty.SetValue ('')
1671 self.fld_name.SetValue ('')
1672 self.fld_address.Clear ()
1673 self.fld_address.SetValue ('')
1674 self.fld_med.SetValue (0)
1675 self.fld_past.SetValue (0)
1676 self.fld_text.SetValue ('')
1677 self.recipient = None
1678
1680 """
1681 Set the available addresses for the selected identity
1682 """
1683 if id is None:
1684 self.recipient = None
1685 self.fld_address.Clear ()
1686 self.fld_address.SetValue ('')
1687 else:
1688 self.recipient = gmDemographicRecord.cDemographicRecord_SQL (id)
1689 self.fld_address.Clear ()
1690 self.addr = self.recipient.getAddresses ('work')
1691 for i in self.addr:
1692 self.fld_address.Append (_("%(number)s %(street)s, %(urb)s %(postcode)s") % i, ('post', i))
1693 fax = self.recipient.getCommChannel (gmDemographicRecord.FAX)
1694 email = self.recipient.getCommChannel (gmDemographicRecord.EMAIL)
1695 if fax:
1696 self.fld_address.Append ("%s: %s" % (_("FAX"), fax), ('fax', fax))
1697 if email:
1698 self.fld_address.Append ("%s: %s" % (_("E-MAIL"), email), ('email', email))
1699
1700 - def _save_new_entry(self):
1701 """
1702 We are always saving a "new entry" here because data_ID is always None
1703 """
1704 if not self.recipient:
1705 raise UserWarning(_('must have a recipient'))
1706 if self.fld_address.GetSelection() == -1:
1707 raise UserWarning(_('must select address'))
1708 channel, addr = self.fld_address.GetClientData (self.fld_address.GetSelection())
1709 text = self.fld_text.GetValue()
1710 flags = {}
1711 flags['meds'] = self.fld_med.GetValue()
1712 flags['pasthx'] = self.fld_past.GetValue()
1713 if not gmReferral.create_referral (self._patient, self.recipient, channel, addr, text, flags):
1714 raise UserWarning('error sending form')
1715
1716
1717
1718
1719
1727
1728
1729
1731 _log.debug("making prescription lines")
1732 lines = []
1733 self.txt_problem = cEditAreaField(parent)
1734 self.txt_class = cEditAreaField(parent)
1735 self.txt_generic = cEditAreaField(parent)
1736 self.txt_drug_product = cEditAreaField(parent)
1737 self.txt_strength= cEditAreaField(parent)
1738 self.txt_directions= cEditAreaField(parent)
1739 self.txt_for = cEditAreaField(parent)
1740 self.txt_progress = cEditAreaField(parent)
1741
1742 lines.append(self.txt_problem)
1743 lines.append(self.txt_class)
1744 lines.append(self.txt_generic)
1745 lines.append(self.txt_drug_product)
1746 lines.append(self.txt_strength)
1747 lines.append(self.txt_directions)
1748 lines.append(self.txt_for)
1749 lines.append(self.txt_progress)
1750 lines.append(self._make_standard_buttons(parent))
1751 self.input_fields = {
1752 "problem": self.txt_problem,
1753 "class" : self.txt_class,
1754 "generic" : self.txt_generic,
1755 "prod" : self.txt_drug_product,
1756 "strength": self.txt_strength,
1757 "directions": self.txt_directions,
1758 "for" : self.txt_for,
1759 "progress": self.txt_progress
1760
1761 }
1762
1763 return self._makeExtraColumns( parent, lines)
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1782
1783
1784
1785
1786
1787
1790 wx.StaticText.__init__(self, parent, id, prompt, wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_LEFT)
1791 self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
1792 self.SetForegroundColour(aColor)
1793
1794
1795
1796
1797
1799 - def __init__(self, parent, id, prompt_labels):
1800 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
1801 self.SetBackgroundColour(richards_light_gray)
1802 gszr = wx.GridSizer (len(prompt_labels)+1, 1, 2, 2)
1803 color = richards_aqua
1804 for prompt_key in prompt_labels.keys():
1805 label = cPrompt_edit_area(self, -1, " %s" % prompt_labels[prompt_key], aColor = color)
1806 gszr.Add(label, 0, wx.EXPAND | wx.ALIGN_RIGHT)
1807 color = richards_blue
1808 self.SetSizer(gszr)
1809 gszr.Fit(self)
1810 self.SetAutoLayout(True)
1811
1812
1813
1814
1815
1816
1817
1818 -class EditTextBoxes(wx.Panel):
1819 - def __init__(self, parent, id, editareaprompts, section):
1820 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize,style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
1821 self.SetBackgroundColour(wx.Colour(222,222,222))
1822 self.parent = parent
1823
1824 self.gszr = wx.GridSizer(len(editareaprompts), 1, 2, 2)
1825
1826 if section == gmSECTION_SUMMARY:
1827 pass
1828 elif section == gmSECTION_DEMOGRAPHICS:
1829 pass
1830 elif section == gmSECTION_CLINICALNOTES:
1831 pass
1832 elif section == gmSECTION_FAMILYHISTORY:
1833 pass
1834 elif section == gmSECTION_PASTHISTORY:
1835 pass
1836
1837
1838 self.txt_condition = cEditAreaField(self,PHX_CONDITION,wx.DefaultPosition,wx.DefaultSize)
1839 self.rb_sideleft = wxRadioButton(self,PHX_LEFT, _(" (L) "), wx.DefaultPosition,wx.DefaultSize)
1840 self.rb_sideright = wxRadioButton(self, PHX_RIGHT, _("(R)"), wx.DefaultPosition,wx.DefaultSize,wx.SUNKEN_BORDER)
1841 self.rb_sideboth = wxRadioButton(self, PHX_BOTH, _("Both"), wx.DefaultPosition,wx.DefaultSize)
1842 rbsizer = wx.BoxSizer(wx.HORIZONTAL)
1843 rbsizer.Add(self.rb_sideleft,1,wx.EXPAND)
1844 rbsizer.Add(self.rb_sideright,1,wx.EXPAND)
1845 rbsizer.Add(self.rb_sideboth,1,wx.EXPAND)
1846 szr1 = wx.BoxSizer(wx.HORIZONTAL)
1847 szr1.Add(self.txt_condition, 4, wx.EXPAND)
1848 szr1.Add(rbsizer, 3, wx.EXPAND)
1849
1850
1851
1852
1853 self.txt_notes1 = cEditAreaField(self,PHX_NOTES,wx.DefaultPosition,wx.DefaultSize)
1854
1855 self.txt_notes2= cEditAreaField(self,PHX_NOTES2,wx.DefaultPosition,wx.DefaultSize)
1856
1857 self.txt_agenoted = cEditAreaField(self, PHX_AGE, wx.DefaultPosition, wx.DefaultSize)
1858 szr4 = wx.BoxSizer(wx.HORIZONTAL)
1859 szr4.Add(self.txt_agenoted, 1, wx.EXPAND)
1860 szr4.Add(5, 0, 5)
1861
1862 self.txt_yearnoted = cEditAreaField(self,PHX_YEAR,wx.DefaultPosition,wx.DefaultSize)
1863 szr5 = wx.BoxSizer(wx.HORIZONTAL)
1864 szr5.Add(self.txt_yearnoted, 1, wx.EXPAND)
1865 szr5.Add(5, 0, 5)
1866
1867 self.parent.cb_active = wx.CheckBox(self, PHX_ACTIVE, _("Active"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1868 self.parent.cb_operation = wx.CheckBox(self, PHX_OPERATION, _("Operation"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1869 self.parent.cb_confidential = wx.CheckBox(self, PHX_CONFIDENTIAL , _("Confidential"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1870 self.parent.cb_significant = wx.CheckBox(self, PHX_SIGNIFICANT, _("Significant"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1871 szr6 = wx.BoxSizer(wx.HORIZONTAL)
1872 szr6.Add(self.parent.cb_active, 1, wx.EXPAND)
1873 szr6.Add(self.parent.cb_operation, 1, wx.EXPAND)
1874 szr6.Add(self.parent.cb_confidential, 1, wx.EXPAND)
1875 szr6.Add(self.parent.cb_significant, 1, wx.EXPAND)
1876
1877 self.txt_progressnotes = cEditAreaField(self,PHX_PROGRESSNOTES ,wx.DefaultPosition,wx.DefaultSize)
1878
1879 szr8 = wx.BoxSizer(wx.HORIZONTAL)
1880 szr8.Add(5, 0, 6)
1881 szr8.Add(self._make_standard_buttons(), 0, wx.EXPAND)
1882
1883 self.gszr.Add(szr1,0,wx.EXPAND)
1884 self.gszr.Add(self.txt_notes1,0,wx.EXPAND)
1885 self.gszr.Add(self.txt_notes2,0,wx.EXPAND)
1886 self.gszr.Add(szr4,0,wx.EXPAND)
1887 self.gszr.Add(szr5,0,wx.EXPAND)
1888 self.gszr.Add(szr6,0,wx.EXPAND)
1889 self.gszr.Add(self.txt_progressnotes,0,wx.EXPAND)
1890 self.gszr.Add(szr8,0,wx.EXPAND)
1891
1892
1893 elif section == gmSECTION_SCRIPT:
1894 pass
1895 elif section == gmSECTION_REQUESTS:
1896 pass
1897 elif section == gmSECTION_RECALLS:
1898 pass
1899 else:
1900 pass
1901
1902 self.SetSizer(self.gszr)
1903 self.gszr.Fit(self)
1904
1905 self.SetAutoLayout(True)
1906 self.Show(True)
1907
1909 self.btn_OK = wx.Button(self, -1, _("Ok"))
1910 self.btn_Clear = wx.Button(self, -1, _("Clear"))
1911 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
1912 szr_buttons.Add(self.btn_OK, 1, wx.EXPAND, wx.ALL, 1)
1913 szr_buttons.Add(5, 0, 0)
1914 szr_buttons.Add(self.btn_Clear, 1, wx.EXPAND, wx.ALL, 1)
1915 return szr_buttons
1916
1918 - def __init__(self, parent, id, line_labels, section):
1919 _log.warning('***** old style EditArea instantiated, please convert *****')
1920
1921 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, style = wx.NO_BORDER)
1922 self.SetBackgroundColour(wx.Colour(222,222,222))
1923
1924
1925 prompts = gmPnlEditAreaPrompts(self, -1, line_labels)
1926
1927 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1928
1929 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
1930 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
1931 szr_shadow_below_prompts.Add(5,0,0,wx.EXPAND)
1932 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
1933
1934 szr_prompts = wx.BoxSizer(wx.VERTICAL)
1935 szr_prompts.Add(prompts, 97, wx.EXPAND)
1936 szr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
1937
1938
1939 edit_fields = EditTextBoxes(self, -1, line_labels, section)
1940
1941 shadow_below_editarea = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1942
1943 shadow_below_editarea.SetBackgroundColour(richards_coloured_gray)
1944 szr_shadow_below_editarea = wx.BoxSizer(wx.HORIZONTAL)
1945 szr_shadow_below_editarea.Add(5,0,0,wx.EXPAND)
1946 szr_shadow_below_editarea.Add(shadow_below_editarea, 12, wx.EXPAND)
1947
1948 szr_editarea = wx.BoxSizer(wx.VERTICAL)
1949 szr_editarea.Add(edit_fields, 92, wx.EXPAND)
1950 szr_editarea.Add(szr_shadow_below_editarea, 5, wx.EXPAND)
1951
1952
1953
1954 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1955 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
1956 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
1957 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
1958 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts,1,wx.EXPAND)
1959
1960 shadow_rightof_editarea = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1961 shadow_rightof_editarea.SetBackgroundColour(richards_coloured_gray)
1962 szr_shadow_rightof_editarea = wx.BoxSizer(wx.VERTICAL)
1963 szr_shadow_rightof_editarea.Add(0, 5, 0, wx.EXPAND)
1964 szr_shadow_rightof_editarea.Add(shadow_rightof_editarea, 1, wx.EXPAND)
1965
1966
1967 self.szr_main_panels = wx.BoxSizer(wx.HORIZONTAL)
1968 self.szr_main_panels.Add(szr_prompts, 10, wx.EXPAND)
1969 self.szr_main_panels.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
1970 self.szr_main_panels.Add(5, 0, 0, wx.EXPAND)
1971 self.szr_main_panels.Add(szr_editarea, 89, wx.EXPAND)
1972 self.szr_main_panels.Add(szr_shadow_rightof_editarea, 1, wx.EXPAND)
1973
1974
1975
1976 self.szr_central_container = wx.BoxSizer(wx.HORIZONTAL)
1977 self.szr_central_container.Add(self.szr_main_panels, 1, wx.EXPAND | wx.ALL, 5)
1978 self.SetSizer(self.szr_central_container)
1979 self.szr_central_container.Fit(self)
1980 self.SetAutoLayout(True)
1981 self.Show(True)
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258 if __name__ == "__main__":
2259
2260
2265 self._add_prompt(line=1, label='line 1')
2266 self._add_prompt(line=2, label='buttons')
2268
2269 self.fld_substance = cEditAreaField(parent)
2270 self._add_field(
2271 line = 1,
2272 pos = 1,
2273 widget = self.fld_substance,
2274 weight = 1
2275 )
2276
2277 self._add_field(
2278 line = 2,
2279 pos = 1,
2280 widget = self._make_standard_buttons(parent),
2281 weight = 1
2282 )
2283
2284 app = wxPyWidgetTester(size = (400, 200))
2285 app.SetWidget(cTestEditArea)
2286 app.MainLoop()
2287
2288
2289
2290
2291
2292
2293
2294