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
32 # listener threads, dispatcher signals etc.
33 #-----------------------------------------------------
34 def _populate_with_data(self):
35 # fill the UI with data
36 print "need to implement _populate_with_data"
37 return False
38 return True
39 #-----------------------------------------------------
40 """
41
42 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
43 __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
44
45 import wx
46
47
49 """Mixin to add redisplay_data-on-wx.EVT_PAINT aspect.
50
51 Any code mixing in this class will gain the mechanism
52 to reget data on wxPaint events. The code must be an
53 instance of a wx.Window and must implement a
54 _populate_with_data() method. It must also call
55 _schedule_data_reget() at appropriate times.
56 """
58 self._data_stale = True
59 try:
60 self.Bind(wx.EVT_PAINT, self.__on_paint_event)
61 except Exception:
62 print('you likely need to call "cRegetOnPaintMixin.__init__(self)" later in %s__init__()' % self.__class__.__name__)
63 raise
64
65
67 """Called just before the widget is repainted.
68
69 Checks whether data needs to be refetched.
70 """
71 self.__repopulate_ui()
72 event.Skip()
73
75 """Checks whether data must be refetched and does so
76
77 Called on different occasions such as "notebook page
78 raised" or "paint event received".
79 """
80 if not self._data_stale:
81 return True
82 repopulated = self._populate_with_data()
83 self._data_stale = (repopulated is False)
84 return repopulated
85
86
87
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
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 self.Refresh()
129
130
131
132
133
134
135
136
137
138 return True
139
140
141
143 """Just a glue method to make this compatible with notebook plugins."""
144 self.__repopulate_ui()
145
146
147
148
149 if __name__ == '__main__':
150 print("no unit test available")
151