gnumed-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnumed-devel] SOAP widget - Fabulous Brilliant


From: Richard Terry
Subject: Re: [Gnumed-devel] SOAP widget - Fabulous Brilliant
Date: Wed, 07 Jul 2004 18:23:06 +1000
User-agent: Mozilla Thunderbird 0.6 (X11/20040503)

Ian this is fabulous, brilliant, I'm so excited seeing this.

You have managed to build not only what I could see in my head but its functionality as well.

This little beast can replace ALL/MOST of the editing areas and in the process lead to integration and a huge saving in screen real-estate.

This becomes the central work space of the entire medical records program.
We can reproduce here just how we work from day to day.

The possibilites here are endless and would blow any existing medical records system out of the water. As the SOAP entry progresses, instead of having to 'change sections' as in the old design, now, with the use of keywords (eg script) the necessary edit area 'pops up' in a flat single bordered window (see attatched PNG file)- akin to your existing word-completion popup. I've done a mock up for writing a prescription from within the SOAP process (except here obviously I've used a complete wxWindow). The same mechanism would exist for writing referral letters, requests, recalls etc. Everything can emanate from the SOAP edit area.

In this example, having written a script for the amoxil, when the popup edit area is closed, the summary is placed in the SOAP after the word script (eg. script - amoxil syrup 250mg tds).

Because the edit area popups will be contained in the same type of pop-up style as your word lists - it all still looks and feels in the same plane.

We save an immense amount of space - screen real-estate, and can introduce (later) much smart stuff (inc decision support etc) using this concept.


Regards

Richard



Ian Haywood wrote:

Here is an example of a basic SOAP widget using wxStyledTextCtrl

It has the four headers "Subjective" "Objective" etc. which are coloured red 
and bold. Of course this can all be changed
to taste.
The user is not allowed to edit these headers (a few kludges to keep the cursor 
away from this text, seems to work)
Pressing return puts the cursor to the right place on the next line. The text 
will wrap if you try to go over the line.

The inbuilt autocompletion mechanism is used, currently with a fixed list but of course this can be anything grabbed from the backend as we do now with the phrasewheel. Completions are coloured light blue.

Please test and comment.

Ian

------------------------------------------------------------------------

#!/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 ()
------------------------------------------------------------------------

_______________________________________________
Gnumed-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/gnumed-devel

PNG image


reply via email to

[Prev in Thread] Current Thread [Next in Thread]