From b7d9b890da8b4899f3618a786bad6047cbe22ccd Mon Sep 17 00:00:00 2001
From: anwinged <anwinged@c733b785-2984-70f4-63a9-da4130069974>
Date: Sun, 6 May 2012 08:24:08 +0000
Subject: [PATCH] plots ench

---
 trunk/opal.py | 138 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 93 insertions(+), 45 deletions(-)

diff --git a/trunk/opal.py b/trunk/opal.py
index 0d909f9..b51c039 100644
--- a/trunk/opal.py
+++ b/trunk/opal.py
@@ -50,16 +50,42 @@ class LineData:
     поэтому не имеет собственного значения названия. Вместо этого
     название берется из графического компонента.
     """
-    def __init__(self, type, mdata, columns, colour = None, style = None):
-        self.type       = type      # тип графика
-        self.mdata      = mdata     # указатель на данные модели
-        self.title      = ''
-        self.columns    = columns   # пара (x, y)
-        self.colour     = colour    # цвет: если не задан выбирается из списка
-        self.style      = style     # стиль: если не задан, еспользуется по умолчанию
+    def __init__(self, ums_ptr, plots_ptr,
+        type, columns, colour = None, style = None):
+
+        self.ums_ptr = ums_ptr      # (ptr, item) указатель на компонент с моделями
+                                    # и индекс в этом компоненте
+        self.plots_ptr = plots_ptr  # (ptr, item) указатель на компонент с графиками
+                                    # и индекс в этом компоненте
+
+        self.type = type            # тип графика
+        self.columns = columns      # пара (x, y)
+        self.colour = colour        # цвет: если не задан выбирается из списка
+        self.style = style          # стиль: если не задан, еспользуется по умолчанию
+
+    def GetTitle(self):
+        # если есть указатель на компонент с графиками,
+        # извлекаем оттуда название
+        if self.plots_ptr:
+            container, item = self.plots_ptr
+            return container.GetItemText(item)
+        # иначе формируем название на основе имени модели и
+        # имен выбранных столбцов
+        else:
+            container, item = self.ums_ptr
+            title = container.GetItemText(item)
+            data = container.GetPyData(item)
+            assert data.res # если результата нет, то а-та-та
+            colx, coly = self.columns
+            title_x = data.res.columns[colx].GetTitle()
+            title_y = data.res.columns[coly].GetTitle()
+            return "{}: {}({})".format(title, title_y, title_x)
 
     def GetPoints(self):
-        return self.mdata.res.Zip(*self.columns)
+        container, item = self.ums_ptr
+        data = container.GetPyData(item)
+        assert data.res # если результата нет, то а-та-та
+        return data.res.Zip(*self.columns)
 
 class ItemError(Exception):
     pass
@@ -601,47 +627,73 @@ class MainFrame(forms.MainFrame):
 
         Возвращает список экземпляров LineData
         """
-        um = self.m_user_models
-        item, data = self.GetSelectedItemData(um)
-        title = um.GetItemText(item)
-        if not data.res:
-            wx.MessageBox('There is no any result data', 'Warning', wx.OK | wx.ICON_EXCLAMATION)
-            return []
-        f = LineSelectDialog(self, 'Select lines for "{}"'.format(title))
-        for index, col in enumerate(data.res.columns):
-            row_title = col.GetTitle()
-            row_data  = index
-            f.Add(row_title, row_data)
-        f.SetSelections()
 
+        def CreateLineSelectDialog(parent, title, model_data):
+            f = LineSelectDialog(parent, title)
+            for index, col in enumerate(model_data.res.columns):
+                row_title = col.GetTitle()
+                row_data  = index
+                f.Add(row_title, row_data)
+            f.SetSelections()
+            return f
+
+        def GetLinesFromUser(select_dialog):
+            lines = []
+            self.do_nothing = True
+            try:
+                if select_dialog.ShowModal() == wx.ID_OK:
+                    for xy in select_dialog.GetLineColumns():
+                        line_data = LineData(
+                            (um, item), # указатель на модель
+                            None,       # указатель на график
+                            line_type, xy) # тип линии, колонки и прочее
+                        lines.append(line_data)
+                f.Destroy()
+            finally:
+                self.do_nothing = False
+            return lines
+
+        um = self.m_user_models
         lines = []
