Package Gnumed :: Package wxpython :: Module gmRegetMixin
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmRegetMixin

  1  """gmRegetMixin - GNUmed data change callback mixin. 
  2   
  3  Widget code can mix in this class as a base class and 
  4  thus gain the infrastructure to update it's display 
  5  when data changes. If the widget is not visible it will 
  6  only schedule refetching data from the business layer. 
  7  If it *is* visible it will immediately fetch and redisplay. 
  8   
  9  You must call cRegetOnPaintMixin.__init__() in your own 
 10  __init__() after calling __init__() on the appropriate 
 11  wx.Widgets class your widget inherits from. 
 12   
 13  You must then make sure to call _schedule_data_reget() 
 14  whenever you learn of backend data changes. This will 
 15  in most cases happen after you receive a gmDispatcher 
 16  signal indicating a change in the backend. 
 17   
 18  The _populate_with_data(self) method must be overriden in the 
 19  including class and must return True if the UI was successfully 
 20  repopulated with content. 
 21   
 22  @copyright: authors 
 23   
 24  Template for users: 
 25   
 26          #----------------------------------------------------- 
 27          # reget-on-paint mixin API 
 28          #----------------------------------------------------- 
 29          # remember to call 
 30          #       self._schedule_data_reget() 
 31          # whenever you learn of data changes from database listener 
 32          # threads, dispatcher signals etc. 
 33          def _populate_with_data(self): 
 34                  # fill the UI with data 
 35                  print "need to implement _populate_with_data" 
 36                  return False 
 37                  return True 
 38          #----------------------------------------------------- 
 39  """ 
 40  #=========================================================================== 
 41  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gmRegetMixin.py,v $ 
 42  # $Id: gmRegetMixin.py,v 1.30 2009/05/08 08:01:36 ncq Exp $ 
 43  __version__ = "$Revision: 1.30 $" 
 44  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
 45  __license__ = 'GPL (details at http://www.gnu.org)' 
 46   
 47  import wx 
 48   
 49  #=========================================================================== 
