Projects/laydi
Projects
/
laydi
Archived
7
0
Fork 0

Add toolbar support to plots, with home made selection support <phew>.

This commit is contained in:
Truls Alexander Tangstad 2006-04-26 12:11:23 +00:00
parent 490038d9bf
commit 21edeecdc3
2 changed files with 179 additions and 41 deletions

View File

@ -24,6 +24,8 @@ class FluentApp:
# Application variables # Application variables
self.project = None self.project = None
self.current_data = None self.current_data = None
self._last_view = None
self._plot_toolbar = None
gtk.glade.set_custom_handler(self.custom_object_factory) gtk.glade.set_custom_handler(self.custom_object_factory)
self.widget_tree = gtk.glade.XML(GLADEFILENAME, 'appwindow') self.widget_tree = gtk.glade.XML(GLADEFILENAME, 'appwindow')
@ -52,10 +54,29 @@ class FluentApp:
return self.log_view return self.log_view
def create_main_view(self, str1, str2, int1, int2): def create_main_view(self, str1, str2, int1, int2):
self.main_view = plots.MainView() self.main_view = plots.MainView(self._update_toolbar)
self.main_view.show() self.main_view.show()
return self.main_view return self.main_view
def _update_toolbar(self, view):
logger.log("debug", "view changed to %s" % view)
# don't do anything on no change
if self._last_view == view:
return
self._last_view = view
window = self.widget_tree.get_widget('plot_toolbar_dock')
if self._plot_toolbar:
print "removing", self._plot_toolbar
window.remove(self._plot_toolbar)
self._plot_toolbar = view.get_toolbar()
if self._plot_toolbar:
print "adding", self._plot_toolbar
window.add(self._plot_toolbar)
print "window contents:", window.get_children()
def create_small_view(self, str1, str2, int1, int2): def create_small_view(self, str1, str2, int1, int2):
self.small_view = plots.SmallView() self.small_view = plots.SmallView()
self.small_view.show() self.small_view.show()

View File