-        self.do_nothing = True
-        try:
-            if f.ShowModal() == wx.ID_OK:
-                lines = [ LineData(line_type, data, xy)
-                            for xy in f.GetLineColumns() ]
-        finally:
-            self.do_nothing = False
+        items = um.GetSelections()
+        count = len(items)
+        for index, item in enumerate(items, 1):
+            data = um.GetPyData(item)
+            title = um.GetItemText(item)
+
+            msg = 'Line(s) for "{}" ({}/{})'.format(title, index, count)
+
+            if not data.res:
+                wx.MessageBox(
+                    'There is no any result data for model!', 
+                    msg, wx.OK | wx.ICON_EXCLAMATION)
+            else:
+                f = CreateLineSelectDialog(self, msg, data)
+                lines += GetLinesFromUser(f)
 
         return lines
 
     @item_protector
     def AddLines(self, line_type):
+        """
+        Добавляет линии в выделенный график компонента с графиками
+        (m_plots)
+        """
+        # получаем указатель на индекс и данные элемента, который выделен
         item, data = self.GetSelectedItemData(self.m_plots)
+        # если это на контейнер с графиками, то выходим
         if data != 'plot':
             return
+        # получаем указанные пользователем линии
         lines = self.GetLines(line_type)
-        if not lines:
-            return
-        it = self.GetSelectedItem(self.m_user_models)
+        # if not lines:
+        #     return
         for line in lines:
-            x, y = line.columns
-            data = line.mdata
-            model_name = self.m_user_models.GetItemText(it)
-            x_name = data.res.columns[x].GetTitle()
-            y_name = data.res.columns[y].GetTitle()
-            title  = "{}: {}({})".format(model_name, y_name, x_name)
-            child  = self.m_plots.AppendItem(item, title)
+            title = line.GetTitle()
+            child = self.m_plots.AppendItem(item, title)
+            # указываем на только что созданный новый элемент
+            line.plots_ptr = (self.m_plots, child)
+            # заполняем элемент данными
             self.m_plots.SetPyData(child, line)
             self.m_plots.SetItemImage(child, self.icons.pline)
             self.m_plots.Expand(item)
@@ -663,14 +715,9 @@ class MainFrame(forms.MainFrame):
 
     def OnQuickShowPlot(self, event):
         lines = self.GetLines(LINE_CURVE)
-        um    = self.m_user_models
-        item, data = self.GetSelectedItemData(um)
+        um = self.m_user_models
+        item = self.GetSelectedItem(um)
         title = um.GetItemText(item)
-        for line in lines:
-            colx, coly = line.columns
-            title_x = data.res.columns[colx].GetTitle()
-            title_y = data.res.columns[coly].GetTitle()
-            line.title = "{}: {}({})".format(title, title_y, title_x)
         self.ShowPlot(lines, title)
 
     def OnPlotProcess(self, event):
@@ -853,6 +900,7 @@ class LineSelectDialog(forms.LineSelectDialog):
 class PlotFrame(forms.PlotFrame):
     def __init__(self, parent, title, lines):
         forms.PlotFrame.__init__(self, parent, title)
+        self.lines = lines      # список объектор LineData
 
         self.Bind(wx.EVT_MENU, self.OnSaveImage,
             id = forms.ID_SAVE_PLOT)
@@ -868,7 +916,7 @@ class PlotFrame(forms.PlotFrame):
                 handle = wxplot.PolyLine
             points = line.GetPoints()
             attr['colour'] = line.colour or colours[i % len(colours)]
-            attr['legend'] = line.title or 'Unknown line'
+            attr['legend'] = line.GetTitle() or 'Unknown line'
             plot_lines.append(handle(points, **attr))
 
         graph = wxplot.PlotGraphics(plot_lines)