50 -class cRegetOnPaintMixin:
51 """Mixin to add redisplay_data-on-wx.EVT_PAINT aspect. 52 53 Any code mixing in this class will gain the mechanism 54 to reget data on wxPaint events. The code must be an 55 instance of a wx.Window and must implement a 56 _populate_with_data() method. It must also call 57 _schedule_data_reget() at appropriate times. 58 """
59 - def __init__(self):
60 self._data_stale = True 61 try: 62 wx.EVT_PAINT(self, self.__on_paint_event) 63 except: 64 print 'you likely need to call "cRegetOnPaintMixin.__init__(self)" later in %s__init__()' % self.__class__.__name__ 65 raise
66 #-----------------------------------------------------
67 - def __on_paint_event(self, event):
68 """Called just before the widget is repainted. 69 70 Checks whether data needs to be refetched. 71 """ 72 self.__repopulate_ui() 73 event.Skip()
74 #-----------------------------------------------------
75 - def __repopulate_ui(self):
76 """Checks whether data must be refetched and does so 77 78 Called on different occasions such as "notebook page 79 raised" or "paint event received". 80 """ 81 if self._data_stale: 82 self._data_stale = not self._populate_with_data() 83 84 return not self._data_stale
85 #----------------------------------------------------- 86 # API for child classes 87 #-----------------------------------------------------
88 - def _populate_with_data(self):
89 """Actually fills the UI with data. 90 91 This must be overridden in child classes ! 92 93 Must return True/False. 94 """ 95 raise NotImplementedError, "[%s] _populate_with_data() not implemented" % self.__class__.__name__
96 #-----------------------------------------------------
97 - def _schedule_data_reget(self):
98 """Flag data as stale and schedule refetch/redisplay. 99 100 - if not visible schedules refetch only 101 - if visible redisplays immediately (virtue of Refresh() 102 calling __on_paint_event() if visible) thereby invoking 103 the actual data refetch 104 105 Called by the child class whenever it learns of data changes 106 such as from database listener threads, dispatcher signals etc. 107 """ 108 self._data_stale = True 109 110 # Master Robin Dunn sayeth this is The Way(tm) but 111 # neither this: 112 #wx.GetApp().GetTopWindow().Refresh() 113 # nor this: 114 #top_parent = wx.GetTopLevelParent(self) 115 #top_parent.Refresh() 116 # appear to work as expected :-( 117 # The issues I have with them are: 118 # 1) It appears to cause refreshes "too often", eg whenever 119 # *any* child of self calls this method - but this may 120 # not matter much as only those that have self._data_stale 121 # set to True will trigger backend refetches. 122 # 2) Even this does not in all cases cause a proper redraw 123 # of the visible widgets - likely because nothing has 124 # really changed in them, visually. 125 126 # further testing by Hilmar revealed that the 127 # following appears to work: 128 self.Refresh() 129 # the logic should go like this: 130 # database insert -> after-insert trigger 131 # -> notify 132 # -> middleware listener 133 # -> flush optional middleware cache 134 # -> dispatcher signal to frontend listener*s* 135 # -> frontend listeners schedule a data reget and a Refresh() 136 # problem: those that are not visible are refreshed, too 137 # FIXME: is this last assumption true ? 138 return True
139 #----------------------------------------------------- 140 # notebook plugin API if needed 141 #-----------------------------------------------------
142 - def repopulate_ui(self):
143 """Just a glue method to make this compatible with notebook plugins.""" 144 self.__repopulate_ui()
145 #=========================================================================== 146 # main 147 #--------------------------------------------------------------------------- 148 if __name__ == '__main__': 149 print "no unit test available" 150 151 #=========================================================================== 152 # $Log: gmRegetMixin.py,v $ 153 # Revision 1.30 2009/05/08 08:01:36 ncq 154 # - template for subclasses 155 # 156 # Revision 1.29 2008/11/20 20:12:57 ncq 157 # - better docs 158 # 159 # Revision 1.28 2008/03/29 16:22:47 ncq 160 # - significant clarification 161 # 162 # Revision 1.27 2007/10/29 13:19:07 ncq 163 # - cleanup 164 # 165 # Revision 1.26 2006/05/31 09:48:14 ncq 166 # - cleanup 167 # 168 # Revision 1.25 2006/05/28 16:14:18 ncq 169 # - cleanup, remove gmLog dependancy, improve docs 170 # - comment out on-set-focus listening 171 # - lots of debugging help for the time being 172 # - add repopulate_ui() for external callers 173 # 174 # Revision 1.24 2005/09/28 21:27:30 ncq 175 # - a lot of wx2.6-ification 176 # 177 # Revision 1.23 2005/09/28 15:57:48 ncq 178 # - a whole bunch of wx.Foo -> wx.Foo 179 # 180 # Revision 1.22 2005/09/27 20:44:59 ncq 181 # - wx.wx* -> wx.* 182 # 183 # Revision 1.21 2005/09/26 18:01:51 ncq 184 # - use proper way to import wx26 vs wx2.4 185 # - note: THIS WILL BREAK RUNNING THE CLIENT IN SOME PLACES 186 # - time for fixup 187 # 188 # Revision 1.20 2005/08/03 20:02:11 ncq 189 # - Hilmar eventually seems to have found a way to 190 # update data in visible widgets immediately 191 # 192 # Revision 1.19 2005/07/31 16:23:27 ncq 193 # - Hilmar's latest refresh fixes 194 # 195 # Revision 1.18 2005/07/27 09:53:30 ncq 196 # - petty cleanup 197 # 198 # Revision 1.17 2005/07/26 19:24:26 hinnef 199 # - fixed refresh bug on MSW platform 200 # 201 # Revision 1.16 2005/06/07 09:05:53 ncq 202 # - better docs 203 # 204 # Revision 1.15 2005/05/29 22:06:19 ncq 205 # - unsuccessfully try yet another technique for forcing a repaint 206 # 207 # Revision 1.14 2005/05/24 19:46:47 ncq 208 # - call top level window refresh at the end of _schedule_data_reget() 209 # which should cause a repaint of the visible widgets, which in turn 210 # will cause them to reget data from the business objects which in 211 # turn will cause those to reload from the backend, suggested by 212 # Robin Dunn 213 # 214 # Revision 1.13 2005/05/17 08:07:19 ncq 215 # - cleanup 216 # 217 # Revision 1.12 2005/05/08 21:42:17 ncq 218 # - import gmLog 219 # 220 # Revision 1.11 2005/05/06 15:31:03 ncq 221 # - slightly improved docs 222 # 223 # Revision 1.10 2005/05/05 06:35:02 ncq 224 # - add some device context measurements in _schedule_data_reget 225 # so we can maybe find a way to detect whether we are indeed 226 # visible or obscured 227 # 228 # Revision 1.9 2005/04/30 13:32:14 sjtan 229 # 230 # if current wxWindow that inherits gmRegetMixin IsShown() is true, then it requires 231 # refresh, so Reget is not scheduled , but immediate. 232 # 233 # Revision 1.8 2005/03/20 17:51:41 ncq 234 # - although not sure whether conceptually it's the right thing to do it 235 # sure seems appropriated to Refresh() on focus events 236 # 237 # Revision 1.7 2005/01/13 14:27:33 ncq 238 # - grammar fix 239 # 240 # Revision 1.6 2004/10/17 15:52:21 ncq 241 # - cleanup 242 # 243 # Revision 1.5 2004/10/17 00:05:36 sjtan 244 # 245 # fixup for paint event re-entry when notification dialog occurs over medDocTree graphics 246 # area, and triggers another paint event, and another notification dialog , in a loop. 247 # Fixup is set flag to stop _repopulate_tree, and to only unset this flag when 248 # patient activating signal gmMedShowDocs to schedule_reget, which is overridden 249 # to include resetting of flag, before calling mixin schedule_reget. 250 # 251 # Revision 1.4 2004/09/05 14:55:19 ncq 252 # - improve comments, some cleanup 253 # 254 # Revision 1.3 2004/08/04 17:12:06 ncq 255 # - fix comment 256 # 257 # Revision 1.2 2004/08/02 17:52:54 hinnef 258 # Added hint to _repopulate_with_data return value 259 # 260 # Revision 1.1 2004/07/28 15:27:31 ncq 261 # - first checkin, used in gmVaccWidget 262 # 263 # 264