source: sasview/sansguiframe/src/sans/guiframe/data_processor.py @ 5425990

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 5425990 was 5425990, checked in by Gervaise Alina <gervyh@…>, 13 years ago

add cell class

  • Property mode set to 100644
File size: 40.0 KB
Line 
1"""
2Implement grid used to store data
3"""
4import wx
5import numpy
6import math
7import re
8import os
9import sys
10import copy
11from wx.lib.scrolledpanel import ScrolledPanel
12import  wx.grid as  Grid
13import wx.aui
14from wx.aui import AuiNotebook as nb
15from sans.guiframe.panel_base import PanelBase
16import wx.lib.sheet as sheet
17
18from sans.guiframe.events import NewPlotEvent
19from sans.guiframe.events import StatusEvent 
20from sans.guiframe.dataFitting import Data1D
21
22FUNC_DICT = {"sqrt": "math.sqrt",
23             "pow": "math.sqrt"}
24
25class BatchCell:
26    """
27    Object describing a cell in  the grid.
28   
29    """
30    def __init__(self):
31        self.label = ""
32        self.value = None
33        self.col = -1
34        self.row = -1
35        self.object = None
36       
37
38def parse_string(sentence, list):
39    """
40    Return a dictionary of column label and index or row selected
41    :param sentence: String to parse
42    :param list: list of columns label
43    """
44    toks = []
45    p2 = re.compile(r'\d+')
46    p = re.compile(r'[\+\-\*\%\/]')
47    labels = p.split(sentence)
48    col_dict = {}
49    for elt in labels:
50        rang = None
51        temp_arr = []
52        for label in  list:
53            label_pos =  elt.find(label)
54            if label_pos != -1:
55                if elt.count(',') > 0:
56                    new_temp = []
57                    temp = elt.split(label)
58                    for item in temp:
59                        range_pos = item.find(":")
60                        if range_pos != -1:
61                            rang = p2.findall(item)
62                            for i in xrange(int(rang[0]), int(rang[1])+1 ):
63                                new_temp.append(i)
64                    temp_arr += new_temp
65                else:
66                    temp = elt.split(label)
67                    for item in temp:
68                        range_pos = item.find(":")
69                        if range_pos != -1:
70                            rang = p2.findall(item)
71                            for i in xrange(int(rang[0]), int(rang[1])+1 ):
72                                temp_arr.append(i)
73                col_dict[elt] = (label, temp_arr)
74    return col_dict
75
76         
77         
78class SPanel(ScrolledPanel):
79    def __init__(self, parent, *args, **kwds):
80        ScrolledPanel.__init__(self, parent , *args, **kwds)
81        self.SetupScrolling() 
82       
83class GridPage(sheet.CSheet):
84    """
85    """
86    def __init__(self, parent, panel=None):
87        """
88        """
89        sheet.CSheet.__init__(self, parent)
90       
91        self.AdjustScrollbars()
92        #self.SetLabelBackgroundColour('#DBD4D4')
93        self.parent = parent
94        self.panel = panel
95        self.col_names = []
96        self.data_inputs = {}
97        self.data_outputs = {}
98        self.data = None
99        self.details = ""
100        self.file_name = None
101        self._cols = 50
102        self._rows = 51
103        col_with = 30
104        row_height = 20
105        self.max_row_touse = 0
106        self.axis_value = []
107        self.axis_label = ""
108        self.selected_cells = []
109        self.selected_cols = []
110        self.SetColMinimalAcceptableWidth(col_with)
111        self.SetRowMinimalAcceptableHeight(row_height)
112        self.SetNumberRows(self._cols)
113        self.SetNumberCols(self._rows)
114        self.AutoSize()
115        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
116        self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
117        self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.on_selected_cell)
118        self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.on_edit_cell)
119       
120    def on_edit_cell(self, event):
121        """
122        """
123        row, col = event.GetRow(), event.GetCol()
124        if row > self.max_row_touse:
125            self.max_row_touse = row
126        event.Skip()
127       
128    def on_selected_cell(self, event):
129        """
130        Handler catching cell selection
131        """
132        flag = event.CmdDown() or event.ControlDown()
133        row, col = event.GetRow(), event.GetCol()
134        cell = (row, col)
135        if not flag:
136            self.selected_cells = []
137            self.axis_value = []
138            self.axis_label = ""
139        if cell not in self.selected_cells:
140            if row > 0:
141                self.selected_cells.append(cell)
142        else:
143            if flag:
144                self.selected_cells.remove(cell)
145        self.axis_value = []
146        for cell_row, cell_col in self.selected_cells:
147            if cell_row > 0 and cell_row < self.max_row_touse:
148                self.axis_value.append(self.GetCellValue(cell_row, cell_col))
149        self.axis_label = self.GetCellValue(0, col)
150        event.Skip()
151     
152    def on_left_click(self, event):
153        """
154        Catch the left click on label mouse event
155        """
156        event.Skip()
157        flag = event.CmdDown() or event.ControlDown()
158        col = event.GetCol()
159        if not flag:
160            self.selected_cols = []
161            self.selected_cells = []
162            self.axis_label = ""
163        if col != -1:
164            for row in range(1, self.GetNumberRows()+ 1):
165                cell = (row, col)
166                if row > 0 and row < self.max_row_touse:
167                    if cell not in self.selected_cells:
168                        self.selected_cells.append(cell)
169            self.selected_cols.append(col)
170            self.axis_value = []
171            for cell_row, cell_col in self.selected_cells:
172                self.axis_value.append(self.GetCellValue(cell_row, cell_col))
173            self.axis_label = self.GetCellValue(0, col)
174       
175
176    def on_right_click(self, event):
177        """
178        Catch the right click mouse
179        """
180       
181        col = event.GetCol()
182        self.selected_cols = []
183        self.selected_cols.append(col)
184        # Slicer plot popup menu
185        slicerpop = wx.Menu()
186        col_label_menu  = wx.Menu()
187        slicerpop.AppendSubMenu(col_label_menu , 
188                                 '&Insert Column', 'Insert Column')
189        col_name = [self.GetCellValue(0, c) 
190                        for c in range(self.GetNumberCols())]
191        row = 0
192        label = self.GetCellValue(row, col)
193        self.insert_col_menu(col_label_menu, label, self)
194        id = wx.NewId()   
195        hint = 'Remove selected column %s'
196        slicerpop.Append(id, '&Remove Column', hint)
197        wx.EVT_MENU(self, id, self.on_remove_column)
198       
199        pos = wx.GetMousePosition()
200        pos = self.ScreenToClient(pos)
201        self.PopupMenu(slicerpop, pos)
202        event.Skip()
203       
204    def insert_col_menu(self, menu, label, window):
205        """
206        """
207        id = wx.NewId()
208        title = "Empty"
209        hint = 'Insert empty column before %s' % str(label)
210        menu.Append(id, title, hint)
211        wx.EVT_MENU(window, id, self.on_insert_column)
212        col_name = [self.GetCellValue(0, col) 
213                        for col in range(self.GetNumberCols())]
214        for c_name in self.data.keys():
215            if c_name not in col_name:
216                id = wx.NewId()
217                hint = "Insert %s column before the " % str(c_name)
218                hint += " %s column" % str(label)
219                menu.Append(id, '&%s' % str(c_name), hint)
220                wx.EVT_MENU(window, id, self.on_insert_column)
221           
222               
223    def on_remove_column(self, event=None):
224        """
225        """
226        if self.selected_cols is not None or len(self.selected_cols) > 0:
227            col = self.selected_cols[0]
228            self.remove_column(col=col, numCols=1)
229           
230    def remove_column(self, col, numCols=1):
231        """
232        Remove column to the current grid
233        """
234        # add data to the grid   
235        row = 0
236        col_name = self.GetCellValue(row, col)
237        self.data[col_name] = []
238        for row in range(1, self.GetNumberRows() + 1):
239            if row < self.max_row_touse:
240                value = self.GetCellValue(row, col)
241                self.data[col_name].append(value)
242                for k , value_list in self.data.iteritems():
243                    if k != col_name:
244                        length = len(value_list)
245                        if length < self.max_row_touse:
246                            diff = self.max_row_touse - length
247                            for i in range(diff):
248                                self.data[k].append("")
249        self.DeleteCols(pos=col, numCols=numCols, updateLabels=True)
250           
251    def on_insert_column(self, event):
252        """
253        """
254        if self.selected_cols is not None or len(self.selected_cols) > 0:
255            col = self.selected_cols[0]
256            # add data to the grid   
257            row = 0
258            id = event.GetId()
259            col_name = event.GetEventObject().GetLabelText(id)
260            self.insert_column(col=col, col_name=col_name)
261            if  not issubclass(event.GetEventObject().__class__ , wx.Menu):
262                col += 1
263                self.selected_cols[0] += 1
264           
265    def insert_column(self, col, col_name):
266        """
267        """ 
268         
269        row = 0
270        self.InsertCols(pos=col, numCols=1, updateLabels=True)
271        if col_name.strip() != "Empty":
272            self.SetCellValue(row, col, str(col_name.strip()))
273        if col_name in self.data.keys():
274            value_list = self.data[col_name]
275            cell_row =  1
276            for value in value_list:
277                self.SetCellValue(cell_row, col, str(value))
278                cell_row += 1
279       
280       
281    def on_set_x_axis(self, event):
282        """
283        """
284        self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
285   
286    def on_set_y_axis(self, event):
287        """
288        """
289        self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)     
290           
291    def set_data(self, data_inputs, data_outputs, details, file_name):
292        """
293        Add data to the grid
294        :param data_inputs: data to use from the context menu of the grid
295        :param data_ouputs: default columns deplayed
296        """
297        self.file_name = file_name
298        self.details = details
299       
300        if data_outputs is None:
301            data_outputs = {}
302        self.data_outputs = data_outputs
303        if data_inputs is None:
304            data_inputs = {}
305        self.data_inputs = data_inputs
306        self.data = {}
307        for item in (self.data_outputs, self.data_inputs):
308            self.data.update(item)
309        if  len(self.data_outputs) > 0:
310            self._cols = self.GetNumberCols()
311            self._rows = self.GetNumberRows()
312            self.col_names = self.data_outputs.keys()
313            self.col_names.sort() 
314            nbr_user_cols = len(self.col_names)
315            #Add more columns to the grid if necessary
316            if nbr_user_cols > self._cols:
317                new_col_nbr = nbr_user_cols -  self._cols
318                self.AppendCols(new_col_nbr, True)
319            #Add more rows to the grid if necessary 
320            nbr_user_row = len(self.data_outputs.values())
321            if nbr_user_row > self._rows + 1:
322                new_row_nbr =  nbr_user_row - self._rows
323                self.AppendRows(new_row_nbr, True)
324            # add data to the grid   
325            row = 0
326            col = 0
327            cell_col = 0
328            for col_name in  self.col_names:
329                # use the first row of the grid to add user defined labels
330                self.SetCellValue(row, col, str(col_name))
331                col += 1
332                cell_row =  1
333                value_list = self.data_outputs[col_name]
334               
335                for value in value_list:
336                    label = value
337                    if issubclass(value.__class__, BatchCell):
338                        label = value.label
339                    self.SetCellValue(cell_row, cell_col, str(label))
340                    cell_row += 1
341                cell_col += 1
342                if cell_row > self.max_row_touse:
343                    self.max_row_touse = cell_row
344                   
345    def get_grid_view(self):
346        """
347        Return value contained in the grid
348        """
349        grid_view = {}
350        for col in xrange(self.GetNumberCols()):
351            label = self.GetCellValue(row=0, col=col) 
352            label = label.strip()
353            if label != "":
354                grid_view[label] = []
355                for row in range(1, self.max_row_touse+1):
356                    value = self.GetCellValue(row=row, col=col)
357                    if value != "":
358                        grid_view[label].append(value) 
359                    else:
360                        grid_view[label].append(None) 
361        return grid_view
362   
363class Notebook(nb, PanelBase):
364    """
365    ## Internal name for the AUI manager
366    window_name = "Fit panel"
367    ## Title to appear on top of the window
368    """
369    window_caption = "Notebook "
370   
371    def __init__(self, parent, manager=None, data=None, *args, **kwargs):
372        """
373        """
374        nb.__init__(self, parent, -1,
375                    style=wx.aui.AUI_NB_WINDOWLIST_BUTTON| 
376                    wx.aui.AUI_BUTTON_DOWN|
377                    wx.aui.AUI_NB_DEFAULT_STYLE|
378                    wx.CLIP_CHILDREN)
379        PanelBase.__init__(self, parent)
380        self.enable_close_button()
381        self.parent = parent
382        self.manager = manager
383        self.data = data
384        #add empty page
385        self.add_empty_page()
386       
387        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_close_page)
388   
389    def add_empty_page(self):
390        """
391        """
392        grid = GridPage(self, panel=self.parent)
393        self.AddPage(grid, "", True)
394        pos = self.GetPageIndex(grid)
395        title = "Batch " + str(self.GetPageCount())
396        self.SetPageText(pos, title)
397        self.SetSelection(pos)
398        return grid , pos
399       
400    def enable_close_button(self):
401        """
402        display the close button on tab for more than 1 tabs else remove the
403        close button
404        """
405        if self.GetPageCount() <= 1:
406            style = self.GetWindowStyleFlag() 
407            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
408            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB == flag:
409                style = style & ~wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
410                self.SetWindowStyle(style)
411        else:
412            style = self.GetWindowStyleFlag()
413            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
414            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB != flag:
415                style |= wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
416                self.SetWindowStyle(style)
417             
418    def on_edit_axis(self):
419        """
420        Return the select cell of a given selected column
421        """
422        pos = self.GetSelection()
423        grid = self.GetPage(pos)
424        if len(grid.selected_cols) > 1:
425            msg = "Edit axis doesn't understand this selection.\n"
426            msg += "Please select only one column"
427            raise ValueError, msg
428        if len(grid.selected_cols) == 1:
429            col = grid.selected_cols[0]
430            if len(grid.selected_cells) > 0:
431                cell_row, cell_col = grid.selected_cells[0]
432                if cell_col  != col:
433                    msg = "Edit axis doesn't understand this selection.\n"
434                    msg += "Please select element of the same col"
435                    raise ValueError, msg
436        return grid.selected_cells
437       
438   
439    def get_column_labels(self):
440        """
441        return dictionary of columns labels of the current page
442        """
443        pos = self.GetSelection()
444        grid = self.GetPage(pos)
445        labels = {}
446        row = 0
447        for col in range(grid.GetNumberCols()):
448            label = grid.GetCellValue(row, col)
449            if label.strip() != "" :
450                labels[label.strip()] = col
451        return labels
452       
453    def create_axis_label(self, cell_list):
454        """
455        Receive a list of cells and  create a string presenting the selected
456        cells.
457        :param cell_list: list of tuple
458       
459        """
460        pos = self.GetSelection()
461        grid = self.GetPage(pos)
462        label = ""
463        col_name = ""
464        def create_label(col_name,  row_min=None, row_max=None):
465            """
466            """
467            result = ""
468            if row_min is not  None or row_max is not None:
469                if row_min is None:
470                    result = str(row_max) + "]"
471                elif row_max is None:
472                     result = str(col_name) + "[" + str(row_min) + ":"
473                else:
474                    result = str(col_name) +  "[" + str(row_min) + ":"
475                    result += str(col_name) + str(row_max) + "]"
476            return result
477           
478        if len(cell_list) > 0:
479            if len(cell_list) == 1:
480                 row_min, col  = cell_list[0]   
481                 col_name = grid.GetCellValue(0, col)
482                 label = create_label(col_name, row_min+1 , row_min+1)
483                 return  label,  col_name
484            else:
485                temp_list = copy.deepcopy(cell_list)
486                temp_list.sort()
487                length = len(temp_list)
488                row_min, col  = temp_list[0]   
489                row_max, _  = temp_list[length-1]
490                col_name = grid.GetCellValue(0, col)
491                index = 0
492                for row in xrange(row_min, row_max +1):
493                    if index > 0 and index < len(temp_list):
494                        new_row, _ = temp_list[index]
495                        if row != new_row:
496                            temp_list.insert(index, (None, None))
497                            if index -1 >=0:
498                                new_row, _ = temp_list[index-1]
499                                label += create_label(col_name, None, new_row +1)
500                                label += ","
501                            if index + 1 < len(temp_list):
502                                new_row, _ = temp_list[index + 1]
503                                label += create_label(col_name, new_row+1, None)
504                    if index == 0:
505                        label += create_label(col_name,  row_min+1, None)
506                    elif index == len(temp_list)-1:
507                        label += create_label(col_name, None, row_max+1)
508                    index += 1
509                return label, col_name
510   
511    def on_close_page(self, event):
512        """
513        close the page
514        """
515        if self.GetPageCount() == 1:
516            event.Veto()
517        self.enable_close_button()
518       
519    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
520        if data_outputs is None or data_outputs == {}:
521            return
522       
523        for pos in range(self.GetPageCount()):
524            grid = self.GetPage(pos)
525            if grid.data is None:
526                #Found empty page
527                grid.set_data(data_inputs=data_inputs, 
528                              data_outputs=data_outputs,
529                              details=details,
530                              file_name=file_name) 
531                self.SetSelection(pos) 
532                return
533               
534        grid, pos = self.add_empty_page()
535        grid.set_data(data_inputs=data_inputs, 
536                      data_outputs=data_outputs,
537                      file_name=file_name,
538                      details=details)
539   
540    def add_column(self):
541        """
542        Append a new column to the grid
543        """
544        pos = self.GetSelection()
545        grid = self.GetPage(pos)
546        grid.AppendCols(1, True)
547       
548   
549
550
551
552class GridPanel(SPanel):
553    def __init__(self, parent, data_inputs=None,
554                 data_outputs=None, *args, **kwds):
555        SPanel.__init__(self, parent , *args, **kwds)
556       
557        self.vbox = wx.BoxSizer(wx.VERTICAL)
558       
559        self.plotting_sizer = wx.FlexGridSizer(3, 7, 10, 5)
560        self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
561        self.vbox.AddMany([(self.grid_sizer, 1, wx.EXPAND, 0),
562                           (wx.StaticLine(self, -1), 0, wx.EXPAND, 0),
563                           (self.plotting_sizer)])
564        self.parent = parent
565        self._data_inputs = data_inputs
566        self._data_outputs = data_outputs
567        self.x = []
568        self.= []
569        self.x_axis_label = None
570        self.y_axis_label = None
571        self.x_axis_title = None
572        self.y_axis_title = None
573        self.x_axis_unit = None
574        self.y_axis_unit = None
575        self.plot_button = None
576        self.notebook = None
577        self.layout_grid()
578        self.layout_plotting_area()
579        self.SetSizer(self.vbox)
580 
581    def set_xaxis(self, label="", x=None):
582        """
583        """
584        if x is None:
585            x = []
586        self.x = x
587        self.x_axis_label.SetValue("%s[:]" % str(label))
588        self.x_axis_title.SetValue(str(label))
589       
590    def set_yaxis(self, label="", y=None):
591        """
592        """
593        if y is None:
594            y = []
595        self.y = y
596        self.y_axis_label.SetValue("%s[:]" % str(label))
597        self.y_axis_title.SetValue(str(label))
598       
599    def get_plot_axis(self, col, list):
600        """
601       
602        """
603        axis = []
604        pos = self.notebook.GetSelection()
605        grid = self.notebook.GetPage(pos)
606        for row in list:
607            label = grid.GetCellValue(0, col)
608            value = grid.GetCellValue(row - 1, col).strip()
609            if value != "":
610                if label.lower().strip() == "data":
611                    axis.append(float(row - 1))
612                else:
613                    try:
614                        axis.append(float(value))
615                    except:
616                        msg = "Invalid data in row %s column %s" % (str(row),
617                                                                    str(col))
618                        wx.PostEvent(self.parent.parent, 
619                             SatusEvent(status=msg, info="error")) 
620            else:
621                axis.append(None) 
622        return axis
623   
624    def on_save_column(self, parent):
625        """
626        """
627        pos = self.notebook.GetSelection()
628        grid = self.notebook.GetPage(pos)
629        if parent is not None and  self.data is not None:
630            parent.write_batch_tofile(data=grid.data, 
631                                               file_name=path,
632                                               details=self.details)
633       
634    def on_plot(self, event):
635        """
636        Evaluate the contains of textcrtl and plot result
637        """ 
638        pos = self.notebook.GetSelection()
639        grid = self.notebook.GetPage(pos)
640        column_names = {}
641        if grid is not None:
642            column_names = self.notebook.get_column_labels()
643        #evalue x
644        sentence = self.x_axis_label.GetValue()
645        if sentence.strip() == "":
646            msg = "select value for x axis"
647            raise ValueError, msg
648        dict = parse_string(sentence, column_names.keys())
649        for tok, (col_name, list) in dict.iteritems():
650            col = column_names[col_name]
651            xaxis = self.get_plot_axis(col, list)
652            sentence = sentence.replace(tok, 
653                                        "numpy.array(%s)" % str(xaxis))
654        for key, value in FUNC_DICT.iteritems():
655            sentence = sentence.replace(key.lower(), value)
656        x = eval(sentence)
657        #evaluate y
658        sentence = self.y_axis_label.GetValue()
659        if sentence.strip() == "":
660            msg = "select value for y axis"
661            raise ValueError, msg
662        dict = parse_string(sentence, column_names.keys())
663        for tok, (col_name, list) in dict.iteritems():
664            col = column_names[col_name]
665            yaxis = self.get_plot_axis(col, list)
666            sentence = sentence.replace(tok, 
667                                        "numpy.array(%s)" % str(yaxis))
668        for key, value in FUNC_DICT.iteritems():
669            sentence = sentence.replace(key, value)
670        y = eval(sentence)
671        #plotting
672        new_plot = Data1D(x=x, y=y)
673        new_plot.id =  wx.NewId()
674        new_plot.group_id = wx.NewId()
675        title = "%s vs %s" % (self.y_axis_title.GetValue(), 
676                              self.x_axis_title.GetValue())
677        new_plot.xaxis(self.x_axis_title.GetValue(), self.x_axis_unit.GetValue())
678        new_plot.yaxis(self.y_axis_title.GetValue(), self.y_axis_unit.GetValue())
679        try:
680            title = self.notebook.GetPageText(pos)
681            new_plot.name = title
682            wx.PostEvent(self.parent.parent, 
683                             NewPlotEvent(plot=new_plot, 
684                        group_id=str(new_plot.group_id), title =title))   
685        except:
686             wx.PostEvent(self.parent.parent, 
687                             SatusEvent(status=msg, info="error")) 
688       
689    def layout_grid(self):
690        """
691        Draw the area related to the grid
692        """
693        self.notebook = Notebook(parent=self)
694        self.notebook.set_data(self._data_inputs, self._data_outputs)
695        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
696       
697    def layout_plotting_area(self):
698        """
699        Draw area containing options to plot
700        """
701        self.x_axis_title = wx.TextCtrl(self, -1)
702        self.y_axis_title = wx.TextCtrl(self, -1)
703        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
704        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
705        self.x_axis_add = wx.Button(self, -1, "Add")
706        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
707                            id=self.x_axis_add.GetId())
708        self.y_axis_add = wx.Button(self, -1, "Add")
709        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
710                            id=self.y_axis_add.GetId())
711        self.x_axis_unit = wx.TextCtrl(self, -1)
712        self.y_axis_unit = wx.TextCtrl(self, -1)
713        self.plot_button = wx.Button(self, -1, "Plot")
714        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
715        self.plotting_sizer.AddMany([
716                    (wx.StaticText(self, -1, "x-axis label"), 1,
717                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
718                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
719                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
720                    (wx.StaticText(self, -1, "x-axis title"), 1, 
721                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
722                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
723                    (wx.StaticText(self, -1 , "unit"), 1, 
724                     wx.TOP|wx.BOTTOM, 10),
725                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
726                    (wx.StaticText(self, -1, "y-axis label"), 1, 
727                     wx.BOTTOM|wx.LEFT, 10),
728                    (self.y_axis_label, wx.BOTTOM, 10),
729                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
730                    (wx.StaticText(self, -1, "y-axis title"), 1, 
731                     wx.BOTTOM|wx.LEFT, 10),
732                    (self.y_axis_title,  wx.BOTTOM, 10),
733                    (wx.StaticText(self, -1 , "unit"), 1, wx.BOTTOM, 10),
734                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
735                      (-1, -1),
736                      (-1, -1),
737                      (-1, -1),
738                      (-1, -1),
739                      (-1, -1),
740                      (-1, -1),
741                      (self.plot_button, 1, wx.LEFT|wx.BOTTOM, 10)])
742   
743    def on_edit_axis(self, event):
744        """
745        Get the selected column on  the visible grid and set values for axis
746        """
747        cell_list = self.notebook.on_edit_axis()
748        label, title = self.create_axis_label(cell_list)
749        tcrtl = event.GetEventObject()
750        if tcrtl == self.x_axis_add:
751            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
752                                   label, title)
753        elif tcrtl == self.y_axis_add:
754            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
755                                   label, title)
756           
757    def create_axis_label(self, cell_list):
758        """
759        Receive a list of cells and  create a string presenting the selected
760        cells.
761        :param cell_list: list of tuple
762       
763        """
764        if self.notebook is not None:
765            return self.notebook.create_axis_label(cell_list)
766   
767    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
768        """
769        get controls to modify
770        """
771        tcrtl_label.SetValue(str(label))
772        tcrtl_title.SetValue(str(title))
773       
774    def add_column(self):
775        """
776        """
777        if self.notebook is not None:
778            self.notebook.add_column()
779       
780    def on_remove_column(self):
781        """
782        """
783        if self.notebook is not None:
784            self.notebook.on_remove_column()
785       
786       
787class GridFrame(wx.Frame):
788    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
789                 title="Batch Results", size=(700, 400)):
790        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
791        self.parent = parent
792        self.panel = GridPanel(self, data_inputs, data_outputs)
793        menubar = wx.MenuBar()
794        self.SetMenuBar(menubar)
795       
796        self.curr_col = None
797        self.curr_grid = None
798        self.curr_col_name = ""
799        file = wx.Menu()
800        menubar.Append(file, "&File")
801       
802        hint = "Open file containing batch results"
803        open_menu = file.Append(wx.NewId(), 'Open ', hint)
804        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
805       
806        hint = "Open the the current grid into excel"
807        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
808        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
809        file.AppendSeparator()
810        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
811        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
812       
813        self.edit = wx.Menu()
814        hint = "Insert column before the selected column"
815        self.insert_before_menu = wx.Menu()
816        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
817                                                      'Insert Before', hint)
818 
819        hint = "Remove the selected column"
820        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
821        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
822       
823        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
824        menubar.Append(self.edit, "&Edit")
825        self.Bind(wx.EVT_CLOSE, self.on_close)
826       
827    def GetLabelText(self, id):
828        """
829        """
830        for item in self.insert_before_menu.GetMenuItems():
831            m_id = item.GetId() 
832            if m_id == id:
833                return item.GetLabel() 
834   
835    def on_remove_column(self, event):
836        """
837        """
838        pos = self.panel.notebook.GetSelection()
839        grid = self.panel.notebook.GetPage(pos)
840        grid.on_remove_column(event=None)
841       
842    def on_menu_open(self, event):
843        """
844       
845        """
846        if self.edit == event.GetMenu():
847            #get the selected column
848            pos = self.panel.notebook.GetSelection()
849            grid = self.panel.notebook.GetPage(pos)
850            col_list = grid.GetSelectedCols()
851            if len(col_list) > 0:
852                self.remove_menu.Enable(True)
853            else:
854                self.remove_menu.Enable(False)
855            if len(col_list)== 0 or len(col_list) > 1:
856                self.insert_sub_menu.Enable(False)
857               
858                label = "Insert Column Before"
859                self.insert_sub_menu.SetText(label)
860            else:
861                self.insert_sub_menu.Enable(True)
862               
863                col = col_list[0]
864                #GetColLabelValue(self, col)
865                col_name = grid.GetCellValue(row=0, col=col)
866                label = "Insert Column Before " + str(col_name)
867                self.insert_sub_menu.SetText(label)
868                for item in self.insert_before_menu.GetMenuItems():
869                    self.insert_before_menu.DeleteItem(item)
870                grid.insert_col_menu(menu=self.insert_before_menu, 
871                                     label=col_name, window=self)
872        event.Skip()
873       
874 
875       
876    def on_save_page(self, event):
877        """
878        """
879        if self.parent is not None:
880            pos = self.panel.notebook.GetSelection()
881            grid = self.panel.notebook.GetPage(pos)
882            reader, ext = os.path.splitext(grid.file_name)
883            path = None
884            if self.parent is not None: 
885                location = os.path.dirname(grid.file_name)
886                dlg = wx.FileDialog(self, "Save Project file",
887                            location, grid.file_name, ext, wx.SAVE)
888                path = None
889                if dlg.ShowModal() == wx.ID_OK:
890                    path = dlg.GetPath()
891                dlg.Destroy()
892                if path != None:
893                    if self.parent is not None:
894                        data = grid.get_grid_view()
895                        self.parent.write_batch_tofile(data=data, 
896                                               file_name=path,
897                                               details=grid.details)
898   
899    def on_open(self, event):
900        """
901        Open file containg batch result
902        """
903        if self.parent is not None:
904            self.parent.on_read_batch_tofile(event)
905           
906    def open_with_excel(self, event):
907        """
908        open excel and display batch result in Excel
909        """
910        if self.parent is not None:
911            pos = self.panel.notebook.GetSelection()
912            grid = self.panel.notebook.GetPage(pos)
913            data = grid.get_grid_view()
914            self.parent.open_with_externalapp(data=data,
915                                               file_name=grid.file_name, 
916                                               details=grid.details)
917           
918    def on_close(self, event):
919        """
920        """
921        self.Hide()
922       
923   
924    def on_append_column(self, event):
925        """
926        Append a new column to the grid
927        """
928        self.panel.add_column()
929       
930    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
931        """
932        """
933       
934        self.panel.notebook.set_data(data_inputs=data_inputs, 
935                            file_name=file_name,
936                            details=details,
937                            data_outputs=data_outputs)
938     
939     
940class BatchOutputFrame(wx.Frame):
941    """
942    Allow to select where the result of batch will be displayed or stored
943    """
944    def __init__(self, parent, data_inputs, data_outputs, file_name="",
945                 details="", *args, **kwds):
946        """
947        :param parent: Window instantiating this dialog
948        :param result: result to display in a grid or export to an external
949                application.
950        """
951        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
952        wx.Frame.__init__(self, parent, *args, **kwds)
953        self.parent = parent
954        self.panel = wx.Panel(self)
955        self.file_name = file_name
956        self.details = details
957        self.data_inputs = data_inputs
958        self.data_outputs = data_outputs
959        self.data = {}
960        for item in (self.data_outputs, self.data_inputs):
961            self.data.update(item)
962        self.flag = 1
963        self.SetSize((300, 200))
964        self.local_app_selected = None
965        self.external_app_selected = None
966        self.save_to_file = None
967        self._do_layout()
968   
969    def _do_layout(self):
970        """
971        Draw the content of the current dialog window
972        """
973        vbox = wx.BoxSizer(wx.VERTICAL)
974        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
975        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
976        selection_sizer = wx.GridBagSizer(5, 5)
977        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
978        text = "Open with %s" % self.parent.application_name
979        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
980                                                style=wx.RB_GROUP)
981        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
982                    id=self.local_app_selected.GetId())
983        text = "Open with Excel"
984        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
985        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
986                    id=self.external_app_selected.GetId())
987        text = "Save to File"
988        self.save_to_file = wx.CheckBox(self.panel, -1, text)
989        self.Bind(wx.EVT_CHECKBOX, self.onselect,
990                    id=self.save_to_file.GetId())
991        self.local_app_selected.SetValue(True)
992        self.external_app_selected.SetValue(False)
993        self.save_to_file.SetValue(False)
994        button_close = wx.Button(self.panel, -1, "Close")
995        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
996                           handler=self.on_close)
997        button_apply = wx.Button(self.panel, -1, "Apply")
998        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
999                        handler=self.on_apply)
1000        button_apply.SetFocus()
1001        hint = ""
1002        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
1003        hint_sizer.Add(selection_sizer)
1004        #draw area containing radio buttons
1005        ix = 0
1006        iy = 0
1007        selection_sizer.Add(self.local_app_selected, (iy, ix),
1008                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1009        iy += 1
1010        selection_sizer.Add(self.external_app_selected, (iy, ix),
1011                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1012        iy += 1
1013        selection_sizer.Add(self.save_to_file, (iy, ix),
1014                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1015        #contruction the sizer contaning button
1016        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1017
1018        button_sizer.Add(button_close, 0,
1019                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1020        button_sizer.Add(button_apply, 0,
1021                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1022        vbox.Add(hint_sizer,  0, wx.EXPAND|wx.ALL, 10)
1023        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
1024        vbox.Add(button_sizer, 0 , wx.TOP|wx.BOTTOM, 10)
1025        self.SetSizer(vbox)
1026       
1027    def on_apply(self, event):
1028        """
1029        Get the user selection and display output to the selected application
1030        """
1031        if self.flag == 1:
1032            self.parent.open_with_localapp(data_inputs=self.data_inputs,
1033                                            data_outputs=self.data_outputs)
1034        elif self.flag == 2:
1035            self.parent.open_with_externalapp(data=self.data, 
1036                                           file_name=self.file_name,
1037                                           details=self.details)
1038    def on_close(self, event):
1039        """
1040        close the Window
1041        """
1042        self.Close()
1043       
1044    def onselect(self, event=None):
1045        """
1046        Receive event and display data into third party application
1047        or save data to file.
1048       
1049        """
1050        if self.save_to_file.GetValue():
1051            reader, ext = os.path.splitext(self.file_name)
1052            path = None
1053            location = os.getcwd()
1054            if self.parent is not None: 
1055                location = os.path.dirname(self.file_name)
1056                dlg = wx.FileDialog(self, "Save Project file",
1057                            location, self.file_name, ext, wx.SAVE)
1058                path = None
1059                if dlg.ShowModal() == wx.ID_OK:
1060                    path = dlg.GetPath()
1061                dlg.Destroy()
1062                if path != None:
1063                    if self.parent is not None and  self.data is not None:
1064                        self.parent.write_batch_tofile(data=self.data, 
1065                                               file_name=path,
1066                                               details=self.details)
1067        if self.local_app_selected.GetValue():
1068            self.flag = 1
1069        else:
1070            self.flag = 2
1071        return self.flag
1072   
1073 
1074       
1075if __name__ == "__main__":
1076    app = wx.App()
1077   
1078    try:
1079        data = {}
1080        j = 0
1081        for i in range(4):
1082            j += 1
1083            data["index"+str(i)] = [i/j, i*j, i, i+j]
1084       
1085        data_input =  copy.deepcopy(data)   
1086        data_input["index5"] = [10,20,40, 50]
1087        frame = GridFrame(data_outputs=data, data_inputs=data_input)
1088        frame.Show(True)
1089    except:
1090        print sys.exc_value
1091       
1092    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.