#!/usr/bin/env python _ = lambda x: x import string from wxPython.wx import * from wxPython.stc import * STYLE_HEADER=1 STYLE_TEXT=2 STYLE_KEYWORD=3 completions = ['oesophagus', 'febrile', 'phlegmon', 'anaesthetic', 'phenoxybenzylpenicillin', 'penicillinamine'] class SOAPTextCtrl (wxStyledTextCtrl): def __init__ (self, parent, id): wxStyledTextCtrl.__init__ (self, parent, id, size = wxSize (400, 400)) id = self.GetId () self.SetWrapMode (wxSTC_WRAP_WORD) self.StyleSetSpec (STYLE_HEADER, "fore:#7F11010,bold,face:Times,size:12") self.StyleSetSpec (STYLE_KEYWORD, "fore:#4040B0") self.SetEOLMode (wxSTC_EOL_LF) self.SetMarginWidth (1, 0) self.AutoCompStops ("()<>,.;:'\"[]{}\\|/? address@hidden&*") self.autocompstr = '' self.AutoCompSetSeparator (10) self.__write_headings () EVT_KEY_DOWN (self, self.__keypressed) EVT_LEFT_DOWN (self, self.__mouse_down) EVT_STC_USERLISTSELECTION (self, id, self.__userlist) def ClearAll (self): wxStyledTextCtrl.ClearAll (self) self.SetEOLMode (wxSTC_EOL_LF) self.__write_headings () def __write_headings (self): self.AddText ("""Subjective: Objective: Assessment: Plan: """) self.StartStyling (0, 0xFF) self.SetStyling (11, STYLE_HEADER) self.StartStyling (13, 0xFF) self.SetStyling (10, STYLE_HEADER) self.StartStyling (25, 0xFF) self.SetStyling (11, STYLE_HEADER) self.StartStyling (38, 0xFF) self.SetStyling (5, STYLE_HEADER) self.GotoPos (9) def __keypressed (self, event): pos = self.GetCurrentPos () if self.AutoCompActive (): event.Skip () else: if event.KeyCode () in [WXK_RETURN, WXK_RIGHT, WXK_DELETE]: if self.GetCharAt (pos) == 10: # we are at the end of a line pos += 1 if self.GetStyleAt (pos) == STYLE_HEADER: # the next line is a header doclen = self.GetLength () while pos < doclen and self.GetCharAt (pos) != 10: pos += 1 # go to the end of line self.GotoPos (pos) else: event.Skip () else: event.Skip () elif event.KeyCode () in [WXK_LEFT, WXK_BACK] and pos > 0 and self.GetStyleAt (pos-1) == STYLE_HEADER: # trying to move left onto a header, veto pass elif event.KeyCode () == WXK_UP: line = self.LineFromPosition (pos) col = self.GetColumn (pos) if line > 0: line -= 1 lineend = self.GetLineEndPosition (line) pos = self.PositionFromLine (line) + col if not (pos < lineend and self.GetStyleAt (pos) == STYLE_HEADER): event.Skip () else: self.GotoPos (lineend) elif event.KeyCode () == WXK_DOWN: line = self.LineFromPosition (pos) col = self.GetColumn (pos) line += 1 pos = self.PositionFromLine (line) + col lineend = self.GetLineEndPosition (line) if pos > 0 and not (pos < lineend and self.GetStyleAt (pos) == STYLE_HEADER): event.Skip () else: self.GotoPos (lineend) else: event.Skip () if event.KeyCode () < 255: ch = string.lower (chr (event.KeyCode ())) if ch in string.letters: self.autocompstr += ch if not self.AutoCompActive (): clist = [] for i in completions: if string.find (i, self.autocompstr) == 0: clist.append (i) if len (clist) > 0 and len (clist) < 7: clist.sort () self.UserListShow (1, string.join (clist, '\n')) else: if ch != '\r': self.autocompstr = '' def __userlist (self, event): pos = self.GetCurrentPos () self.SetTargetEnd (pos) start = pos - len (self.autocompstr) self.SetTargetStart (start) text = event.GetText () self.ReplaceTarget (text) self.StartStyling (start, 0xFF) self.SetStyling (len (text), STYLE_KEYWORD) self.GotoPos (start + len (text)) def __mouse_down (self, event): pos = self.PositionFromPoint (event.GetPosition ()) if self.GetStyleAt (pos) == STYLE_HEADER: doclen = self.GetLength () while pos < doclen and self.GetCharAt (pos) != 10: pos += 1 # go to the end of line self.GotoPos (pos) else: event.Skip () class MyFrame(wxFrame): def __init__(self, title): # begin wxGlade: MyFrame.__init__ wxFrame.__init__(self, None, wxNewId (), title) self.text_ctrl_1 = SOAPTextCtrl(self, -1) self.__do_layout() # end wxGlade def __do_layout(self): # begin wxGlade: MyFrame.__do_layout sizer_1 = wxBoxSizer(wxVERTICAL) sizer_1.Add(self.text_ctrl_1, 1, wxEXPAND, 0) self.SetAutoLayout(1) self.SetSizer(sizer_1) sizer_1.Fit(self) sizer_1.SetSizeHints(self) self.Layout() # end wxGlade # end of class MyFrame class MyApp (wxApp): def OnInit (self): frame = MyFrame ("Test SOAP") frame.Show () return 1 app = MyApp (0) app.MainLoop ()