source: sasview/src/sas/sasview/wxcruft.py @ efe730d

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalcmagnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since efe730d was efe730d, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

move sasview to src/sas/sasview and refactor bundled apps for easier debugging

  • Property mode set to 100644
File size: 4.6 KB
Line 
1import inspect
2import wx
3from wx import Timer
4import wx._misc
5
6def call_later_fix():
7    # TODO: test if we need the fix
8    wx.CallLater = CallLater
9    wx.FutureCall = FutureCall
10    wx.PyTimer = PyTimer
11
12def trace_new_id():
13    wx.NewId = NewId
14
15def NewId():
16    id = wx._misc.NewId()
17    path, line, function = _get_caller()
18    if path == "sas/guiframe/utils.py":
19        # Special case: NewId is being called via an IdList request; we
20        # want to which widget triggered the request, not that it was
21        # triggered via IdList.
22        path, line, function = _get_caller(2)
23        tag = " via IdList"
24    elif path.endswith("/wxcruft.py"):
25        # Special case: NewId is being called via CallLater; we want to
26        # know where the CallLater was invoked.
27        path, line, function = _get_caller(1)
28        tag = " via CallLater"
29    else:
30        tag = ""
31    print "NewId %d from %s(%d):%s%s"%(id, path, line, function, tag)
32    return id
33
34def _get_caller(distance=0):
35    frame = inspect.stack()[distance+2]
36    path = frame[1]
37    index = path.find('/sas/')
38    if index == -1: index = path.find('\\sas\\')
39    return path[index+1:], frame[2], frame[3]
40
41
42
43# ==========================================================================
44# Hacked versions of CallLater and PyTimer so that the main GUI loop doesn't
45# eat wx ids.
46# Changed lines are marked #PAK
47# ==========================================================================
48
49# For backwards compatibility with 2.4
50class PyTimer(Timer):
51    def __init__(self, notify, *args, **kw):  #PAK
52        Timer.__init__(self, *args, **kw)     #PAK
53        self.notify = notify
54
55    def Notify(self):
56        if self.notify:
57            self.notify()
58
59
60class CallLater:
61    """
62    A convenience class for `wx.Timer`, that calls the given callable
63    object once after the given amount of milliseconds, passing any
64    positional or keyword args.  The return value of the callable is
65    availbale after it has been run with the `GetResult` method.
66
67    If you don't need to get the return value or restart the timer
68    then there is no need to hold a reference to this object.
69
70    :see: `wx.CallAfter`
71    """
72
73    __RUNNING = set()
74
75    def __init__(self, millis, callableObj, *args, **kwargs):
76        # print "=================== entering CallLater constructor"
77        assert callable(callableObj), "callableObj is not callable"
78        self.millis = millis
79        self.callable = callableObj
80        self.SetArgs(*args, **kwargs)
81        self.runCount = 0
82        self.running = False
83        self.hasRun = False
84        self.result = None
85        self.timer = None
86        self.id = wx.NewId()  # PAK
87        self.Start()
88
89
90    def Start(self, millis=None, *args, **kwargs):
91        """
92        (Re)start the timer
93        """
94        self.hasRun = False
95        if millis is not None:
96            self.millis = millis
97        if args or kwargs:
98            self.SetArgs(*args, **kwargs)
99        self.Stop()
100        self.timer = PyTimer(self.Notify, id=self.id)  # PAK
101        self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
102        self.running = True
103        self.__RUNNING.add(self)
104    Restart = Start
105
106
107    def Stop(self):
108        """
109        Stop and destroy the timer.
110        """
111        if self.timer is not None:
112            self.timer.Stop()
113            self.timer = None
114        self.__RUNNING.discard(self)
115
116
117    def GetInterval(self):
118        if self.timer is not None:
119            return self.timer.GetInterval()
120        else:
121            return 0
122
123
124    def IsRunning(self):
125        return self.timer is not None and self.timer.IsRunning()
126
127
128    def SetArgs(self, *args, **kwargs):
129        """
130        (Re)set the args passed to the callable object.  This is
131        useful in conjunction with Restart if you want to schedule a
132        new call to the same callable object but with different
133        parameters.
134        """
135        self.args = args
136        self.kwargs = kwargs
137
138
139    def HasRun(self):
140        return self.hasRun
141
142
143    def GetResult(self):
144        return self.result
145
146
147    def Notify(self):
148        """
149        The timer has expired so call the callable.
150        """
151        if self.callable and getattr(self.callable, 'im_self', True):
152            self.runCount += 1
153            self.running = False
154            self.result = self.callable(*self.args, **self.kwargs)
155        self.hasRun = True
156        if not self.running:
157            # if it wasn't restarted, then cleanup
158            wx.CallAfter(self.Stop)
159
160    Interval = property(GetInterval)
161    Result = property(GetResult)
162
163
164class FutureCall(CallLater):
165    """A compatibility alias for `CallLater`."""
Note: See TracBrowser for help on using the repository browser.