diff --git a/src/damaris/gui/DamarisGUI.py b/src/damaris/gui/DamarisGUI.py index 5f8524f..8675d8c 100644 --- a/src/damaris/gui/DamarisGUI.py +++ b/src/damaris/gui/DamarisGUI.py @@ -253,6 +253,8 @@ class DamarisGUI: "on_display_y_scaling_combobox_changed": self.monitor.display_scaling_changed, "on_display_save_data_as_text_button_clicked": self.monitor.save_display_data_as_text, "on_display_copy_data_to_clipboard_button_clicked": self.monitor.copy_display_data_to_clipboard, + "on_display_copy_png_button_clicked": self.monitor.copy_canvas_as_png, + "on_display_copy_svg_button_clicked": self.monitor.copy_canvas_as_svg, "on_experiment_script_textview_event": self.sw.textviews_modified, "on_main_notebook_switch_page": self.nopevent, "main_window_close": self.nopevent @@ -3832,25 +3834,20 @@ class MonitorWidgets: return try: - # Save the original figure size - original_size = self.matplot_figure.get_size_inches() # Save figure to a buffer as SVG import io as iomodule buf = iomodule.StringIO() - self.matplot_figure.set_size_inches(6, 4) self.matplot_figure.savefig(buf, format='svg', bbox_inches='tight') buf.seek(0) # Copy SVG text to clipboard clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD) clipboard.set_text(buf.read(), -1) - clipboard.store() - self.matplot_figure.set_size_inches(original_size) - log("Figure copied to clipboard as SVG") + logger.info("Figure copied to clipboard as SVG") except Exception as e: - log(f"Error copying figure as SVG: {e}") + logger.error("Error copying figure as SVG: %s", e) def copy_display_data_to_clipboard( self, widget, data=None ): """ @@ -3858,38 +3855,42 @@ class MonitorWidgets: Also keep text data copy functionality as fallback """ # First, try to copy the matplotlib figure as image - # Save the original figure size - original_size = self.matplot_figure.get_size_inches() if self.matplot_figure is not None and self.matplot_canvas is not None: try: - # Save figure to a temporary buffer as PNG - import io as iomodule - buf = iomodule.BytesIO() - self.matplot_figure.set_size_inches(6, 4) - self.matplot_figure.savefig(buf, format='png', dpi=300, bbox_inches='tight') - buf.seek(0) - - # Load the PNG data into a GdkPixbuf - from gi.repository import GdkPixbuf - loader = GdkPixbuf.PixbufLoader.new_with_type('png') - loader.write(buf.read()) - loader.close() - pixbuf = loader.get_pixbuf() + # Render off-screen at a fixed size (12:8 inches, 800 px + # wide) on a temporary Agg canvas. Snapshotting the GTK + # canvas buffer instead would copy the window size, and + # re-rendering through the GTK canvas would replace its + # renderer and leave the on-screen plot blank. + from matplotlib.backends.backend_agg import FigureCanvasAgg + figure = self.matplot_figure + orig_canvas = figure.canvas + orig_size = figure.get_size_inches( ) + orig_dpi = figure.dpi + try: + agg_canvas = FigureCanvasAgg( figure ) + figure.set_size_inches( 12, 8 ) + figure.dpi = 800 / 12 + agg_canvas.draw( ) + rgba = numpy.asarray( agg_canvas.buffer_rgba( ) ) + finally: + figure.set_canvas( orig_canvas ) + figure.set_size_inches( *orig_size ) + figure.dpi = orig_dpi + height, width = rgba.shape[ :2 ] + pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( + glib.Bytes.new( rgba.tobytes( ) ), GdkPixbuf.Colorspace.RGB, True, 8, + width, height, width * 4 ) # Copy to clipboard - clipboard = gtk.Clipboard.get(gdk.SELECTION_CLIPBOARD) - clipboard.set_image(pixbuf) - clipboard.store() - # Restore original figure size - self.matplot_figure.set_size_inches(original_size) - # Redraw the canvas to ensure it stays visible - self.matplot_canvas.draw() + clipboard = gtk.Clipboard.get( gdk.SELECTION_CLIPBOARD ) + clipboard.set_image( pixbuf ) - log("Figure copied to clipboard as PNG image") + logger.info("Figure copied to clipboard as PNG image") return except Exception as e: - log("Error copying figure to clipboard: %s" % str(e)) + logger.error("Error copying figure to clipboard: %s", e) ##################### functions to feed display def clear_display( self ): diff --git a/src/damaris/gui/damaris3.glade b/src/damaris/gui/damaris3.glade index 75ac801..9c36f3d 100644 --- a/src/damaris/gui/damaris3.glade +++ b/src/damaris/gui/damaris3.glade @@ -1414,10 +1414,56 @@ Public License instead of this License. - + + True + True + False + Copy plot as PNG image to clipboard + + + + True + False + 10 + <span foreground="#0000ff">PNG</span> + True + + + + + 3 + 4 + 1 + 2 + + GTK_FILL + - + + True + True + False + Copy plot as SVG to clipboard + + + + True + False + 10 + <span foreground="#0000ff">SVG</span> + True + + + + + 2 + 3 + 1 + 2 + + GTK_FILL +