From: jh777916 Date: Fri, 8 Sep 2023 13:21:18 +0000 (+0200) Subject: Adding a BarView for the MVC; New ID for the plots (bar+curves together); clickable... X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1bdb239564fa9ce8f90ac1f371a93c46db6282c1;p=modules%2Fgui.git Adding a BarView for the MVC; New ID for the plots (bar+curves together); clickable legend; updated highlighted text in legend --- diff --git a/tools/CurvePlot/src/python/controller/PlotController.py b/tools/CurvePlot/src/python/controller/PlotController.py index a75619fc2..af4fe052c 100644 --- a/tools/CurvePlot/src/python/controller/PlotController.py +++ b/tools/CurvePlot/src/python/controller/PlotController.py @@ -798,6 +798,8 @@ class PlotController(object): cps.setTitle(cps_title) cps.addCurve(bm) + Logger.Debug(" --- model ID when adding the barplot : {}".format(bm.getID())) + mp = self._curveTabsView.mapModId2ViewId() xyview_id = mp[cps.getID()] xyview = self._curveTabsView._XYViews[xyview_id] @@ -807,7 +809,7 @@ class PlotController(object): # Make CurveBrowser and CurveView depend on changes in the curve itself: self.setModelListener(bm, self._curveBrowserView) - self.setModelListener(bm, xyview._curveViews[bm.getID()]) + self.setModelListener(bm, xyview._curveViews[bm.getID()]) # TAG CHECK # Upon change on the curve also update the full plot, notably for the auto-fit and the legend: self.setModelListener(bm, xyview) diff --git a/tools/CurvePlot/src/python/model/BarModel.py b/tools/CurvePlot/src/python/model/BarModel.py index 1ba8d931b..bc9debadb 100644 --- a/tools/CurvePlot/src/python/model/BarModel.py +++ b/tools/CurvePlot/src/python/model/BarModel.py @@ -21,9 +21,11 @@ from .Model import Model from .utils import toUnicodeWithWarning class BarModel(Model): + def __init__(self, controller, table=None, isDirac=True, heightIndex=-1, widthIndex=-1): Model.__init__(self, controller) + # self.ID_PLOT += 1 self._name = "BarModel" self._title = "Barplot %d" % self.getID() self._table = table @@ -107,4 +109,4 @@ class BarModel(Model): self.notifyChange("XAxisIndexChange") def getID(self): - return self._id + return self._idPlot diff --git a/tools/CurvePlot/src/python/model/CurveModel.py b/tools/CurvePlot/src/python/model/CurveModel.py index 50cdf7f0c..56367d7ff 100644 --- a/tools/CurvePlot/src/python/model/CurveModel.py +++ b/tools/CurvePlot/src/python/model/CurveModel.py @@ -20,11 +20,12 @@ from .Model import Model from .utils import toUnicodeWithWarning -class CurveModel(Model): +class CurveModel(Model): + def __init__(self, controller, table=None, index=-1): Model.__init__(self, controller) - - # self._name = "CurveModel" + + self._name = "CurveModel" self._title = "Curve %d" % self.getID() self._table = table self._yaxisIndex = index # column index in the table @@ -84,6 +85,5 @@ class CurveModel(Model): self.notifyChange("XAxisIndexChange") def getID(self): - return self._id - + return self._idPlot diff --git a/tools/CurvePlot/src/python/model/Model.py b/tools/CurvePlot/src/python/model/Model.py index ff803ddf4..4fc9a6330 100644 --- a/tools/CurvePlot/src/python/model/Model.py +++ b/tools/CurvePlot/src/python/model/Model.py @@ -17,9 +17,12 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # +from collections import defaultdict + class Model(object): - START_ID = -1 - + START_ID = -1 + COUNT_MODELS = defaultdict(int) + @classmethod def __GenerateID(cls): cls.START_ID += 1 @@ -28,10 +31,18 @@ class Model(object): def __init__( self, controller ): """Constructor""" + # Counting instances of classes (Model) and subclasses + for cls in self.__class__.__mro__: + self.COUNT_MODELS[cls.__name__] += 1 + self._name = None self._controller = controller self._id = self.__GenerateID() # A unique ID for this class of object - + + # A unique ID for the traces (Curves and Bars), starting from 0 + self._idPlot = self.COUNT_MODELS["CurveModel"] \ + + self.COUNT_MODELS["BarModel"] - 1 + def getID(self): return self._id diff --git a/tools/CurvePlot/src/python/model/XYPlotSetModel.py b/tools/CurvePlot/src/python/model/XYPlotSetModel.py index 6b8795559..c960e258b 100644 --- a/tools/CurvePlot/src/python/model/XYPlotSetModel.py +++ b/tools/CurvePlot/src/python/model/XYPlotSetModel.py @@ -19,6 +19,7 @@ from .Model import Model from .utils import toUnicodeWithWarning +from .utils import Logger class XYPlotSetModel(Model): @@ -55,7 +56,20 @@ class XYPlotSetModel(Model): return self._currentCurve def addCurve(self, curve, silent=False): + # if self._curves: + # lastID = max(list(self._curves.keys())) + # else : + # lastID = -1 + + # # if (curve.getID() >= lastID): + # # newLastID = curve.getID() + # # else : + # self._lastID += 1 + self._curves[curve.getID()] = curve + + Logger.Debug(" ---- XYPlotSetModel::addCurve( curve ) -> curve.getID() = {}".format(curve.getID())) + # Logger.Debug(" ---- XYPlotSetModel::addCurve( curve ) -> _curves new last ID = {}".format(self._lastID)) if not silent: self.notifyChange("AddCurve") diff --git a/tools/CurvePlot/src/python/test/PlotCurve_Standalone_test.py b/tools/CurvePlot/src/python/test/PlotCurve_Standalone_test.py index 90bb89a05..08db134ff 100755 --- a/tools/CurvePlot/src/python/test/PlotCurve_Standalone_test.py +++ b/tools/CurvePlot/src/python/test/PlotCurve_Standalone_test.py @@ -31,7 +31,7 @@ def activate(): """This method mimicks SALOME's module activation """ global desktop - #desktop.showCurveTreeView() + desktop.showCurveTreeView() return True def activeViewChanged( viewID ): diff --git a/tools/CurvePlot/src/python/test/TestDesktop_test.py b/tools/CurvePlot/src/python/test/TestDesktop_test.py index 0e6340e33..0a3ef732a 100755 --- a/tools/CurvePlot/src/python/test/TestDesktop_test.py +++ b/tools/CurvePlot/src/python/test/TestDesktop_test.py @@ -205,8 +205,8 @@ class TestDesktop_test(QMainWindow): x_label="Energy", y_label="Intensity", append=True) curveplot.SetLegendVisible(ps_id, True) - if self.cnt >= 0: - QTimer.singleShot(self.timeLap, self, SLOT("itemDel()")) + # if self.cnt >= 0: + # QTimer.singleShot(self.timeLap, self, SLOT("itemDel()")) @pyqtSlot() def addBarplotNonDirac(self): @@ -233,12 +233,13 @@ class TestDesktop_test(QMainWindow): cont = curveplot.PlotController.GetInstance() crv_id, ps_id = cont.plotBarPlotFromTable(t, isDirac, x_col_index=0, height_col_index=1, width_col_index=2, - curve_label=bar_label, append=True) + curve_label=bar_label, + append=True) curveplot.SetLegendVisible(ps_id, True) - if self.cnt >= 0: - QTimer.singleShot(self.timeLap, self, SLOT("itemDel()")) + # if self.cnt >= 0: + # QTimer.singleShot(self.timeLap, self, SLOT("itemDel()")) def clearPlotSet(self): diff --git a/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.py b/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.py index 862a6f1c6..636603cc6 100644 --- a/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.py +++ b/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.py @@ -26,8 +26,8 @@ class CurveTreeDockWidget(QtWidgets.QDockWidget): QtWidgets.QDockWidget.__init__(self) loadUiGen(completeResPath("CurveTreeDockWidget.ui"), self) self.treeWidget.setHeaderLabel ("Plots") - self.treeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder) - self.treeWidget.setSortingEnabled(True); + # self.treeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder) + # self.treeWidget.setSortingEnabled(True); self.treeWidget.setColumnHidden(1, True); def getTreeWidget(self): diff --git a/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.ui b/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.ui index b13925a3a..8ebb730e0 100644 --- a/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.ui +++ b/tools/CurvePlot/src/python/ui/CurveTreeDockWidget.ui @@ -18,7 +18,7 @@ - true + false 2 diff --git a/tools/CurvePlot/src/python/views/BarView.py b/tools/CurvePlot/src/python/views/BarView.py new file mode 100644 index 000000000..187af9b14 --- /dev/null +++ b/tools/CurvePlot/src/python/views/BarView.py @@ -0,0 +1,120 @@ +# Copyright (C) 2016-2022 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from .View import View +from .utils import Logger + +class BarView(View): + _PICKER_PRECISION_BAR = 5 #pts + + def __init__(self, controller, parentXYView): + View.__init__(self, controller) + self._mplAxes = None + self._mplBars = None + + self._isHighlighted = False + self._initialLineWidth = None + self._initialEdgeColorBar = None + self._initialAlpha = None + self._parentXYView = parentXYView + + self._facecolor = None + self._opacity = None + + def setMPLAxes(self, axes): + self._mplAxes = axes + + def erase(self): + self._mplBars.remove() + self._mplBars = None + + def draw(self): + m = self._model + x_idx, height_idx, width_idx = m.getXAxisIndex(), m.getHeightIndex(), m.getWidthIndex() + x_align = "center" if m.getIsDirac() else "edge" + d = self._model.getTable().getData() + + self._mplBars = self._mplAxes.bar(d[:, x_idx], d[:, height_idx], width=d[:, width_idx], + align=x_align, label=m._title, alpha= 0.7, + picker=self._PICKER_PRECISION_BAR) + + self._initialLineWidth = 0. #self._mplBars[0].get_linewidth() + self._initialEdgeColorBar = self._mplBars[0].get_edgecolor() + self._initialAlpha = self._mplBars[0].get_alpha() + + # Logger.Debug(" > Bar initial lw : {}".format(self._initialLineWidth)) + # Logger.Debug(" > Bar initial ec : {}".format(self._initialEdgeColorBar)) + # Logger.Debug(" > Bar initial alpha : {}".format(self._initialAlpha)) + + def onCurveTitleChange(self): + if self._mplBars is None: + return + self._mplBars.set_label(self._model._title) + + def update(self): + Logger.Debug("BarView::udpate") + + if self._mplBars is None: + return + color = self.getColor() + opacity = self.getAlpha() + self.erase() + self.draw() + self.setColor(color) + self.setAlpha(opacity) + self.toggleHighlight(self._isHighlighted, force=True) + + def toggleHighlight(self, highlight, force=False): + bar = self._mplBars.patches # TAG CHECK + if highlight and (force or not self._isHighlighted): + for rect in bar : + rect.set_linewidth(1.) + rect.set_alpha(1) + rect.set_edgecolor("crimson") + self._isHighlighted = True + elif not highlight and (force or self._isHighlighted): + for rect in bar : + rect.set_linewidth(self._initialLineWidth) + rect.set_alpha(self._initialAlpha) + rect.set_edgecolor(self._initialEdgeColorBar) + self._isHighlighted = False + else: + # Nothing to do, already the correct state + return + + def isHighlighted(self): + return self._isHighlighted + + def setColor(self, rgb_color): + for rect in self._mplBars : + rect.set_facecolor(rgb_color) + + def getColor(self): + if self._mplBars is None: + return None + return self._mplBars[0].get_facecolor() + + def setAlpha(self, opacity): + for rect in self._mplBars: + rect.set_alpha(opacity) + + def getAlpha(self): + if self._mplBars is None: + return None + return self._mplBars[0].get_alpha() diff --git a/tools/CurvePlot/src/python/views/CMakeLists.txt b/tools/CurvePlot/src/python/views/CMakeLists.txt index 39420d15f..6ec77d1f1 100644 --- a/tools/CurvePlot/src/python/views/CMakeLists.txt +++ b/tools/CurvePlot/src/python/views/CMakeLists.txt @@ -22,6 +22,7 @@ SET(_all_lib_SCRIPTS CurveBrowserView.py CurveTabsView.py CurveView.py + BarView.py XYView.py ) diff --git a/tools/CurvePlot/src/python/views/CurveView.py b/tools/CurvePlot/src/python/views/CurveView.py index 8feae780d..064172c46 100644 --- a/tools/CurvePlot/src/python/views/CurveView.py +++ b/tools/CurvePlot/src/python/views/CurveView.py @@ -21,119 +21,66 @@ from .View import View from .utils import Logger class CurveView(View): - _PICKER_PRECISION = 20 #pts - _PICKER_PRECISION_BAR = 5 #pts + _PICKER_PRECISION = 10 #pts def __init__(self, controller, parentXYView): View.__init__(self, controller) self._mplAxes = None self._mplLines = None - self._mplBars = None self._isHighlighted = False self._initialLineWidth = None - self._initialEdgeColorBar = None - self._initialAlpha = None self._parentXYView = parentXYView self._marker = None self._color = None - self._opacity = None self._lineStyle = None def setMPLAxes(self, axes): self._mplAxes = axes def erase(self): - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - self._mplBars.remove() - self._mplBars = None - else: - self._mplAxes.lines.remove(self._mplLines[0]) - self._mplLines = None + self._mplAxes.lines.remove(self._mplLines[0]) + self._mplLines = None def draw(self): m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - x_idx, height_idx, width_idx = m.getXAxisIndex(), m.getHeightIndex(), m.getWidthIndex() - x_align = "center" if m.getIsDirac() else "edge" - d = self._model.getTable().getData() - - self._mplBars = self._mplAxes.bar(d[:, x_idx], d[:, height_idx], width=d[:, width_idx], - align=x_align, label=m._title, alpha= 0.7, - picker=self._PICKER_PRECISION_BAR) - - self._initialLineWidth = 0. #self._mplBars[0].get_linewidth() - self._initialEdgeColorBar = self._mplBars[0].get_edgecolor() - self._initialAlpha = self._mplBars[0].get_alpha() - - Logger.Debug(" > Bar initial lw : {}".format(self._initialLineWidth)) - Logger.Debug(" > Bar initial ec : {}".format(self._initialEdgeColorBar)) - Logger.Debug(" > Bar initial alpha : {}".format(self._initialAlpha)) - else: - x_idx, y_idx = m.getXAxisIndex(), m.getYAxisIndex() - d = self._model.getTable().getData() - self._mplLines = self._mplAxes.plot(d[:, x_idx], d[:, y_idx], label=m._title, - picker=self._PICKER_PRECISION) - self._initialLineWidth = self._mplLines[0].get_linewidth() + x_idx, y_idx = m.getXAxisIndex(), m.getYAxisIndex() + d = self._model.getTable().getData() + self._mplLines = self._mplAxes.plot(d[:, x_idx], d[:, y_idx], label=m._title, + picker=self._PICKER_PRECISION) + self._initialLineWidth = self._mplLines[0].get_linewidth() def onCurveTitleChange(self): - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - if self._mplBars is None: - return - self._mplBars.set_label(self._model._title) - else: - if self._mplLines is None: - return - self._mplLines[0].set_label(self._model._title) + if self._mplLines is None: + return + self._mplLines[0].set_label(self._model._title) def update(self): Logger.Debug("CurveView::udpate") - - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - if self._mplBars is None: - return - color = self.getColor() - opacity = self.getAlpha() - self.erase() - self.draw() - self.setColor(color) - self.setAlpha(opacity) - self.toggleHighlight(self._isHighlighted, force=True) - else: - if self._mplLines is None: - return - lineStyle, marker, color = self.getLineStyle(), self.getMarker(), self.getColor() - self.erase() - self.draw() - # Reset correctly color, marker and highlight state - self.setLineStyle(lineStyle) - self.setMarker(marker) - self.setColor(color) - self.toggleHighlight(self._isHighlighted, force=True) + if self._mplLines is None: + return + lineStyle, marker, color = self.getLineStyle(), self.getMarker(), self.getColor() + self.erase() + self.draw() + # Reset correctly color, marker and highlight state + self.setLineStyle(lineStyle) + self.setMarker(marker) + self.setColor(color) + self.toggleHighlight(self._isHighlighted, force=True) def setLineStyle(self, lin_style): - if (self._model._name != "BarModel"): - lin = self._mplLines[0] - lin.set_linestyle(lin_style) + lin = self._mplLines[0] + lin.set_linestyle(lin_style) def getLineStyle(self): - if (self._model._name != "BarModel"): - if self._mplLines is None: - return None - return self._mplLines[0].get_linestyle() + if self._mplLines is None: + return None + return self._mplLines[0].get_linestyle() def setMarker(self, marker): - if (self._model._name != "BarModel"): - lin = self._mplLines[0] - lin.set_marker(marker) + lin = self._mplLines[0] + lin.set_marker(marker) def getMarker(self): if self._mplLines is None: @@ -141,78 +88,34 @@ class CurveView(View): return self._mplLines[0].get_marker() def toggleHighlight(self, highlight, force=False): - if (self._model._name == "BarModel"): - bar = self._mplBars.patches - if highlight and (force or not self._isHighlighted): - for rect in bar : - rect.set_linewidth(1.) - rect.set_alpha(1) - rect.set_edgecolor("red") - self._isHighlighted = True - elif not highlight and (force or self._isHighlighted): - for rect in bar : - rect.set_linewidth(self._initialLineWidth) - rect.set_alpha(self._initialAlpha) - rect.set_edgecolor(self._initialEdgeColorBar) - self._isHighlighted = False - else: - # Nothing to do, already the correct state - return + lin = self._mplLines[0] + if highlight and (force or not self._isHighlighted): + lin.set_linewidth(2*self._initialLineWidth) + self._isHighlighted = True + elif not highlight and (force or self._isHighlighted): + lin.set_linewidth(self._initialLineWidth) + self._isHighlighted = False else: - lin = self._mplLines[0] - if highlight and (force or not self._isHighlighted): - lin.set_linewidth(2*self._initialLineWidth) - self._isHighlighted = True - elif not highlight and (force or self._isHighlighted): - lin.set_linewidth(self._initialLineWidth) - self._isHighlighted = False - else: - # Nothing to do, already the correct state - return + # Nothing to do, already the correct state + return def isHighlighted(self): return self._isHighlighted def setColor(self, rgb_color): - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - for rect in self._mplBars : - rect.set_facecolor(rgb_color) - else: - lin = self._mplLines[0] - lin.set_color(rgb_color) + lin = self._mplLines[0] + lin.set_color(rgb_color) def getColor(self): - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - if self._mplBars is None: - return None - return self._mplBars[0].get_facecolor() - else: - if self._mplLines is None: - return None - return self._mplLines[0].get_color() + if self._mplLines is None: + return None + return self._mplLines[0].get_color() def setAlpha(self, opacity): - m = self._model - # Check si BarModel ou CurveModel00 - if (m._name == "BarModel"): - for rect in self._mplBars: - rect.set_alpha(opacity) - else: - lin = self._mplLines[0] - lin.set_alpha(opacity) + lin = self._mplLines[0] + lin.set_alpha(opacity) def getAlpha(self): - m = self._model - # Check si BarModel ou CurveModel - if (m._name == "BarModel"): - if self._mplBars is None: - return None - return self._mplBars[0].get_alpha() - else: - if self._mplLines is None: - return None - return self._mplLines[0].get_alpha() + if self._mplLines is None: + return None + return self._mplLines[0].get_alpha() diff --git a/tools/CurvePlot/src/python/views/XYView.py b/tools/CurvePlot/src/python/views/XYView.py index 738da3224..9c039c9d0 100644 --- a/tools/CurvePlot/src/python/views/XYView.py +++ b/tools/CurvePlot/src/python/views/XYView.py @@ -27,6 +27,7 @@ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationTool from .View import View from .CurveView import CurveView +from .BarView import BarView from .PlotWidget import PlotWidget from .PlotSettings import PlotSettings from .utils import Logger, trQ @@ -75,7 +76,7 @@ class XYView(View): View.__init__(self, controller) self._eventHandler = EventHandler() - self._curveViews = {} # key: curve (model) ID, value: CurveView + self._curveViews = {} # key: trace ID (BarModel + CurveModel), value: CurveView / BarView self._salomeViewID = None self._mplFigure = None self._mplAxes = None @@ -123,12 +124,19 @@ class XYView(View): newC.setModel(self._model._curves[curveID]) newC.setMPLAxes(self._mplAxes) newC.draw() - if (self._model._curves[curveID]._name == "BarModel"): - Logger.Debug(" > Appending a bar model") - else: - newC.setMarker(self.getMarker(go_next=True)) + newC.setMarker(self.getMarker(go_next=True)) + Logger.Debug(" ** > appendCurve() crvID = {}".format(curveID)) self._curveViews[curveID] = newC + def appendBarplot(self, curveID): + Logger.Debug(" > Appending a bar model") + newB = BarView(self._controller, self) + newB.setModel(self._model._curves[curveID]) + newB.setMPLAxes(self._mplAxes) + newB.draw() + Logger.Debug(" ** > appendBarplot() crvID = {}".format(curveID)) + self._curveViews[curveID] = newB + def removeCurve(self, curveID): v = self._curveViews.pop(curveID) v.erase() @@ -172,7 +180,7 @@ class XYView(View): def onClearAll(self): """ Just does an update with a reset of the marker cycle. """ if self.__repaintOK(): - if (self._model._name != "BarModel") : self._lastMarkerID = -1 + self._lastMarkerID = -1 self.update() def onPick(self, event): @@ -185,18 +193,38 @@ class XYView(View): a = event.artist Logger.Debug(" > Artist picked : {}".format(a)) + # Checks if the picked item is a legend handler artist if self._legend is not None: + h, l = self._mplAxes.get_legend_handles_labels() + + # For text + for leg_idx,legText in enumerate(self._legend.get_texts()): + if legText is a : + # Gets the associated plot from the axes.legend handles + selected_plot = h[leg_idx] + # Gets the id from the curveViews + for crv_id, cv in list(self._curveViews.items()): + if (cv._model._name == "BarModel") : + if selected_plot is cv._mplBars: + selected_id = crv_id + if (cv._model._name == "CurveModel") : + if selected_plot in cv._mplLines: + selected_id = crv_id + for leg_idx,legHandler in enumerate(self._legend.legendHandles): if legHandler is a : - selected_id = leg_idx + # Gets the associated plot from the axes.legend handles + selected_plot = h[leg_idx] + # Gets the id from the curveViews + for crv_id, cv in list(self._curveViews.items()): + if (cv._model._name == "BarModel") : + if selected_plot is cv._mplBars: + selected_id = crv_id + if (cv._model._name == "CurveModel") : + if selected_plot in cv._mplLines: + selected_id = crv_id + Logger.Debug("Legend {} selected".format(selected_id)) - # if legHandler is a: - # Logger.Debug(" ---> Picked artist : {}, adress : {}".format(legHandler, id(legHandler))) - # for crv_id, cv in list(self._curveViews.items()): - # if (cv._model._name == "BarModel") : - # if legHandler in cv._mplBars: - # selected_id = crv_id - # Logger.Debug("Barplot {} selected".format(selected_id)) for crv_id, cv in list(self._curveViews.items()): if (cv._model._name == "BarModel") : @@ -481,10 +509,12 @@ class XYView(View): raise Exception("Invalid legend placement! Must be 'bottom' or 'right'") - # Trying to set legend items pickable - Logger.Debug(" > Legend handles : {}".format(self._legend.legendHandles)) - for handler in self._legend.legendHandles: # legend_handles in newer versions of matplotlib ... + # Setting legend handle and text items pickable + for handler in self._legend.legendHandles: # legendHandles combines patches and lines (.legend_handles in matplotlib 3.7) handler.set_picker(True) + for text in self._legend.get_texts(): + text.set_picker(True) + # Canvas must be drawn so we can adjust the figure placement: self._mplCanvas.draw() @@ -500,16 +530,27 @@ class XYView(View): self._mplCanvas.draw() self.__adjustFigureMargins(withLegend=False) - curr_crv = self._model._currentCurve - if curr_crv is None: curr_title = None - else: curr_title = curr_crv.getTitle() + # Update how the text is highlighted in the legend : + # + Correction of the bug where all same text labels are highlighted if self._legend is not None: - for label in self._legend.get_texts() : - text = label.get_text() - if (text == curr_title): - label.set_backgroundcolor('0.85') - else : - label.set_backgroundcolor('white') + curr_crv = self._model._currentCurve + if curr_crv is not None : + h, l = self._mplAxes.get_legend_handles_labels() + print(h) + view = self._curveViews[curr_crv.getID()] + if curr_crv._name == "CurveModel": + whatToGet = view._mplLines[0] + elif curr_crv._name == "BarModel": + whatToGet = view._mplBars + else: + raise Exception("Invalid model for the current curve") + legCurr_idx = h.index(whatToGet) + legLabelCurr_crv = self._legend.get_texts()[legCurr_idx] + legLabelCurr_crv.set_backgroundcolor('0.85') + else : + # Nothing is selected + for label in self._legend.get_texts(): + label.set_backgroundcolor('white') if repaint: self.repaint() @@ -532,28 +573,38 @@ class XYView(View): dlg.axisXMaxEdit.setText(xmaxText) dlg.axisYMinEdit.setText(yminText) dlg.axisYMaxEdit.setText(ymaxText) - # List of markers - dlg.markerCurve.clear() - for marker in self.CURVE_MARKERS : - dlg.markerCurve.addItem(marker) + curr_crv = self._model.getCurrentCurve() - if not curr_crv is None: + if curr_crv is None: + dlg.colorCurve.setEnabled(False) + dlg.markerCurve.setEnabled(False) + dlg.setSelectedCurveName("") + view = None + else: dlg.colorCurve.setEnabled(True) - dlg.markerCurve.setEnabled(True) name = curr_crv.getTitle() dlg.setSelectedCurveName(name) view = self._curveViews[curr_crv.getID()] - marker = view.getMarker() color = view.getColor() - index = dlg.markerCurve.findText(marker) - dlg.markerCurve.setCurrentIndex(index) rgb = colors.colorConverter.to_rgb(color) dlg.setRGB(rgb[0],rgb[1],rgb[2]) - else : - dlg.colorCurve.setEnabled(False) - dlg.markerCurve.setEnabled(False) - dlg.setSelectedCurveName("") - view = None + + if curr_crv._name == "CurveModel": + # List of markers + dlg.markerCurve.show() + dlg.markerCurveLabel.show() + dlg.markerCurve.clear() + for marker in self.CURVE_MARKERS : + dlg.markerCurve.addItem(marker) + dlg.markerCurve.setEnabled(True) + marker = view.getMarker() + index = dlg.markerCurve.findText(marker) + dlg.markerCurve.setCurrentIndex(index) + + if curr_crv._name == "BarModel": + dlg.markerCurve.hide() + dlg.markerCurveLabel.hide() + if self._legend is None: dlg.showLegendCheckBox.setChecked(False) dlg.legendPositionComboBox.setEnabled(False) @@ -600,8 +651,9 @@ class XYView(View): # Color and marker of the curve if view: view.setColor(dlg.getRGB()) - view.setMarker(self.CURVE_MARKERS[dlg.markerCurve.currentIndex()]) crvModel = view._model + if curr_crv._name == "CurveModel": + view.setMarker(self.CURVE_MARKERS[dlg.markerCurve.currentIndex()]) if dlg.nameCurve.text() != crvModel.getTitle(): Logger.Debug("XYView : about to cahnge crv title after settings") view._model.setTitle(dlg.nameCurve.text()) @@ -664,19 +716,32 @@ class XYView(View): set_mod = set(self._model._curves.keys()) set_view = set(self._curveViews.keys()) + Logger.Debug(" --- List of models ID: {}".format(set_mod)) + Logger.Debug(" --- List of views ID: {}".format(set_view)) + # Deleted/Added curves: dels = set_view - set_mod added = set_mod - set_view + Logger.Debug(" --- List of dels ID: {}".format(dels)) + Logger.Debug(" --- List of added ID: {}".format(added)) + for d in dels: self.removeCurve(d) if not len(self._curveViews): # Reset color cycle + Logger.Debug(" ---- !! Resetting color cycle ...") self._mplAxes.set_prop_cycle(None) for a in added: - self.appendCurve(a) + if ( self._model._curves[a]._name == "CurveModel" ) : + self.appendCurve(a) + elif ( self._model._curves[a]._name == "BarModel" ) : + self.appendBarplot(a) + else: + # Should not happen + raise Exception("Invalid specified curve type") # Axes labels and title self._mplAxes.set_xlabel(self._model._xlabel)