@ -4,6 +4,7 @@ import gtk
import matplotlib import matplotlib
import scipy import scipy
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTK as NavigationToolbar2
from matplotlib.axes import Subplot from matplotlib.axes import Subplot
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.numerix import arange, sin, pi from matplotlib.numerix import arange, sin, pi
@ -12,13 +13,14 @@ from system import logger
class MainView (gtk.Notebook): class MainView (gtk.Notebook):
def __init__(self): def __init__(self, view_listener):
gtk.Notebook.__init__(self) gtk.Notebook.__init__(self)
self.set_show_tabs(False) self.set_show_tabs(False)
self.set_show_border(False) self.set_show_border(False)
# Add a multiple pane view and a single pane view. # Add a multiple pane view and a single pane view.
self.small_view = SmallView() self.small_view = SmallView()
self.small_view.set_view_listener(view_listener)
self.small_view.show() self.small_view.show()
self.large_view = LargeView() self.large_view = LargeView()
self.large_view.show() self.large_view.show()
@ -47,7 +49,43 @@ class MainView (gtk.Notebook):
def insert_view(self, view): def insert_view(self, view):
self.small_view.insert_view(view) self.small_view.insert_view(view)
class Plot (gtk.Frame):
def __init__(self, title):
gtk.Frame.__init__(self)
self.mark_active(False)
self.connect('button_press_event', self.on_button_press)
self.sel_obj = None
self.active = False
self.title = title
def get_title(self):
return self.title
def on_button_press(self, *rest):
# logger.log('debug', 'button pressed in plot')
self.mark_active(True)
def mark_active(self, active):
if active:
self.set_shadow_type(gtk.SHADOW_IN)
else:
self.set_shadow_type(gtk.SHADOW_OUT)
self.active = active
def update(self, key):
pass
def set_project(self, project):
self.project = project
def get_toolbar(self):
return None
class SmallView (gtk.Table): class SmallView (gtk.Table):
def __init__(self): def __init__(self):
gtk.Table.__init__(self, 2, 2, True) gtk.Table.__init__(self, 2, 2, True)
@ -61,6 +99,7 @@ class SmallView (gtk.Table):
self.set_row_spacings(3) self.set_row_spacings(3)
self.set_col_spacings(3) self.set_col_spacings(3)
self._listener = None
for x in range(self.cols): for x in range(self.cols):
for y in range(self.rows): for y in range(self.rows):
@ -68,6 +107,9 @@ class SmallView (gtk.Table):
child.parent_signalling = child.connect('button_press_event', self.__view_button_event__) child.parent_signalling = child.connect('button_press_event', self.__view_button_event__)
self.attach(child, x, x+1, y, y+1) self.attach(child, x, x+1, y, y+1)
def set_view_listener(self, listener):
self._listener = listener
def set_child(self, child, col, row): def set_child(self, child, col, row):
cur_widget = self.child_views[col][row] cur_widget = self.child_views[col][row]
cur_widget.disconnect(cur_widget.parent_signalling) cur_widget.disconnect(cur_widget.parent_signalling)
@ -115,6 +157,9 @@ class SmallView (gtk.Table):
new_focus.mark_active(True) new_focus.mark_active(True)
self.active_x = x self.active_x = x
self.active_y = y self.active_y = y
if self._listener:
logger.log("debug", "emitting")
self._listener(new_focus)
def find_child(self, child): def find_child(self, child):
for i, row in enumerate(self.child_views): for i, row in enumerate(self.child_views):
@ -158,36 +203,6 @@ class LargeView (gtk.Frame):
self.remove(child) self.remove(child)
return child return child
class Plot (gtk.Frame):
def __init__(self, title):
gtk.Frame.__init__(self)
self.mark_active(False)
self.connect('button_press_event', self.on_button_press)
self.sel_obj = None
self.active = False
self.title = title
def get_title(self):
return self.title
def on_button_press(self, *rest):
# logger.log('debug', 'button pressed in plot')
self.mark_active(True)
def mark_active(self, active):
if active:
self.set_shadow_type(gtk.SHADOW_IN)
else:
self.set_shadow_type(gtk.SHADOW_OUT)
self.active = active
def update(self, key):
pass
def set_project(self, project):
self.project = project
class EmptyView (Plot): class EmptyView (Plot):
def __init__(self): def __init__(self):
@ -214,6 +229,101 @@ class EmptyView (Plot):
Plot.hide(self) Plot.hide(self)
class NavToolbar(NavigationToolbar2):
toolitems = (('Select', 'Select within rectangle', 'zoom_to_rect.png',
'select'),) + NavigationToolbar2.toolitems
def __init__(self, *args):
NavigationToolbar2.__init__(self, *args)
self._select_callback = None
def select(self, *args):
"""Selection mode selected handler."""
if self._active == 'SELECT':
self._active = None
else:
self._active = 'SELECT'
if self._idPress is not None:
self._idPress = self.canvas.mpl_disconnect(self._idPress)
self.mode = ''
if self._idRelease is not None:
self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
self.mode = ''
if self._active:
self._idPress = self.canvas.mpl_connect('button_press_event', self.press_select)
self._idRelease = self.canvas.mpl_connect('button_release_event', self.release_select)
self.mode = 'Select rectangle mode'
self.set_message(self.mode)
def set_message(self, s):
"""Set status in toolbar to string s.
Overrided to make sure message can be updated even when
drawing rubberband.
"""
self.message.set_label(s)
def press_select(self, event):
"""Mouse button pressed handler for selection mode."""
x, y = event.x, event.y
for i, a in enumerate(self.canvas.figure.get_axes()):
if event.inaxes==a and event.inaxes.get_navigate():
xmin, xmax = a.get_xlim()
ymin, ymax = a.get_ylim()
lim = xmin, xmax, ymin, ymax
self._xypress = x, y, a, i, lim, a.transData.deepcopy()
break
self.press(event)
def release_select(self, event):
"""Mouse button released handler for selection mode."""
# only release if button was pressed inside first?
if self._xypress:
x, y = event.x, event.y
lastx, lasty, a, ind, lim, trans = self._xypress
lastx, lasty = a.transData.inverse_xy_tup( (lastx, lasty) )
x, y = a.transData.inverse_xy_tup( (x, y) )
if self._select_callback:
self._select_callback(lastx, lasty, x, y)
self._xypress = None
self.draw()
self.release(event)
def mouse_move(self, event):
"""Extend NavigationToolbar2.mouse_move to provide selection support."""
from matplotlib.backend_bases import cursors
# Only update the rubberband for selection mode when mouse is
# within the plotting area.
if event.inaxes and self._active=='SELECT':
if self._lastCursor != cursors.SELECT_REGION:
self.set_cursor(cursors.SELECT_REGION)
self._lastCursor = cursors.SELECT_REGION
if self._xypress is not None:
x, y = event.x, event.y
lastx, lasty, a, ind, lim, trans= self._xypress
self.draw_rubberband(event, x, y, lastx, lasty)
NavigationToolbar2.mouse_move(self, event)
def set_select_callback(self, listener):
"""Allow plots to register a callback for selection events.
The callback will be called as listener(x1, y1, x2, y2). All
coordinates are in the plot coordinate system, not pixels or
widget coordinates.
"""
self._select_callback = listener
class SinePlot(Plot): class SinePlot(Plot):
def __init__(self): def __init__(self):
Plot.__init__(self, 'Sine plot') Plot.__init__(self, 'Sine plot')
@ -225,9 +335,14 @@ class SinePlot(Plot):
ax.plot(t,s) ax.plot(t,s)
self.canvas = FigureCanvas(fig) self.canvas = FigureCanvas(fig)
self._toolbar = NavToolbar(self.canvas, None)
self._toolbar.set_property('show-arrow', False)
self.add(self.canvas) self.add(self.canvas)
self.canvas.show() self.canvas.show()
def get_toolbar(self):
return self._toolbar
class ScatterPlot(Plot): class ScatterPlot(Plot):
def __init__(self, dataset,id_dim, sel_dim,id_1,id_2): def __init__(self, dataset,id_dim, sel_dim,id_1,id_2):
@ -243,21 +358,22 @@ class ScatterPlot(Plot):
self.xaxis_data = dataset._array[:,x_index] self.xaxis_data = dataset._array[:,x_index]
self.yaxis_data = dataset._array[:,y_index] self.yaxis_data = dataset._array[:,y_index]
ax.plot(self.xaxis_data,self.yaxis_data,'og') ax.plot(self.xaxis_data,self.yaxis_data,'og')
### ###
self.canvas = FigureCanvas(fig) self.canvas = FigureCanvas(fig)
self.add(self.canvas) self.add(self.canvas)
rectprops = dict(facecolor='gray', edgecolor = 'black',
alpha=0.2, fill=True) #cool
self.sel = RectangleSelector(ax, self.rectangle_select_callback,
drawtype='box',useblit=True,rectprops=rectprops)
self.canvas.show() self.canvas.show()
def rectangle_select_callback(self,event1, event2): self._toolbar = NavToolbar(self.canvas, None)
self._toolbar.set_property('show-arrow', False)
self._toolbar.set_select_callback(self.rectangle_select_callback)
def get_toolbar(self):
return self._toolbar
def rectangle_select_callback(self, x1, y1, x2, y2):
'event1 and event2 are the press and release events' 'event1 and event2 are the press and release events'
x1, y1 = event1.xdata, event1.ydata
x2, y2 = event2.xdata, event2.ydata
ydata = self.yaxis_data ydata = self.yaxis_data
xdata = self.xaxis_data xdata = self.xaxis_data
@ -297,3 +413,4 @@ class ScatterPlot(Plot):
self.ax.plot(self.xaxis_data,self.yaxis_data,'og') self.ax.plot(self.xaxis_data,self.yaxis_data,'og')
self.ax.plot(xdata_new,ydata_new,'or') self.ax.plot(xdata_new,ydata_new,'or')
self.canvas.draw() self.canvas.draw()