"""Matplotlib backend to include matplotlib figures as dockwidgets in the
psyplot gui
This backend is based upon matplotlibs qt4agg and qt5agg backends."""
# SPDX-FileCopyrightText: 2016-2024 University of Lausanne
# SPDX-FileCopyrightText: 2020-2021 Helmholtz-Zentrum Geesthacht
# SPDX-FileCopyrightText: 2021-2024 Helmholtz-Zentrum hereon GmbH
#
# SPDX-License-Identifier: LGPL-3.0-only
from matplotlib.backend_bases import FigureManagerBase
from matplotlib.figure import Figure
from psyplot_gui.common import DockMixin
from psyplot_gui.compat.qtcompat import (
QDockWidget,
Qt,
QVBoxLayout,
QWidget,
with_qt5,
)
if with_qt5:
from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg,
FigureManagerQT,
)
else:
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg,
FigureManagerQT,
)
[docs]
class PsyplotCanvasManager(FigureManagerQT):
"""The canvas manager for the psyplot backend interacting with the
mainwindow of the psyplot gui"""
toolbar = None
def __init__(self, canvas, num):
from psyplot_gui.main import mainwindow
self.main = mainwindow
if mainwindow is None:
return super(PsyplotCanvasManager, self).__init__(canvas, num)
parent_widget = FigureWidget()
parent_widget.vbox = vbox = QVBoxLayout()
self.window = dock = parent_widget.to_dock(
mainwindow,
title="Figure %d" % num,
position=Qt.TopDockWidgetArea,
docktype=None,
)
if mainwindow.figures:
mainwindow.tabifyDockWidget(mainwindow.figures[-1], dock)
mainwindow.figures.append(dock)
FigureManagerBase.__init__(self, canvas, num)
self.canvas = canvas
self.window.setWindowTitle("Figure %d" % num)
if hasattr(self, "_get_toolbar"):
# legacy solution for matplotlib < 3.6
self.toolbar = self._get_toolbar(canvas, parent_widget)
# add text label to status bar
self.statusbar_label = mainwindow.figures_label
if self.toolbar is not None:
vbox.addWidget(self.toolbar)
self.toolbar.message.connect(self.statusbar_label.setText)
vbox.addWidget(canvas)
parent_widget.setLayout(vbox)
self.parent_widget = parent_widget
# Give the keyboard focus to the figure instead of the
# manager; StrongFocus accepts both tab and click to focus and
# will enable the canvas to process event w/o clicking.
# ClickFocus only takes the focus is the window has been
# clicked
# on. http://qt-project.org/doc/qt-4.8/qt.html#FocusPolicy-enum or
# http://doc.qt.digia.com/qt/qt.html#FocusPolicy-enum
self.canvas.setFocusPolicy(Qt.StrongFocus)
self.canvas.setFocus()
self.window._destroying = False
self.main.show()
def notify_axes_change(fig):
# This will be called whenever the current axes is changed
if self.toolbar is not None:
self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
[docs]
def statusBar(self, *args, **kwargs):
if self.main is None:
return super(PsyplotCanvasManager, self).statusBar(*args, **kwargs)
return self.main.statusBar(*args, **kwargs)
[docs]
def resize(self, width, height):
self.window.resize(width, height + self.toolbar.sizeHint().height())
[docs]
class PsyplotCanvas(FigureCanvasQTAgg):
"""The canvas class with reimplemented resizing"""
[docs]
def resizeEvent(self, event):
"""Reimplemented to make sure that the figure is only resized for
events with height and width greater 0"""
if event.size().width() > 0 and event.size().height() > 0:
super(PsyplotCanvas, self).resizeEvent(event)
FigureManager = PsyplotCanvasManager
FigureCanvas = PsyplotCanvas