From b686837f59499282689a59cf7279a039268e8c0c Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sun, 2 Dec 2007 15:05:59 -0500 Subject: [PATCH] Add a "Save As" right-click menu option to the ReplotResult custom_result.py replay.py: Add custom_result.show_menu() to avoid cut-and-paste between replot and replay. replay.py: Add "Save As" right click menu item that calls to matplotlib's print_figure() (http://www.reinteract.org/trac/ticket/13, Justyn Butler) --- lib/reinteract/custom_result.py | 34 +++++++++++++++++++++++++++++++++ lib/replay.py | 36 +++-------------------------------- lib/replot.py | 42 ++++++++++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/lib/reinteract/custom_result.py b/lib/reinteract/custom_result.py index 2947a88..f8fb423 100644 --- a/lib/reinteract/custom_result.py +++ b/lib/reinteract/custom_result.py @@ -1,3 +1,37 @@ +import gtk + class CustomResult(object): def create_widget(self): raise NotImplementedError + +def show_menu(widget, event, save_callback=None): + """Convenience function to create a right-click menu with a Save As option""" + + toplevel = widget.get_toplevel() + + menu = gtk.Menu() + menu_item = gtk.ImageMenuItem(stock_id=gtk.STOCK_SAVE_AS) + menu_item.show() + menu.add(menu_item) + + def on_selection_done(menu): + menu.destroy() + menu.connect('selection-done', on_selection_done) + + def on_activate(menu): + chooser = gtk.FileChooserDialog("Save As...", toplevel, gtk.FILE_CHOOSER_ACTION_SAVE, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, gtk.RESPONSE_OK)) + chooser.set_default_response(gtk.RESPONSE_OK) + response = chooser.run() + filename = None + if response == gtk.RESPONSE_OK: + filename = chooser.get_filename() + + chooser.destroy() + + if filename != None: + save_callback(filename) + + menu_item.connect('activate', on_activate) + menu.popup(None, None, None, event.button, event.time) diff --git a/lib/replay.py b/lib/replay.py index f8f43b4..b7f3525 100644 --- a/lib/replay.py +++ b/lib/replay.py @@ -3,9 +3,9 @@ import os from numpy import float32, float64 -from reinteract.custom_result import CustomResult +import reinteract.custom_result as custom_result -class PlayResult(CustomResult): +class PlayResult(custom_result.CustomResult): def __init__(self, data): self.__data = data @@ -30,7 +30,6 @@ class PlayResult(CustomResult): def __save(self, filename): escaped = filename.replace("'", r"'\''") - print repr(escaped) if self.__data.dtype == float32: command = "sox -t raw -r 44100 -f -4 -L -q - '%s'" % escaped @@ -43,36 +42,7 @@ class PlayResult(CustomResult): def on_button_press(self, button, event): if event.button == 3: - toplevel = button.get_toplevel() - - menu = gtk.Menu() - menu_item = gtk.ImageMenuItem(stock_id=gtk.STOCK_SAVE_AS) - menu_item.show() - menu.add(menu_item) - - def on_selection_done(menu): - menu.destroy() - menu.connect('selection-done', on_selection_done) - - def on_activate(menu): - chooser = gtk.FileChooserDialog("Save As...", toplevel, gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_SAVE, gtk.RESPONSE_OK)) - chooser.set_default_response(gtk.RESPONSE_OK) - response = chooser.run() - filename = None - if response == gtk.RESPONSE_OK: - filename = chooser.get_filename() - - chooser.destroy() - - if filename != None: - self.__save(filename) - - menu_item.connect('activate', on_activate) - - menu.popup(None, None, None, event.button, event.time) - + custom_result.show_menu(button, event, save_callback=self.__save) return True return False diff --git a/lib/replot.py b/lib/replot.py index 81d437f..da89add 100644 --- a/lib/replot.py +++ b/lib/replot.py @@ -1,15 +1,18 @@ import gtk from matplotlib.figure import Figure -from matplotlib.backends.backend_cairo import RendererCairo +from matplotlib.backends.backend_cairo import RendererCairo, FigureCanvasCairo import numpy -from reinteract.custom_result import CustomResult +import reinteract.custom_result as custom_result -class _DummyCanvas: +class _PlotResultCanvas(FigureCanvasCairo): def draw_event(*args): + # Since we never change anything about the figure, the only time we + # need to redraw is in response to an expose event, which we handle + # ourselves pass -class PlotResult(CustomResult): +class PlotResult(custom_result.CustomResult): def __init__(self, *args, **kwargs): self.__args = args self.__kwargs = kwargs @@ -20,7 +23,7 @@ class PlotResult(CustomResult): return widget -class ImshowResult(CustomResult): +class ImshowResult(custom_result.CustomResult): def __init__(self, *args, **kwargs): self.__args = args self.__kwargs = kwargs @@ -41,7 +44,7 @@ class PlotWidget(gtk.DrawingArea): def __init__(self, result): gtk.DrawingArea.__init__(self) self.figure = Figure(facecolor='white', figsize=(6,4.5)) - self.figure.set_canvas(_DummyCanvas()) + self.canvas = _PlotResultCanvas(self.figure) self.axes = self.figure.add_axes((0.05,0.05,0.9,0.9)) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE) @@ -61,15 +64,40 @@ class PlotWidget(gtk.DrawingArea): self.figure.draw(renderer) def do_button_press_event(self, event): - return True + if event.button == 3: + custom_result.show_menu(self, event, save_callback=self.__save) + return True + else: + return True def do_button_release_event(self, event): return True + def do_realize(self): + gtk.DrawingArea.do_realize(self) + cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR) + self.window.set_cursor(cursor) + def do_size_request(self, requisition): requisition.width = self.figure.bbox.width() requisition.height = self.figure.bbox.height() + def __save(self, filename): + # The save/restore here was added to matplotlib's after 0.90. We duplicate + # it for compatibility with older versions. + + orig_dpi = self.figure.dpi.get() + orig_facecolor = self.figure.get_facecolor() + orig_edgecolor = self.figure.get_edgecolor() + + try: + self.canvas.print_figure(filename) + finally: + self.figure.dpi.set(orig_dpi) + self.figure.set_facecolor(orig_facecolor) + self.figure.set_edgecolor(orig_edgecolor) + self.figure.set_canvas(self.canvas) + # def do_size_allocate(self, allocation): # gtk.DrawingArea.do_size_allocate(self, allocation) # -- 2.11.4.GIT