Source code for sas.sasview.wxcruft

from __future__ import print_function

import inspect
import wx
from wx import Timer
import wx._misc

[docs]def call_later_fix(): # TODO: test if we need the fix wx.CallLater = CallLater wx.FutureCall = FutureCall wx.PyTimer = PyTimer
[docs]def trace_new_id(): wx.NewId = NewId
[docs]def NewId(): id = wx._misc.NewId() path, line, function = _get_caller() if path == "sas/guiframe/utils.py": # Special case: NewId is being called via an IdList request; we # want to which widget triggered the request, not that it was # triggered via IdList. path, line, function = _get_caller(2) tag = " via IdList" elif path.endswith("/wxcruft.py"): # Special case: NewId is being called via CallLater; we want to # know where the CallLater was invoked. path, line, function = _get_caller(1) tag = " via CallLater" else: tag = "" print("NewId %d from %s(%d):%s%s"%(id, path, line, function, tag)) return id
def _get_caller(distance=0): frame = inspect.stack()[distance+2] path = frame[1] index = path.find('/sas/') if index == -1: index = path.find('\\sas\\') return path[index+1:], frame[2], frame[3] # ========================================================================== # Hacked versions of CallLater and PyTimer so that the main GUI loop doesn't # eat wx ids. # Changed lines are marked #PAK # ========================================================================== # For backwards compatibility with 2.4
[docs]class PyTimer(Timer): def __init__(self, notify, *args, **kw): #PAK Timer.__init__(self, *args, **kw) #PAK self.notify = notify
[docs] def Notify(self): if self.notify: self.notify()
[docs]class CallLater: """ A convenience class for `wx.Timer`, that calls the given callable object once after the given amount of milliseconds, passing any positional or keyword args. The return value of the callable is availbale after it has been run with the `GetResult` method. If you don't need to get the return value or restart the timer then there is no need to hold a reference to this object. :see: `wx.CallAfter` """ __RUNNING = set() def __init__(self, millis, callableObj, *args, **kwargs): # print "=================== entering CallLater constructor" assert callable(callableObj), "callableObj is not callable" self.millis = millis self.callable = callableObj self.SetArgs(*args, **kwargs) self.runCount = 0 self.running = False self.hasRun = False self.result = None self.timer = None self.id = wx.NewId() # PAK self.Start()
[docs] def Start(self, millis=None, *args, **kwargs): """ (Re)start the timer """ self.hasRun = False if millis is not None: self.millis = millis if args or kwargs: self.SetArgs(*args, **kwargs) self.Stop() self.timer = PyTimer(self.Notify, id=self.id) # PAK self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) self.running = True self.__RUNNING.add(self)
Restart = Start
[docs] def Stop(self): """ Stop and destroy the timer. """ if self.timer is not None: self.timer.Stop() self.timer = None self.__RUNNING.discard(self)
[docs] def GetInterval(self): if self.timer is not None: return self.timer.GetInterval() else: return 0
[docs] def IsRunning(self): return self.timer is not None and self.timer.IsRunning()
[docs] def SetArgs(self, *args, **kwargs): """ (Re)set the args passed to the callable object. This is useful in conjunction with Restart if you want to schedule a new call to the same callable object but with different parameters. """ self.args = args self.kwargs = kwargs
[docs] def HasRun(self): return self.hasRun
[docs] def GetResult(self): return self.result
[docs] def Notify(self): """ The timer has expired so call the callable. """ if self.callable and getattr(self.callable, 'im_self', True): self.runCount += 1 self.running = False self.result = self.callable(*self.args, **self.kwargs) self.hasRun = True if not self.running: # if it wasn't restarted, then cleanup wx.CallAfter(self.Stop)
Interval = property(GetInterval) Result = property(GetResult)
[docs]class FutureCall(CallLater): """A compatibility alias for `CallLater`."""