Changed generic observer pattern and project dependency in plots to be a two-way selection-listener model.
The project listens to selections done in plot and broadcasts it back to all plots (including source) which allows them to redraw properly.
This commit is contained in:
parent
c6ef6cdb07
commit
5bb93af6f0
|
@ -60,7 +60,7 @@ class Plot (gtk.Frame):
|
||||||
self.sel_obj = None
|
self.sel_obj = None
|
||||||
self.active = False
|
self.active = False
|
||||||
self.title = title
|
self.title = title
|
||||||
self.project = None
|
self.selection_listener = None
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
@ -76,11 +76,17 @@ class Plot (gtk.Frame):
|
||||||
self.set_shadow_type(gtk.SHADOW_OUT)
|
self.set_shadow_type(gtk.SHADOW_OUT)
|
||||||
self.active = active
|
self.active = active
|
||||||
|
|
||||||
def update(self, key):
|
def selection_changed(self, selection):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_project(self, project):
|
def set_selection_listener(self, listener):
|
||||||
self.project = project
|
"""Allow project to listen to selections.
|
||||||
|
|
||||||
|
The selection will propagate back to all plots through the
|
||||||
|
selection_changed() method. The listener will be called as
|
||||||
|
listener(dimension_name, ids).
|
||||||
|
"""
|
||||||
|
self.selection_listener = listener
|
||||||
|
|
||||||
def get_toolbar(self):
|
def get_toolbar(self):
|
||||||
return None
|
return None
|
||||||
|
@ -365,8 +371,9 @@ class LinePlot(Plot):
|
||||||
silent_eval("k <- sapply(1:length(res), function(id) rev(res[[id]]$y))")
|
silent_eval("k <- sapply(1:length(res), function(id) rev(res[[id]]$y))")
|
||||||
self._bg_matrix = bg_matrix = rpy.r("k")
|
self._bg_matrix = bg_matrix = rpy.r("k")
|
||||||
rpy.r.rm(["k", "res", "m"])
|
rpy.r.rm(["k", "res", "m"])
|
||||||
|
|
||||||
self.update(None)
|
# Hack - we draw plot in selection_changed()
|
||||||
|
self.selection_changed(None)
|
||||||
|
|
||||||
self.add(self.canvas)
|
self.add(self.canvas)
|
||||||
self.canvas.show()
|
self.canvas.show()
|
||||||
|
@ -379,15 +386,14 @@ class LinePlot(Plot):
|
||||||
self.canvas.draw()
|
self.canvas.draw()
|
||||||
return self._toolbar
|
return self._toolbar
|
||||||
|
|
||||||
def update(self, key):
|
def selection_changed(self, selection):
|
||||||
self.ax.clear()
|
self.ax.clear()
|
||||||
|
|
||||||
rows, cols = self._bg_matrix.shape
|
rows, cols = self._bg_matrix.shape
|
||||||
self.ax.imshow(self._bg_matrix, cmap=cm.Greys, extent=(0.5, cols+0.5, self._ymin, self._ymax))
|
self.ax.imshow(self._bg_matrix, cmap=cm.Greys, extent=(0.5, cols+0.5, self._ymin, self._ymax))
|
||||||
|
|
||||||
if self.project:
|
if selection:
|
||||||
curr_sel = self.project.get_selection() # get selection object
|
ids = selection['ids'] # current identifiers
|
||||||
ids = curr_sel['ids'] # current identifiers
|
|
||||||
index = [ind for id,ind in self._dataset['ids'].items() if id in ids] #conversion to index
|
index = [ind for id,ind in self._dataset['ids'].items() if id in ids] #conversion to index
|
||||||
for i in index:
|
for i in index:
|
||||||
line = self._dataset.get_matrix()[i]
|
line = self._dataset.get_matrix()[i]
|
||||||
|
@ -457,11 +463,10 @@ class ScatterPlot(Plot):
|
||||||
for ind in index:
|
for ind in index:
|
||||||
ids.append(reverse[ind])
|
ids.append(reverse[ind])
|
||||||
|
|
||||||
self.project.set_selection(self.current_dim,ids)
|
self.selection_listener(self.current_dim,ids)
|
||||||
|
|
||||||
def update(self, key):
|
def selection_changed(self, selection):
|
||||||
curr_sel = self.project.get_selection() # get selection object
|
ids = selection[self.current_dim] # current identifiers
|
||||||
ids = curr_sel[self.current_dim] # current identifiers
|
|
||||||
|
|
||||||
index = [ind for id,ind in self.dataset[self.current_dim].items() if id in ids] #conversion to index
|
index = [ind for id,ind in self.dataset[self.current_dim].items() if id in ids] #conversion to index
|
||||||
xdata_new = scipy.take(self.xaxis_data,index) #take data
|
xdata_new = scipy.take(self.xaxis_data,index) #take data
|
||||||
|
|
|
@ -12,35 +12,20 @@ class Project:
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.dim_names = []
|
self.dim_names = []
|
||||||
self._observers = {}
|
self._selection_observers = []
|
||||||
self.current_data = None
|
self.current_data = None
|
||||||
self.datasets = []
|
self.datasets = []
|
||||||
self.sel_obj = dataset.Selection()
|
self.sel_obj = dataset.Selection()
|
||||||
|
|
||||||
def attach(self,observer,key):
|
def notify_selection_listeners(self):
|
||||||
"""Attach observer for selection updates"""
|
|
||||||
if not self._observers.has_key(key):
|
|
||||||
self._observers[key]=[]
|
|
||||||
if not observer in self._observers[key]:
|
|
||||||
self._observers[key].append(observer)
|
|
||||||
|
|
||||||
def detach(self,observer,key):
|
|
||||||
"""Detach observer for selection updates"""
|
|
||||||
try:
|
|
||||||
self._observers[key].remove(observer)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def notify(self,key,modifier=None):
|
|
||||||
"""Notifies observers"""
|
"""Notifies observers"""
|
||||||
for observer in self._observers[key]:
|
for observer in self._selection_observers:
|
||||||
if modifier != observer:
|
observer.selection_changed(self.get_selection())
|
||||||
observer.update(key)
|
|
||||||
|
|
||||||
def set_selection(self,dim_name,selection):
|
def set_selection(self,dim_name,selection):
|
||||||
"""Sets a current selection and notify observers"""
|
"""Sets a current selection and notify observers"""
|
||||||
self.sel_obj.current_selection[dim_name] = set(selection)
|
self.sel_obj.current_selection[dim_name] = set(selection)
|
||||||
self.notify('selection_update')
|
self.notify_selection_listeners()
|
||||||
|
|
||||||
def get_selection(self):
|
def get_selection(self):
|
||||||
"""Returns the current selection object"""
|
"""Returns the current selection object"""
|
||||||
|
@ -71,10 +56,9 @@ class Project:
|
||||||
self.add_dataset(d)
|
self.add_dataset(d)
|
||||||
self.data_tree_insert(it, d.get_name(), d)
|
self.data_tree_insert(it, d.get_name(), d)
|
||||||
elif isinstance(d, plots.Plot):
|
elif isinstance(d, plots.Plot):
|
||||||
# self.add_view(d)
|
|
||||||
self.data_tree_insert(it, d.get_title(), d)
|
self.data_tree_insert(it, d.get_title(), d)
|
||||||
d.set_project(self)
|
d.set_selection_listener(self.set_selection)
|
||||||
self.attach(d, 'selection_update')
|
self._selection_observers.append(d)
|
||||||
|
|
||||||
def data_tree_insert(self, parent, text, data):
|
def data_tree_insert(self, parent, text, data):
|
||||||
tree = self.data_tree
|
tree = self.data_tree
|
||||||
|
|
Reference in New Issue