From 69d09a30b38567c3ae33a227a3959aee43c721a7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 6 Oct 2009 21:52:41 -0700 Subject: added bind to visible event function to callback when visibility changes within tabs --- gr-wxgui/src/python/common.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index 9c97ce1ec..f355fd3ce 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -19,6 +19,41 @@ # Boston, MA 02110-1301, USA. # +import wx + +def bind_to_visible_event(win, callback): + """ + Bind a callback to a window when its visibility changes. + Specifically, callback when the window changes visibility + when a notebook tab event in one of the parents occurs. + @param win the wx window + @param callback a 1 param function + """ + #is the window visible in the hierarchy + def is_wx_window_visible(my_win): + while True: + parent = my_win.GetParent() + if not parent: return True #reached the top of the hierarchy + #if we are hidden, then finish, otherwise keep traversing up + if isinstance(parent, wx.Notebook) and parent.GetCurrentPage() != my_win: return False + my_win = parent + #call the callback, the arg is shown or not + def callback_factory(my_win, my_callback): + cache = [None] + def the_callback(*args): + visible = is_wx_window_visible(my_win) + if cache[0] != visible: my_callback(visible) + cache[0] = visible + return the_callback + handler = callback_factory(win, callback) + #bind the handler to all the parent notebooks + while win: + if isinstance(win, wx.Notebook): + win.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, handler) + if not win.GetParent(): + win.Bind(wx.EVT_ACTIVATE, handler) + win = win.GetParent() + #A macro to apply an index to a key index_key = lambda key, i: "%s_%d"%(key, i+1) -- cgit From 645ab0cfa4ab46e057ab4df74066ab434ad5b90a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 6 Oct 2009 22:28:09 -0700 Subject: work on a special connect function that registers a callback --- gr-wxgui/src/python/common.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index f355fd3ce..09ce44719 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -54,6 +54,26 @@ def bind_to_visible_event(win, callback): win.Bind(wx.EVT_ACTIVATE, handler) win = win.GetParent() +from gnuradio import gr + +def special_connect(source, sink, hb, win, size): + nulls = [gr.null_sink(size), gr.null_source(size)] + def callback(visible, init=False): + if not init: hb.lock() + if visible: + if not init: hb.disconnect(source, nulls[0]) + if not init: hb.disconnect(nulls[1], sink) + hb.connect(source, sink) + #hb.connect(nulls[1], nulls[0]) + else: + if not init: hb.disconnect(source, sink) + #if not init: hb.disconnect(nulls[1], nulls[0]) + hb.connect(source, nulls[0]) + hb.connect(nulls[1], sink) + if not init: hb.unlock() + callback(False, init=True) #initially connect + bind_to_visible_event(win, callback) + #A macro to apply an index to a key index_key = lambda key, i: "%s_%d"%(key, i+1) -- cgit From bbecdd8372f57d49ad0046d9d096f322059005cb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Oct 2009 01:47:38 -0700 Subject: working special connect for fftsink --- gr-wxgui/src/python/common.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index 09ce44719..fe080aa4a 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -39,12 +39,7 @@ def bind_to_visible_event(win, callback): my_win = parent #call the callback, the arg is shown or not def callback_factory(my_win, my_callback): - cache = [None] - def the_callback(*args): - visible = is_wx_window_visible(my_win) - if cache[0] != visible: my_callback(visible) - cache[0] = visible - return the_callback + return lambda *args: my_callback(is_wx_window_visible(my_win)) handler = callback_factory(win, callback) #bind the handler to all the parent notebooks while win: @@ -57,19 +52,25 @@ def bind_to_visible_event(win, callback): from gnuradio import gr def special_connect(source, sink, hb, win, size): - nulls = [gr.null_sink(size), gr.null_source(size)] + nulls = list() + cache = [None] def callback(visible, init=False): + if visible == cache[0]: return + cache[0] = visible if not init: hb.lock() + print 'visible', visible if visible: - if not init: hb.disconnect(source, nulls[0]) - if not init: hb.disconnect(nulls[1], sink) + if not init: + hb.disconnect(source, nulls[0]) + hb.disconnect(nulls[1], nulls[2]) + hb.disconnect(nulls[2], sink) + while nulls: nulls.pop() hb.connect(source, sink) - #hb.connect(nulls[1], nulls[0]) else: if not init: hb.disconnect(source, sink) - #if not init: hb.disconnect(nulls[1], nulls[0]) + nulls.extend([gr.null_sink(size), gr.null_source(size), gr.head(size, 0)]) hb.connect(source, nulls[0]) - hb.connect(nulls[1], sink) + hb.connect(nulls[1], nulls[2], sink) if not init: hb.unlock() callback(False, init=True) #initially connect bind_to_visible_event(win, callback) -- cgit From af5e21e35cda1d9d3e4bd659364dafe181274064 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Oct 2009 09:48:24 -0700 Subject: setup special wxgui connect on sinks, needs testing --- gr-wxgui/src/python/common.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index fe080aa4a..dca41c9a3 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -19,6 +19,9 @@ # Boston, MA 02110-1301, USA. # +################################################## +# conditional disconnections of wx flow graph +################################################## import wx def bind_to_visible_event(win, callback): @@ -51,14 +54,14 @@ def bind_to_visible_event(win, callback): from gnuradio import gr -def special_connect(source, sink, hb, win, size): +def conditional_connect(source, sink, hb, win, size): nulls = list() cache = [None] def callback(visible, init=False): if visible == cache[0]: return cache[0] = visible if not init: hb.lock() - print 'visible', visible + print 'visible', visible, source, sink if visible: if not init: hb.disconnect(source, nulls[0]) @@ -75,6 +78,24 @@ def special_connect(source, sink, hb, win, size): callback(False, init=True) #initially connect bind_to_visible_event(win, callback) +class wxgui_hb(object): + def wxgui_connect(self, *points): + """ + Use wxgui connect when the first point is the self source of the hb. + The win property of this object should be set to the wx window. + When this method tries to connect self to the next point, + it will conditionally make this connection based on the visibility state. + """ + try: + assert points[0] == self or points[0][0] == self + conditional_connect( + points[0], points[1], + win=self.win, hb=self, + size=self._hb.input_signature().sizeof_stream_item(0), + ) + if len(points[1:]) > 1: self.connect(*points[1:]) + except (AssertionError, IndexError): self.connect(*points) + #A macro to apply an index to a key index_key = lambda key, i: "%s_%d"%(key, i+1) -- cgit From 1e8aefecdc607de260c1797aba27eb1598b9e7b8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Oct 2009 11:52:33 -0700 Subject: making use of update ui event --- gr-wxgui/src/python/common.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index dca41c9a3..04875e7f2 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -28,7 +28,7 @@ def bind_to_visible_event(win, callback): """ Bind a callback to a window when its visibility changes. Specifically, callback when the window changes visibility - when a notebook tab event in one of the parents occurs. + when a update ui event in the window occurs. @param win the wx window @param callback a 1 param function """ @@ -45,23 +45,18 @@ def bind_to_visible_event(win, callback): return lambda *args: my_callback(is_wx_window_visible(my_win)) handler = callback_factory(win, callback) #bind the handler to all the parent notebooks - while win: - if isinstance(win, wx.Notebook): - win.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, handler) - if not win.GetParent(): - win.Bind(wx.EVT_ACTIVATE, handler) - win = win.GetParent() + win.Bind(wx.EVT_UPDATE_UI, handler) from gnuradio import gr -def conditional_connect(source, sink, hb, win, size): +def conditional_connect_callback_factory(source, sink, hb, win, size): nulls = list() cache = [None] def callback(visible, init=False): if visible == cache[0]: return cache[0] = visible if not init: hb.lock() - print 'visible', visible, source, sink + #print 'visible', visible, source, sink if visible: if not init: hb.disconnect(source, nulls[0]) @@ -75,8 +70,12 @@ def conditional_connect(source, sink, hb, win, size): hb.connect(source, nulls[0]) hb.connect(nulls[1], nulls[2], sink) if not init: hb.unlock() - callback(False, init=True) #initially connect - bind_to_visible_event(win, callback) + return callback + +def conditional_connect(source, sink, hb, win, size): + handler = conditional_connect_callback_factory(source, sink, hb, win, size) + handler(False, init=True) #initially connect + bind_to_visible_event(win, handler) class wxgui_hb(object): def wxgui_connect(self, *points): -- cgit From 64a5167c53eeb2d2a657507397b402abe22f67b6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Oct 2009 18:01:56 -0700 Subject: moved the wxgui connect helper functions into the wrapper class --- gr-wxgui/src/python/common.py | 137 ++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 57 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index 04875e7f2..aae4d63cf 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -23,78 +23,101 @@ # conditional disconnections of wx flow graph ################################################## import wx - -def bind_to_visible_event(win, callback): - """ - Bind a callback to a window when its visibility changes. - Specifically, callback when the window changes visibility - when a update ui event in the window occurs. - @param win the wx window - @param callback a 1 param function - """ - #is the window visible in the hierarchy - def is_wx_window_visible(my_win): - while True: - parent = my_win.GetParent() - if not parent: return True #reached the top of the hierarchy - #if we are hidden, then finish, otherwise keep traversing up - if isinstance(parent, wx.Notebook) and parent.GetCurrentPage() != my_win: return False - my_win = parent - #call the callback, the arg is shown or not - def callback_factory(my_win, my_callback): - return lambda *args: my_callback(is_wx_window_visible(my_win)) - handler = callback_factory(win, callback) - #bind the handler to all the parent notebooks - win.Bind(wx.EVT_UPDATE_UI, handler) - from gnuradio import gr -def conditional_connect_callback_factory(source, sink, hb, win, size): - nulls = list() - cache = [None] - def callback(visible, init=False): - if visible == cache[0]: return - cache[0] = visible - if not init: hb.lock() - #print 'visible', visible, source, sink - if visible: - if not init: - hb.disconnect(source, nulls[0]) - hb.disconnect(nulls[1], nulls[2]) - hb.disconnect(nulls[2], sink) - while nulls: nulls.pop() - hb.connect(source, sink) - else: - if not init: hb.disconnect(source, sink) - nulls.extend([gr.null_sink(size), gr.null_source(size), gr.head(size, 0)]) - hb.connect(source, nulls[0]) - hb.connect(nulls[1], nulls[2], sink) - if not init: hb.unlock() - return callback - -def conditional_connect(source, sink, hb, win, size): - handler = conditional_connect_callback_factory(source, sink, hb, win, size) - handler(False, init=True) #initially connect - bind_to_visible_event(win, handler) - class wxgui_hb(object): + """ + The wxgui hier block helper/wrapper class: + A hier block should inherit from this class to make use of the wxgui connect method. + To use, call wxgui_connect in place of regular connect; self.win must be defined. + The implementation will conditionally connect or disconnect the self (source) of the hb. + This condition depends on weather or not the window is visible with the parent notebooks. + This condition will be re-checked on every ui update event. + """ + def wxgui_connect(self, *points): """ Use wxgui connect when the first point is the self source of the hb. The win property of this object should be set to the wx window. When this method tries to connect self to the next point, it will conditionally make this connection based on the visibility state. + All other points will be connected normally. """ try: assert points[0] == self or points[0][0] == self - conditional_connect( - points[0], points[1], - win=self.win, hb=self, - size=self._hb.input_signature().sizeof_stream_item(0), - ) + self._conditional_connect(points[0], points[1]) if len(points[1:]) > 1: self.connect(*points[1:]) except (AssertionError, IndexError): self.connect(*points) + def _conditional_connect(self, source, sink): + """ + Create a handler for visibility changes. + Initially call the handler to setup the fg. + Bind the handler to the visibility meta event. + """ + handler = self._conditional_connect_handler_factory( + source=source, sink=sink, win=self.win, hb=self, + size=self._hb.input_signature().sizeof_stream_item(0), + ) + handler(False, init=True) #initially connect + self._bind_to_visible_event(win=self.win, handler=handler) + + @staticmethod + def _conditional_connect_handler_factory(source, sink, hb, win, size): + """ + Create a function that will handle the re-connections based on a flag. + The current state of the connection is stored in the namespace. + """ + nulls = list() + cache = [None] + def callback(visible, init=False): + if visible == cache[0]: return + cache[0] = visible + if not init: hb.lock() + #print 'visible', visible, source, sink + if visible: + if not init: + hb.disconnect(source, nulls[0]) + hb.disconnect(nulls[1], nulls[2]) + hb.disconnect(nulls[2], sink) + while nulls: nulls.pop() + hb.connect(source, sink) + else: + if not init: hb.disconnect(source, sink) + nulls.extend([gr.null_sink(size), gr.null_source(size), gr.head(size, 0)]) + hb.connect(source, nulls[0]) + hb.connect(nulls[1], nulls[2], sink) + if not init: hb.unlock() + return callback + + @staticmethod + def _bind_to_visible_event(win, handler): + """ + Bind a handler to a window when its visibility changes. + Specifically, call the handler when the window visibility changes. + This condition is checked on every update ui event. + @param win the wx window + @param handler a function of 1 param + """ + #is the window visible in the hierarchy + def is_wx_window_visible(my_win): + while True: + parent = my_win.GetParent() + if not parent: return True #reached the top of the hierarchy + #if we are hidden, then finish, otherwise keep traversing up + if isinstance(parent, wx.Notebook) and parent.GetCurrentPage() != my_win: return False + my_win = parent + #call the handler, the arg is shown or not + def handler_factory(my_win, my_handler): + return lambda *args: my_handler(is_wx_window_visible(my_win)) + handler = handler_factory(win, handler) + #bind the handler to all the parent notebooks + win.Bind(wx.EVT_UPDATE_UI, handler) + +################################################## +# Helpful Functions +################################################## + #A macro to apply an index to a key index_key = lambda key, i: "%s_%d"%(key, i+1) -- cgit From dfa5e0a5bccb6b3539c1230281b5bec60196f8a2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Oct 2009 18:47:21 -0700 Subject: simplify some params --- gr-wxgui/src/python/common.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index aae4d63cf..9bf3094f2 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -55,39 +55,37 @@ class wxgui_hb(object): Initially call the handler to setup the fg. Bind the handler to the visibility meta event. """ - handler = self._conditional_connect_handler_factory( - source=source, sink=sink, win=self.win, hb=self, - size=self._hb.input_signature().sizeof_stream_item(0), - ) + handler = self._conditional_connect_handler_factory(source=source, sink=sink) handler(False, init=True) #initially connect self._bind_to_visible_event(win=self.win, handler=handler) - @staticmethod - def _conditional_connect_handler_factory(source, sink, hb, win, size): + def _conditional_connect_handler_factory(self, source, sink): """ Create a function that will handle the re-connections based on a flag. The current state of the connection is stored in the namespace. + !!!#TODO This entire method could be replaced with a mute block that starves the stream. """ nulls = list() cache = [None] + size = self._hb.input_signature().sizeof_stream_item(0) def callback(visible, init=False): if visible == cache[0]: return cache[0] = visible - if not init: hb.lock() + if not init: self.lock() #print 'visible', visible, source, sink if visible: if not init: - hb.disconnect(source, nulls[0]) - hb.disconnect(nulls[1], nulls[2]) - hb.disconnect(nulls[2], sink) + self.disconnect(source, nulls[0]) + self.disconnect(nulls[1], nulls[2]) + self.disconnect(nulls[2], sink) while nulls: nulls.pop() - hb.connect(source, sink) + self.connect(source, sink) else: - if not init: hb.disconnect(source, sink) + if not init: self.disconnect(source, sink) nulls.extend([gr.null_sink(size), gr.null_source(size), gr.head(size, 0)]) - hb.connect(source, nulls[0]) - hb.connect(nulls[1], nulls[2], sink) - if not init: hb.unlock() + self.connect(source, nulls[0]) + self.connect(nulls[1], nulls[2], sink) + if not init: self.unlock() return callback @staticmethod -- cgit From 38d5389f3054164a2f04d6e4e8fe381aa5ee03fc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 8 Oct 2009 21:46:53 -0700 Subject: using gr copy in the wxgui connect, added gr copy to grc xml --- gr-wxgui/src/python/common.py | 56 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) (limited to 'gr-wxgui/src/python/common.py') diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index 9bf3094f2..fa11b3152 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -30,7 +30,7 @@ class wxgui_hb(object): The wxgui hier block helper/wrapper class: A hier block should inherit from this class to make use of the wxgui connect method. To use, call wxgui_connect in place of regular connect; self.win must be defined. - The implementation will conditionally connect or disconnect the self (source) of the hb. + The implementation will conditionally enable the copy block after the source (self). This condition depends on weather or not the window is visible with the parent notebooks. This condition will be re-checked on every ui update event. """ @@ -45,47 +45,29 @@ class wxgui_hb(object): """ try: assert points[0] == self or points[0][0] == self - self._conditional_connect(points[0], points[1]) - if len(points[1:]) > 1: self.connect(*points[1:]) - except (AssertionError, IndexError): self.connect(*points) + copy = gr.copy(self._hb.input_signature().sizeof_stream_item(0)) + handler = self._handler_factory(copy.set_enabled) + handler(False) #initially disable the copy block + self._bind_to_visible_event(win=self.win, handler=handler) + points = list(points) + points.insert(1, copy) #insert the copy block into the chain + except (AssertionError, IndexError): pass + self.connect(*points) #actually connect the blocks - def _conditional_connect(self, source, sink): - """ - Create a handler for visibility changes. - Initially call the handler to setup the fg. - Bind the handler to the visibility meta event. - """ - handler = self._conditional_connect_handler_factory(source=source, sink=sink) - handler(False, init=True) #initially connect - self._bind_to_visible_event(win=self.win, handler=handler) - - def _conditional_connect_handler_factory(self, source, sink): + @staticmethod + def _handler_factory(handler): """ - Create a function that will handle the re-connections based on a flag. - The current state of the connection is stored in the namespace. - !!!#TODO This entire method could be replaced with a mute block that starves the stream. + Create a function that will cache the visibility flag, + and only call the handler when that flag changes. + @param handler the function to call on a change + @return a function of 1 argument """ - nulls = list() cache = [None] - size = self._hb.input_signature().sizeof_stream_item(0) - def callback(visible, init=False): - if visible == cache[0]: return + def callback(visible): + if cache[0] == visible: return cache[0] = visible - if not init: self.lock() - #print 'visible', visible, source, sink - if visible: - if not init: - self.disconnect(source, nulls[0]) - self.disconnect(nulls[1], nulls[2]) - self.disconnect(nulls[2], sink) - while nulls: nulls.pop() - self.connect(source, sink) - else: - if not init: self.disconnect(source, sink) - nulls.extend([gr.null_sink(size), gr.null_source(size), gr.head(size, 0)]) - self.connect(source, nulls[0]) - self.connect(nulls[1], nulls[2], sink) - if not init: self.unlock() + #print visible, handler + handler(visible) return callback @staticmethod -- cgit