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

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 86a9e6c was 86a9e6c, checked in by Jae Cho <jhjcho@…>, 12 years ago

some minor fixes in Grid panel

  • Property mode set to 100644
File size: 60.7 KB
Line 
1"""
2Implement grid used to store data
3"""
4import wx
5import numpy
6import math
7import time
8import re
9import os
10import sys
11import copy
12from wx.lib.scrolledpanel import ScrolledPanel
13import  wx.grid as  Grid
14import wx.aui
15from wx.aui import AuiNotebook as nb
16import wx.lib.sheet as sheet
17from sans.guiframe.panel_base import PanelBase
18from sans.guiframe.utils import format_number
19from sans.guiframe.events import NewPlotEvent
20from sans.guiframe.events import StatusEvent 
21from danse.common.plottools import plottables
22from sans.guiframe.dataFitting import Data1D
23
24FUNC_DICT = {"sqrt": "math.sqrt",
25             "pow": "math.sqrt"}
26
27class BatchCell:
28    """
29    Object describing a cell in  the grid.
30   
31    """
32    def __init__(self):
33        self.label = ""
34        self.value = None
35        self.col = -1
36        self.row = -1
37        self.object = []
38       
39
40def parse_string(sentence, list):
41    """
42    Return a dictionary of column label and index or row selected
43    :param sentence: String to parse
44    :param list: list of columns label
45    """
46    toks = []
47    p2 = re.compile(r'\d+')
48    p = re.compile(r'[\+\-\*\%\/]')
49    labels = p.split(sentence)
50    col_dict = {}
51    for elt in labels:
52        rang = None
53        temp_arr = []
54        for label in  list:
55            label_pos =  elt.find(label)
56            separator_pos  = label_pos + len(label)
57            if label_pos != -1 and len(elt) >= separator_pos  and\
58                elt[separator_pos]== "[":
59                # the label contain , meaning the range selected is not
60                # continuous
61                if elt.count(',') > 0:
62                    new_temp = []
63                    temp = elt.split(label)
64                    for item in temp:
65                        range_pos = item.find(":")
66                        if range_pos != -1:
67                            rang = p2.findall(item)
68                            for i in xrange(int(rang[0]), int(rang[1])+1 ):
69                                new_temp.append(i)
70                    temp_arr += new_temp
71                else:
72                    # continuous range
73                    temp = elt.split(label)
74                    for item in temp:
75                        if item.strip() != "":
76                            range_pos = item.find(":")
77                            if range_pos != -1:
78                                rang = p2.findall(item)
79                                for i in xrange(int(rang[0]), int(rang[1])+1 ):
80                                    temp_arr.append(i)
81                col_dict[elt] = (label, temp_arr)
82    return col_dict
83
84         
85         
86class SPanel(ScrolledPanel):
87    def __init__(self, parent, *args, **kwds):
88        ScrolledPanel.__init__(self, parent , *args, **kwds)
89        self.SetupScrolling() 
90       
91class GridPage(sheet.CSheet):
92    """
93    """
94    def __init__(self, parent, panel=None):
95        """
96        """
97        sheet.CSheet.__init__(self, parent)
98       
99        self.AdjustScrollbars()
100        #self.SetLabelBackgroundColour('#DBD4D4')
101        self.uid = wx.NewId()
102        self.parent = parent
103        self.panel = panel
104        self.col_names = []
105        self.data_inputs = {}
106        self.data_outputs = {}
107        self.data = None
108        self.details = ""
109        self.file_name = None
110        self._cols = 50
111        self._rows = 501
112        self.last_selected_row = -1
113        self.last_selected_col = -1
114        self.col_width = 30
115        self.row_height = 20
116        self.max_row_touse = 0
117        self.axis_value = []
118        self.axis_label = ""
119        self.selected_cells = []
120        self.selected_cols = []
121        self.selected_rows = []
122        self.plottable_cells = []
123        self.plottable_flag = False
124        self.SetColMinimalAcceptableWidth(self.col_width)
125        self.SetRowMinimalAcceptableHeight(self.row_height)
126        self.SetNumberRows(self._rows)
127        self.SetNumberCols(self._cols)
128        color = self.parent.GetBackgroundColour()
129        for col in range(self._cols):
130            self.SetCellBackgroundColour(0, col, color)
131        self.AutoSize()
132        self.list_plot_panels = {}
133        self.default_col_width = 75
134        self.EnableEditing(False)
135        if self.GetNumberCols() > 0:
136            self.default_col_width =  self.GetColSize(0)
137        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
138        self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
139        self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.on_selected_cell)
140        self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.on_edit_cell)
141       
142       
143    def on_edit_cell(self, event):
144        """
145        """
146        row, col = event.GetRow(), event.GetCol()
147        if row > self.max_row_touse:
148            self.max_row_touse = row
149        event.Skip()
150       
151    def on_selected_cell(self, event):
152        """
153        Handler catching cell selection
154        """
155        flag = event.CmdDown() or event.ControlDown()
156        flag_shift =  event.ShiftDown()
157        row, col = event.GetRow(), event.GetCol()
158        cell = (row, col)
159        event.Skip()
160        if not flag and not flag_shift:
161            self.selected_cols = []
162            self.selected_rows = []
163            self.selected_cells = []
164            self.axis_label = ""
165            self.axis_value = []
166            self.plottable_list = []
167            self.plottable_cells = []
168            self.plottable_flag = False
169        self.last_selected_col = col
170        self.last_selected_row = row
171        if col >= 0:
172            if flag:
173                label_row = row
174            else:
175                label_row = 0
176            self.axis_label = self.GetCellValue(label_row, col)
177            self.selected_cols.append(col)
178        if flag_shift:
179            if not self.selected_rows:
180                min_r = 1
181            else:
182                min_r = min(self.selected_rows)
183            for row_s in range(min_r, row+1):
184                cel = (row_s, col)
185                if cel not in self.selected_cells:
186                    if row > 0:
187                        self.selected_cells.append(cel)
188                        self.selected_rows.append(row) 
189            for row_s in self.selected_rows: 
190                cel = (row_s, col)
191                if row_s > row:
192                    try:
193                        self.selected_cells.remove(cel)
194                    except:
195                        pass
196                    try:
197                        self.selected_rows.remove(row_s)
198                    except:
199                        pass
200        elif flag:
201            if cell not in self.selected_cells:
202                if row > 0 :
203                    self.selected_cells.append(cell)
204                    self.selected_rows.append(row)
205            else:
206                try:
207                    self.selected_cells.remove(cell)
208                except:
209                    pass
210                try:
211                    self.selected_rows.remove(row)
212                except:
213                    pass
214        else:
215            self.selected_cells.append(cell)
216            self.selected_rows.append(row)
217        self.axis_value = []
218        for cell_row, cell_col in self.selected_cells:
219            if cell_row > 0 and cell_row < self.max_row_touse:
220                self.axis_value.append(self.GetCellValue(cell_row, cell_col))
221
222    def on_left_click(self, event):
223        """
224        Catch the left click on label mouse event
225        """
226        event.Skip()
227        flag = event.CmdDown() or event.ControlDown()
228       
229        col = event.GetCol()
230        row = event.GetRow()
231
232        if not (flag):
233            self.selected_cols = []
234            self.selected_rows = []
235            self.selected_cells = []
236            self.axis_label = ""
237            self.axis_value = []
238            self.plottable_list = []
239            self.plottable_cells = []
240            self.plottable_flag = False
241       
242        self.last_selected_col = col
243        self.last_selected_row = row
244        if row != -1 and row not in self.selected_rows:
245             self.selected_rows.append(row)
246             
247        if col != -1:
248            for row in range(1, self.GetNumberRows()+ 1):
249                cell = (row, col)
250                if row > 0 and row < self.max_row_touse:
251                    if cell not in self.selected_cells:
252                        self.selected_cells.append(cell)
253                    else:
254                        if flag:
255                             self.selected_cells.remove(cell)
256            self.selected_cols.append(col)
257            self.axis_value = []
258            for cell_row, cell_col in self.selected_cells:
259                val = self.GetCellValue(cell_row, cell_col)
260                if not val:
261                    self.axis_value.append(self.GetCellValue(cell_row, cell_col))
262            self.axis_label = self.GetCellValue(0, col)
263            if not self.axis_label:
264                self.axis_label = " "
265       
266    def on_right_click(self, event):
267        """
268        Catch the right click mouse
269        """
270       
271        col = event.GetCol()
272        row = event.GetRow()
273        # Ignore the index column
274        if col < 0 or row != -1:
275            return
276        self.selected_cols = []
277        self.selected_cols.append(col)
278        # Slicer plot popup menu
279        slicerpop = wx.Menu()
280        col_label_menu  = wx.Menu()
281        c_name = self.GetCellValue(0, col) 
282        label = "Insert column before %s " % str(c_name)
283        slicerpop.AppendSubMenu(col_label_menu , 
284                                 '&%s' % str(label), str(label))
285        col_name = [self.GetCellValue(0, c) 
286                        for c in range(self.GetNumberCols())]
287        row = 0
288        label = self.GetCellValue(row, col)
289        self.insert_col_menu(col_label_menu, label, self)
290       
291       
292        col_after_menu  = wx.Menu()
293        label = "Insert column after %s " % str(c_name)
294        slicerpop.AppendSubMenu(col_after_menu , 
295                                 '&%s' % str(label), str(label))
296        col_name = [self.GetCellValue(0, c) 
297                        for c in range(self.GetNumberCols())]
298        self.insert_after_col_menu(col_after_menu, label, self)
299       
300       
301        id = wx.NewId()   
302        hint = 'Remove selected column %s'
303        slicerpop.Append(id, '&Remove Column', hint)
304        wx.EVT_MENU(self, id, self.on_remove_column)
305       
306        pos = wx.GetMousePosition()
307        pos = self.ScreenToClient(pos)
308        self.PopupMenu(slicerpop, pos)
309        event.Skip()
310       
311    def insert_col_menu(self, menu, label, window):
312        """
313        """
314        if self.data is None:
315            return
316        id = wx.NewId()
317        title = "Empty"
318        hint = 'Insert empty column before %s' % str(label)
319        menu.Append(id, title, hint)
320        wx.EVT_MENU(window, id, self.on_insert_column)
321        row = 0
322        col_name = [self.GetCellValue(row, col) 
323                        for col in range(self.GetNumberCols())]
324        for c_name in self.data.keys():
325            if c_name not in col_name:
326                id = wx.NewId()
327                hint = "Insert %s column before the " % str(c_name)
328                hint += " %s column" % str(label)
329                menu.Append(id, '&%s' % str(c_name), hint)
330                wx.EVT_MENU(window, id, self.on_insert_column)
331           
332    def insert_after_col_menu(self, menu, label, window):
333        """
334        """
335        if self.data is None:
336            return
337        id = wx.NewId()
338        title = "Empty"
339        hint = 'Insert empty column after %s' % str(label)
340        menu.Append(id, title, hint)
341        wx.EVT_MENU(window, id, self.on_insert_after_column)
342        row = 0
343        col_name = [self.GetCellValue(row, col) 
344                        for col in range(self.GetNumberCols())]
345        for c_name in self.data.keys():
346            if c_name not in col_name:
347                id = wx.NewId()
348                hint = "Insert %s column after the " % str(c_name)
349                hint += " %s column" % str(label)
350                menu.Append(id, '&%s' % str(c_name), hint)
351                wx.EVT_MENU(window, id, self.on_insert_after_column)
352                               
353    def on_remove_column(self, event=None):
354        """
355        """
356        if self.selected_cols is not None or len(self.selected_cols) > 0:
357            col = self.selected_cols[0]
358            self.remove_column(col=col, numCols=1)
359           
360    def remove_column(self, col, numCols=1):
361        """
362        Remove column to the current grid
363        """
364        # add data to the grid   
365        row = 0
366        col_name = self.GetCellValue(row, col)
367        self.data[col_name] = []
368        for row in range(1, self.GetNumberRows() + 1):
369            if row < self.max_row_touse:
370                value = self.GetCellValue(row, col)
371                self.data[col_name].append(value)
372                for k , value_list in self.data.iteritems():
373                    if k != col_name:
374                        length = len(value_list)
375                        if length < self.max_row_touse:
376                            diff = self.max_row_touse - length
377                            for i in range(diff):
378                                self.data[k].append("")
379        self.DeleteCols(pos=col, numCols=numCols, updateLabels=True)
380           
381    def on_insert_column(self, event):
382        """
383        """
384        if self.selected_cols is not None or len(self.selected_cols) > 0:
385            col = self.selected_cols[0]
386            # add data to the grid   
387            row = 0
388            id = event.GetId()
389            col_name = event.GetEventObject().GetLabelText(id)
390            self.insert_column(col=col, col_name=col_name)
391            if  not issubclass(event.GetEventObject().__class__ , wx.Menu):
392                col += 1
393                self.selected_cols[0] += 1
394               
395    def on_insert_after_column(self, event):
396        """
397        Insert the given column after the highlighted column
398        """
399        if self.selected_cols is not None or len(self.selected_cols) > 0:
400            col = self.selected_cols[0] + 1
401            # add data to the grid   
402            row = 0
403            id = event.GetId()
404            col_name = event.GetEventObject().GetLabelText(id)
405            self.insert_column(col=col, col_name=col_name)
406            if  not issubclass(event.GetEventObject().__class__ , wx.Menu):
407                self.selected_cols[0] += 1
408           
409    def insert_column(self, col, col_name):
410        """
411        """ 
412         
413        row = 0
414        self.InsertCols(pos=col, numCols=1, updateLabels=True)
415        if col_name.strip() != "Empty":
416            self.SetCellValue(row, col, str(col_name.strip()))
417        if col_name in self.data.keys():
418            value_list = self.data[col_name]
419            cell_row =  1
420            for value in value_list:
421                label = value#format_number(value, high=True)
422                self.SetCellValue(cell_row, col, str(label))
423                cell_row += 1
424        self.AutoSizeColumn(col, True)
425        width = self.GetColSize(col)
426        if width < self.default_col_width:
427           self.SetColSize(col, self.default_col_width)
428        color = self.parent.GetBackgroundColour()
429        self.SetCellBackgroundColour(0, col, color)
430        self.ForceRefresh()
431       
432    def on_set_x_axis(self, event):
433        """
434        """
435        self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
436   
437    def on_set_y_axis(self, event):
438        """
439        """
440        self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)     
441           
442    def set_data(self, data_inputs, data_outputs, details, file_name):
443        """
444        Add data to the grid
445        :param data_inputs: data to use from the context menu of the grid
446        :param data_ouputs: default columns deplayed
447        """
448        self.file_name = file_name
449        self.details = details
450       
451        if data_outputs is None:
452            data_outputs = {}
453        self.data_outputs = data_outputs
454        if data_inputs is None:
455            data_inputs = {}
456        self.data_inputs = data_inputs
457        self.data = {}
458        for item in (self.data_outputs, self.data_inputs):
459            self.data.update(item)
460           
461        if len(self.data) + len(self.data_inputs) +len(self.data_outputs) == 0:
462            self.EnableEditing(False)
463        else:
464            self.EnableEditing(True)
465        if  len(self.data_outputs) > 0:
466            self._cols = self.GetNumberCols()
467            self._rows = self.GetNumberRows()
468            self.col_names = self.data_outputs.keys()
469            self.col_names.sort() 
470            nbr_user_cols = len(self.col_names)
471            #Add more columns to the grid if necessary
472            if nbr_user_cols > self._cols:
473                new_col_nbr = nbr_user_cols -  self._cols + 1
474                self.AppendCols(new_col_nbr, True)
475            #Add more rows to the grid if necessary 
476            nbr_user_row = len(self.data_outputs.values()[0])
477            if nbr_user_row > self._rows + 1:
478                new_row_nbr =  nbr_user_row - self._rows + 1
479                self.AppendRows(new_row_nbr, True)
480            # add data to the grid   
481            wx.CallAfter(self.set_grid_values)
482        self.ForceRefresh()
483   
484    def set_grid_values(self):
485        """
486        Set the values in grids
487        """
488        # add data to the grid   
489        row = 0
490        col = 0
491        cell_col = 0
492        for col_name in  self.col_names:
493            # use the first row of the grid to add user defined labels
494            self.SetCellValue(row, col, str(col_name))
495            col += 1
496            cell_row =  1
497            value_list = self.data_outputs[col_name]
498           
499            for value in value_list:
500                label = value
501                if issubclass(value.__class__, BatchCell):
502                    label = value.label
503                try:
504                    float(label)
505                    label = str(label)#format_number(label, high=True)
506                except:
507                    label = str(label)
508                self.SetCellValue(cell_row, cell_col, label)
509                self.AutoSizeColumn(cell_col, True)
510                width = self.GetColSize(cell_col)
511                if width < self.default_col_width:
512                   self.SetColSize(cell_col, self.default_col_width)
513               
514                cell_row += 1
515            cell_col += 1
516            if cell_row > self.max_row_touse:
517                self.max_row_touse = cell_row
518                         
519    def get_grid_view(self):
520        """
521        Return value contained in the grid
522        """
523        grid_view = {}
524        for col in xrange(self.GetNumberCols()):
525            label = self.GetCellValue(row=0, col=col) 
526            label = label.strip()
527            if label != "":
528                grid_view[label] = []
529                for row in range(1, self.max_row_touse):
530                    value = self.GetCellValue(row=row, col=col)
531                    if value != "":
532                        grid_view[label].append(value) 
533                    else:
534                        grid_view[label].append(None) 
535        return grid_view
536   
537    def get_nofrows(self):
538        """
539        Return number of total rows
540        """
541        return self._rows
542   
543class Notebook(nb, PanelBase):
544    """
545    ## Internal name for the AUI manager
546    window_name = "Fit panel"
547    ## Title to appear on top of the window
548    """
549    window_caption = "Notebook "
550   
551    def __init__(self, parent, manager=None, data=None, *args, **kwargs):
552        """
553        """
554        nb.__init__(self, parent, -1,
555                    style=wx.aui.AUI_NB_WINDOWLIST_BUTTON| 
556                    wx.aui.AUI_BUTTON_DOWN|
557                    wx.aui.AUI_NB_DEFAULT_STYLE|
558                    wx.CLIP_CHILDREN)
559        PanelBase.__init__(self, parent)
560        self.gpage_num = 1
561        self.enable_close_button()
562        self.parent = parent
563        self.manager = manager
564        self.data = data
565        #add empty page
566        self.add_empty_page()
567        self.pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
568        self.Bind(self.pageClosedEvent, self.on_close_page)   
569   
570    def add_empty_page(self):
571        """
572        """
573        grid = GridPage(self, panel=self.parent)
574        self.AddPage(grid, "", True)
575        pos = self.GetPageIndex(grid)
576        title = "Grid" + str(self.gpage_num)
577        self.SetPageText(pos, title)
578        self.SetSelection(pos)
579        self.enable_close_button()
580        self.gpage_num += 1
581        return grid , pos
582       
583    def enable_close_button(self):
584        """
585        display the close button on tab for more than 1 tabs else remove the
586        close button
587        """
588        if self.GetPageCount() <= 1:
589            style = self.GetWindowStyleFlag() 
590            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
591            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB == flag:
592                style = style & ~wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
593                self.SetWindowStyle(style)
594        else:
595            style = self.GetWindowStyleFlag()
596            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
597            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB != flag:
598                style |= wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
599                self.SetWindowStyle(style)
600             
601    def on_edit_axis(self):
602        """
603        Return the select cell of a given selected column. Check that all cells
604        are from the same column
605        """
606        pos = self.GetSelection()
607        grid = self.GetPage(pos)
608        #grid.selected_cols = [grid.GetSelectedRows()]#
609        if len(grid.selected_cols) >= 1:
610            col = grid.selected_cols[0]
611            for c in grid.selected_cols:
612                if c != col:
613                    msg = "Edit axis doesn't understand this selection.\n"
614                    msg += "Please select only one column"
615                    raise ValueError, msg
616            for (cell_row, cell_col) in grid.selected_cells:
617                if cell_col != col:
618                    msg = "Cannot use cells from different columns for "
619                    msg += "this operation.\n"
620                    msg += "Please select elements of the same col.\n"
621                    raise ValueError, msg
622               
623            # Finally check the highlighted cell if any cells missing
624            self.get_highlighted_row()
625        else:
626            msg = "No item selected.\n"
627            msg += "Please select only one column or one cell"
628            raise ValueError, msg
629        return grid.selected_cells
630       
631    def get_highlighted_row(self):
632        """
633        Add highlight rows
634        """
635        pos = self.GetSelection()
636        grid = self.GetPage(pos)
637        col = grid.selected_cols[0]
638        # Finally check the highlighted cell if any cells missing
639        for row in range(grid.get_nofrows()):
640            if grid.IsInSelection(row, col):
641                cel = (row, col)
642                if row < 1:
643                    continue
644                if not grid.GetCellValue(row, col):
645                    continue
646                if cel not in grid.selected_cells:
647                    grid.selected_cells.append(cel)
648                       
649    def get_column_labels(self):
650        """
651        return dictionary of columns labels of the current page
652        """
653        pos = self.GetSelection()
654        grid = self.GetPage(pos)
655        labels = {}
656        row = 0
657        for col in range(grid.GetNumberCols()):
658            label = grid.GetColLabelValue(int(col))
659            #label = grid.GetCellValue(row, col)
660            if label.strip() != "" :
661                labels[label.strip()] = col
662        return labels
663       
664    def create_axis_label(self, cell_list):
665        """
666        Receive a list of cells and  create a string presenting the selected
667        cells.
668        :param cell_list: list of tuple
669       
670        """
671        pos = self.GetSelection()
672        grid = self.GetPage(pos)
673        label = ""
674        col_name = ""
675        def create_label(col_name,  row_min=None, row_max=None):
676            """
677            """
678            result = " "
679            if row_min is not  None or row_max is not None:
680                if row_min is None:
681                    result = str(row_max) + "]"
682                elif row_max is None:
683                     result = str(col_name) + "[" + str(row_min) + ":"
684                else:
685                    result = str(col_name) +  "[" + str(row_min) + ":"
686                    result += str(row_max) + "]"
687            return str(result)
688           
689        if len(cell_list) > 0:
690            if len(cell_list) == 1:
691                row_min, col  = cell_list[0]   
692                col_name =  grid.GetColLabelValue(int(col))
693                 
694                col_title = grid.GetCellValue(0, col)
695                label = create_label(col_name, row_min+1 , row_min+1)
696                return  label,  col_title
697            else:
698                temp_list = copy.deepcopy(cell_list)
699                temp_list.sort()
700                length = len(temp_list)
701                row_min, col  = temp_list[0]   
702                row_max, _  = temp_list[length-1]
703                col_name = grid.GetColLabelValue(int(col))
704                col_title = grid.GetCellValue(0, col)
705
706                index = 0
707                for row in xrange(row_min, row_max + 1):
708                    if index > 0 and index < len(temp_list):
709                        new_row, _ = temp_list[index]
710                        if row != new_row:
711                            temp_list.insert(index, (None, None))
712                            if index -1 >= 0:
713                                new_row, _ = temp_list[index-1]
714                                if not new_row == None and new_row != ' ' :
715                                    label += create_label(col_name, None, 
716                                                          int(new_row) +1)
717                                else:
718                                    label += "]"
719                                label += ","
720                            if index + 1 < len(temp_list):
721                                new_row, _ = temp_list[index + 1]
722                                if not new_row==None:
723                                    label += create_label(col_name, 
724                                                          int(new_row)+1, None)
725                    if row_min != None and row_max != None:
726                        if index == 0:
727                            label += create_label(col_name, 
728                                                  int(row_min)+1, None)
729                        elif index == len(temp_list)-1:
730                            label += create_label(col_name, None, 
731                                                  int(row_max)+1)
732                    index += 1
733                # clean up the list
734                label_out = ''
735                for item in label.split(','):
736                    if item.split(":")[1] == "]":
737                        continue
738                    else:
739                        label_out += item + ","
740
741                return label_out, col_title
742   
743    def on_close_page(self, event):
744        """
745        close the page
746        """
747        if self.GetPageCount() == 1:
748            event.Veto()
749        wx.CallAfter(self.enable_close_button)
750       
751    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
752        if data_outputs is None or data_outputs == {}:
753            return
754        inputs, outputs = self.get_odered_results(data_inputs, data_outputs)
755        for pos in range(self.GetPageCount()):
756            grid = self.GetPage(pos)
757            if grid.data is None:
758                #Found empty page
759                grid.set_data(data_inputs=inputs, 
760                              data_outputs=outputs,
761                              details=details,
762                              file_name=file_name) 
763                self.SetSelection(pos) 
764                return
765               
766        grid, pos = self.add_empty_page()
767        grid.set_data(data_inputs=inputs, 
768                      data_outputs=outputs,
769                      file_name=file_name,
770                      details=details)
771       
772    def get_odered_results(self, inputs, outputs=None):
773        """
774        Get ordered the results
775        """
776        # Let's re-order the data from the keys in 'Data' name.
777        if outputs == None:
778            return
779        try:
780            # For outputs from batch
781            to_be_sort = [str(item.label) for item in outputs['Data']]
782        except:
783            # When inputs are from an external file
784            return inputs, outputs
785        inds = numpy.lexsort((to_be_sort, to_be_sort))
786        for key in outputs.keys():
787            key_list = outputs[key]
788            temp_key = [item for item in key_list]
789            for ind in inds:
790                temp_key[ind] = key_list[inds[ind]]
791            outputs[key] = temp_key
792        for key in inputs.keys():
793            key_list = inputs[key]
794            if len(key_list) > 0:
795                temp_key = [item for item in key_list]
796                for ind in inds:
797                    temp_key[ind] = key_list[inds[ind]]
798                inputs[key] = temp_key
799        return inputs, outputs
800   
801    def add_column(self):
802        """
803        Append a new column to the grid
804        """
805        pos = self.GetSelection()
806        grid = self.GetPage(pos)
807        grid.AppendCols(1, True)
808       
809    def on_remove_column(self):
810        """
811        Remove the selected column from the grid
812        """
813        pos = self.GetSelection()
814        grid = self.GetPage(pos)
815        grid.on_remove_column(event=None)
816       
817       
818class GridPanel(SPanel):
819    def __init__(self, parent, data_inputs=None,
820                 data_outputs=None, *args, **kwds):
821        SPanel.__init__(self, parent , *args, **kwds)
822       
823        self.vbox = wx.BoxSizer(wx.VERTICAL)
824       
825        self.plotting_sizer = wx.FlexGridSizer(3, 7, 10, 5)
826        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
827        self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
828        self.vbox.AddMany([(self.grid_sizer, 1, wx.EXPAND, 0),
829                           (wx.StaticLine(self, -1), 0, wx.EXPAND, 0),
830                           (self.plotting_sizer),
831                           (self.button_sizer, 0, wx.BOTTOM, 10)])
832        self.parent = parent
833        self._data_inputs = data_inputs
834        self._data_outputs = data_outputs
835        self.x = []
836        self.= []
837        self.dy  = []
838        self.x_axis_label = None
839        self.y_axis_label = None
840        self.dy_axis_label = None
841        self.x_axis_title = None
842        self.y_axis_title = None
843        self.x_axis_unit = None
844        self.y_axis_unit = None
845        self.view_button = None
846        self.plot_button = None
847        self.notebook = None
848        self.plot_num = 1
849       
850        self.layout_grid()
851        self.layout_plotting_area()
852        self.SetSizer(self.vbox)
853
854    def set_xaxis(self, label="", x=None):
855        """
856        """
857        if x is None:
858            x = []
859        self.x = x
860        self.x_axis_label.SetValue("%s[:]" % str(label))
861        self.x_axis_title.SetValue(str(label))
862       
863    def set_yaxis(self, label="", y=None):
864        """
865        """
866        if y is None:
867            y = []
868        self.y = y
869        self.y_axis_label.SetValue("%s[:]" % str(label))
870        self.y_axis_title.SetValue(str(label))
871       
872    def set_dyaxis(self, label="", dy=None):
873        """
874        """
875        if dy is None:
876            dy = []
877        self.dy = dy
878        self.dy_axis_label.SetValue("%s[:]" % str(label))
879               
880    def get_plot_axis(self, col, list):
881        """
882       
883        """
884        axis = []
885        pos = self.notebook.GetSelection()
886        grid = self.notebook.GetPage(pos)
887        for row in list:
888            label = grid.GetCellValue(0, col)
889            value = grid.GetCellValue(row - 1, col).strip()
890            if value != "":
891                if label.lower().strip() == "data":
892                    axis.append(float(row - 1))
893                else:
894                    try:
895                        axis.append(float(value))
896                    except:
897                        msg = "Invalid data in row %s column %s" % (str(row),
898                                                                    str(col))
899                        wx.PostEvent(self.parent.parent, 
900                             StatusEvent(status=msg, info="error")) 
901            else:
902                axis.append(None) 
903        return axis
904   
905    def on_view(self, event):
906        """
907        Get object represented buy the given cell and plot them.
908        """
909        pos = self.notebook.GetSelection()
910        grid = self.notebook.GetPage(pos)
911        title = self.notebook.GetPageText(pos)
912        self.notebook.get_highlighted_row()
913        if len(grid.selected_cells) == 0:
914            msg = "Highlight a Data or Chi2 column first..."
915            wx.PostEvent(self.parent.parent, 
916                             StatusEvent(status=msg, info="error")) 
917            return
918        elif len(grid.selected_cells) > 20:
919            msg = "Too many data (> 20) to plot..."
920            msg += "\n Please select no more than 20 data."
921            dial = wx.MessageDialog(self, msg, 'Plotting', wx.OK)
922            wx.PostEvent(self.parent.parent, 
923                             StatusEvent(status=msg, info="error")) 
924            return
925
926        for cell in grid.selected_cells:
927            row, col = cell
928            label_row = 0
929            label = grid.GetCellValue(label_row, col)
930            if label in grid.data:
931                values = grid.data[label]
932                if row > len(values) or row < 1:
933                    msg = "Invalid cell was chosen." 
934                    wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
935                                                                info="error"))
936                    #time.sleep(0.5)
937                    continue
938                else:
939                     value = values[row -1]
940                if issubclass(value.__class__, BatchCell):
941                    if value.object is None or len(value.object) == 0:
942                        msg = "Row %s , " % str(row)
943                        msg += "Column %s is NOT " % str(label)
944                        msg += "the results of fits to view..."
945                        #raise ValueError, msg
946                        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
947                                                                info="error")) 
948                        return
949                    for new_plot in value.object:
950                        if new_plot is None or \
951                         not issubclass(new_plot.__class__, 
952                                        plottables.Plottable):
953                            msg = "Row %s , " % str(row)
954                            msg += "Column %s is NOT " % str(label)
955                            msg += "the results of fits to view..."
956                            #raise ValueError, msg
957                            wx.PostEvent(self.parent.parent, 
958                                 StatusEvent(status=msg, info="error")) 
959                            return
960                            #continue
961                        #new_plot.name =  title + ': ' + new_plot.title
962                        if issubclass(new_plot.__class__, Data1D):
963                            if label in grid.list_plot_panels.keys():
964                                group_id = grid.list_plot_panels[label]
965                            else:
966                                group_id = str(new_plot.group_id) + str(grid.uid)
967                                grid.list_plot_panels[label] = group_id
968                            if group_id not in new_plot.list_group_id:
969                                new_plot.group_id = group_id
970                                new_plot.list_group_id.append(group_id)
971                        else:
972                            if label.lower() in ["data", "chi2"]:
973                                if len(grid.selected_cells) != 1:
974                                    msg = "2D View: Please select one data set"
975                                    msg += " at a time for View Fit Results."
976                                    wx.PostEvent(self.parent.parent, 
977                                                 StatusEvent(status=msg,
978                                                              info="error"))
979                                    #time.sleep(0.5)
980                                    return
981
982                        wx.PostEvent(self.parent.parent, 
983                                     NewPlotEvent(plot=new_plot, 
984                                                group_id=str(new_plot.group_id),
985                                                title=title)) 
986                        msg = "Plotting the View Fit Results  completed!"
987                        wx.PostEvent( self.parent.parent, 
988                                      StatusEvent(status=msg)) 
989                else:
990                   
991                    msg = "Row %s , " % str(row)
992                    msg += "Column %s is NOT " % str(label)
993                    msg += "the results of fits to view..."
994                    #raise ValueError, msg
995                    wx.PostEvent(self.parent.parent, 
996                         StatusEvent(status=msg, info="error")) 
997                    #time.sleep(0.5)
998                    return
999                    #continue
1000   
1001    def on_plot(self, event):
1002        """
1003        Evaluate the contains of textcrtl and plot result
1004        """ 
1005        pos = self.notebook.GetSelection()
1006        grid = self.notebook.GetPage(pos)
1007        column_names = {}
1008        if grid is not None:
1009            column_names = self.notebook.get_column_labels()
1010        #evaluate x
1011        sentence = self.x_axis_label.GetValue()
1012        try:
1013            if sentence.strip() == "":
1014                msg = "Select column values for x axis"
1015                raise ValueError, msg
1016        except:
1017            msg = "X axis value error."
1018            wx.PostEvent(self.parent.parent, 
1019                            StatusEvent(status=msg, info="error")) 
1020            return
1021        dict = parse_string(sentence, column_names.keys())
1022       
1023        try:
1024            sentence = self.get_sentence(dict, sentence, column_names)
1025            x = eval(sentence)
1026        except:
1027            msg = "Need a proper x-range."
1028            wx.PostEvent(self.parent.parent, 
1029                             StatusEvent(status=msg, info="error")) 
1030            return
1031        #evaluate y
1032        sentence = self.y_axis_label.GetValue()
1033        try:
1034            if sentence.strip() == "":
1035                msg = "select value for y axis"
1036                raise ValueError, msg
1037        except:
1038            msg = "Y axis value error."
1039            wx.PostEvent(self.parent.parent, 
1040                            StatusEvent(status=msg, info="error")) 
1041            return
1042        dict = parse_string(sentence, column_names.keys())
1043        try:
1044            sentence = self.get_sentence(dict, sentence, column_names)
1045            y = eval(sentence)
1046        except:
1047            msg = "Need a proper y-range."
1048            wx.PostEvent(self.parent.parent, 
1049                             StatusEvent(status=msg, info="error")) 
1050            return
1051        #evaluate y
1052        sentence = self.dy_axis_label.GetValue()
1053        dy = None
1054        if sentence.strip() != "":
1055            dict = parse_string(sentence, column_names.keys())
1056            sentence = self.get_sentence(dict, sentence, column_names)
1057            try:
1058                dy = eval(sentence)
1059            except:
1060                msg = "Need a proper dy-range."
1061                wx.PostEvent(self.parent.parent, 
1062                                 StatusEvent(status=msg, info="error")) 
1063                return
1064        if len(x) != len(y) or (len(x) == 0 or len(y) == 0):
1065            msg = "Need same length for X and Y axis and both greater than 0"
1066            msg += " to plot.\n"
1067            msg += "Got X length = %s, Y length = %s" % (str(len(x)),
1068                                                          str(len(y)))
1069            wx.PostEvent(self.parent.parent, 
1070                             StatusEvent(status=msg, info="error")) 
1071            return
1072        if dy != None and (len(y) != len(dy)): 
1073            msg = "Need same length for Y and dY axis and both greater than 0"
1074            msg += " to plot.\n"
1075            msg += "Got Y length = %s, dY length = %s" % (str(len(y)),
1076                                                          str(len(dy)))
1077            wx.PostEvent(self.parent.parent, 
1078                             StatusEvent(status=msg, info="error")) 
1079            return
1080        #plotting
1081        new_plot = Data1D(x=x, y=y, dy=dy)
1082        new_plot.id =  wx.NewId()
1083        new_plot.group_id = wx.NewId()
1084        y_title = self.y_axis_title.GetValue()
1085        x_title = self.x_axis_title.GetValue()
1086        title = "%s_vs_%s" % (y_title, 
1087                              x_title)
1088        new_plot.xaxis(x_title, 
1089                       self.x_axis_unit.GetValue())
1090        new_plot.yaxis(y_title, 
1091                       self.y_axis_unit.GetValue())
1092        try:
1093            title = y_title.strip()
1094           
1095            title += "_" + self.notebook.GetPageText(pos)
1096            title += "_" + str(self.plot_num)
1097            self.plot_num += 1
1098            new_plot.name = title
1099            new_plot.xtransform = "x"
1100            new_plot.ytransform  = "y" 
1101            #new_plot.is_data = False
1102            wx.PostEvent(self.parent.parent, 
1103                        NewPlotEvent(plot=new_plot, 
1104                        group_id=str(new_plot.group_id), title =title)) 
1105            msg = "Plotting completed!"
1106            wx.PostEvent( self.parent.parent, 
1107                                      StatusEvent(status=msg)) 
1108            self.parent.parent.update_theory(data_id=new_plot.id, 
1109                                              theory=new_plot) 
1110        except:
1111             wx.PostEvent(self.parent.parent, 
1112                             StatusEvent(status=msg, info="error")) 
1113   
1114    def get_sentence(self, dict, sentence, column_names):
1115        """
1116        Get sentence from dict
1117        """
1118        for tok, (col_name, list) in dict.iteritems():
1119            col = column_names[col_name]
1120            axis = self.get_plot_axis(col, list)
1121            sentence = sentence.replace(tok, 
1122                                        "numpy.array(%s)" % str(axis))
1123        for key, value in FUNC_DICT.iteritems():
1124            sentence = sentence.replace(key.lower(), value)
1125        return sentence
1126           
1127    def layout_grid(self):
1128        """
1129        Draw the area related to the grid
1130        """
1131        self.notebook = Notebook(parent=self)
1132        self.notebook.set_data(self._data_inputs, self._data_outputs)
1133        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
1134       
1135    def layout_plotting_area(self):
1136        """
1137        Draw area containing options to plot
1138        """
1139        view_description = wx.StaticBox(self, -1, 'Plot Fits/Residuals')
1140        note = "To plot the fits (or residuals), click the 'View Fits' button"
1141        note += "\n after highlighting the Data names (or Chi2 values)."
1142        note_text = wx.StaticText(self, -1, note)
1143        boxsizer1 = wx.StaticBoxSizer(view_description, wx.HORIZONTAL)
1144        self.x_axis_title = wx.TextCtrl(self, -1)
1145        self.y_axis_title = wx.TextCtrl(self, -1)
1146        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1147        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1148        self.dy_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1149        self.x_axis_add = wx.Button(self, -1, "Add")
1150        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1151                            id=self.x_axis_add.GetId())
1152        self.y_axis_add = wx.Button(self, -1, "Add")
1153        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1154                            id=self.y_axis_add.GetId())
1155        self.dy_axis_add = wx.Button(self, -1, "Add")
1156        self.dy_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1157                            id=self.dy_axis_add.GetId())
1158        self.x_axis_unit = wx.TextCtrl(self, -1)
1159        self.y_axis_unit = wx.TextCtrl(self, -1)
1160        self.view_button = wx.Button(self, -1, "View Fits")
1161        view_tip = "Highlight the data set or the Chi2 column first."
1162        self.view_button.SetToolTipString(view_tip)
1163        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
1164        self.plot_button = wx.Button(self, -1, "Plot")
1165        plot_tip = "Highlight a column for each axis and \n"
1166        plot_tip += "click the Add buttons first."
1167       
1168        self.plot_button.SetToolTipString(plot_tip)
1169        boxsizer1.AddMany([(note_text, 0, wx.LEFT, 10),
1170                           (self.view_button, 0, wx.LEFT|wx.RIGHT, 10)])
1171        self.button_sizer.AddMany([(boxsizer1, 0, 
1172                                    wx.LEFT|wx.RIGHT|wx.BOTTOM, 10), 
1173                                   (self.plot_button, 0, 
1174                                    wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND, 12)])
1175       
1176        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
1177        self.plotting_sizer.AddMany([
1178                    (wx.StaticText(self, -1, 
1179                                   "X-axis Label\nSelection Range"), 1,
1180                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1181                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
1182                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
1183                    (wx.StaticText(self, -1, "X-axis Label"), 1, 
1184                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1185                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
1186                    (wx.StaticText(self, -1 , "X-axis Unit"), 1, 
1187                     wx.TOP|wx.BOTTOM, 10),
1188                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
1189                    (wx.StaticText(self, -1, 
1190                                   "Y-axis Label\nSelection Range"), 1, 
1191                     wx.BOTTOM|wx.LEFT, 10),
1192                    (self.y_axis_label, wx.BOTTOM, 10),
1193                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
1194                    (wx.StaticText(self, -1, "Y-axis Label"), 1, 
1195                     wx.BOTTOM|wx.LEFT, 10),
1196                    (self.y_axis_title,  wx.BOTTOM, 10),
1197                    (wx.StaticText(self, -1 , "Y-axis Unit"), 1, wx.BOTTOM, 10),
1198                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
1199                    (wx.StaticText(self, -1, 
1200                                   "dY-Bar (Optional)\nSelection Range"), 
1201                                   1, wx.BOTTOM|wx.LEFT, 10),
1202                    (self.dy_axis_label, wx.BOTTOM, 10),
1203                    (self.dy_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
1204                      (-1, -1),
1205                      (-1, -1),
1206                      (-1, -1),
1207                      (-1, -1),
1208                      (-1, -1),
1209                      (-1, -1),
1210                      (-1, 1)])
1211   
1212    def on_edit_axis(self, event):
1213        """
1214        Get the selected column on  the visible grid and set values for axis
1215        """
1216        try:
1217            cell_list = self.notebook.on_edit_axis()
1218        except:
1219            msg = str(sys.exc_value)
1220            wx.PostEvent(self.parent.parent, 
1221                             StatusEvent(status=msg, info="error")) 
1222            return 
1223        label, title = self.create_axis_label(cell_list)
1224        tcrtl = event.GetEventObject()
1225        if tcrtl == self.x_axis_add:
1226            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
1227                                   label, title)
1228        elif tcrtl == self.y_axis_add:
1229            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
1230                                   label, title)
1231        elif tcrtl == self.dy_axis_add:
1232            self.edit_axis_helper(self.dy_axis_label, None,
1233                                   label, None)
1234           
1235    def create_axis_label(self, cell_list):
1236        """
1237        Receive a list of cells and  create a string presenting the selected
1238        cells.
1239        :param cell_list: list of tuple
1240       
1241        """
1242        if self.notebook is not None:
1243            return self.notebook.create_axis_label(cell_list)
1244   
1245    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
1246        """
1247        get controls to modify
1248        """
1249        if label != None:
1250            tcrtl_label.SetValue(str(label))
1251        if title != None:
1252            tcrtl_title.SetValue(str(title))
1253       
1254    def add_column(self):
1255        """
1256        """
1257        if self.notebook is not None:
1258            self.notebook.add_column()
1259       
1260    def on_remove_column(self):
1261        """
1262        """
1263        if self.notebook is not None:
1264            self.notebook.on_remove_column()
1265       
1266       
1267class GridFrame(wx.Frame):
1268    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
1269                 title="Grid Window", size=(800, 500)):
1270        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
1271        self.parent = parent
1272        self.panel = GridPanel(self, data_inputs, data_outputs)
1273        menubar = wx.MenuBar()
1274        self.SetMenuBar(menubar)
1275       
1276        self.curr_col = None
1277        self.curr_grid = None
1278        self.curr_col_name = ""
1279        file = wx.Menu()
1280        menubar.Append(file, "&File")
1281       
1282        hint = "Open file containing batch results"
1283        open_menu = file.Append(wx.NewId(), 'Open ', hint)
1284        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
1285       
1286        hint = "Open the the current grid into excel"
1287        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
1288        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
1289        file.AppendSeparator()
1290        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
1291        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
1292       
1293        self.edit = wx.Menu()
1294        hint = "Insert column before the selected column"
1295        self.insert_before_menu = wx.Menu()
1296        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
1297                                                      'Insert Before', hint)
1298 
1299        hint = "Remove the selected column"
1300        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
1301        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
1302       
1303        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
1304        menubar.Append(self.edit, "&Edit")
1305        self.Bind(wx.EVT_CLOSE, self.on_close)
1306    def GetLabelText(self, id):
1307        """
1308        """
1309        for item in self.insert_before_menu.GetMenuItems():
1310            m_id = item.GetId() 
1311            if m_id == id:
1312                return item.GetLabel() 
1313   
1314    def on_remove_column(self, event):
1315        """
1316        """
1317        pos = self.panel.notebook.GetSelection()
1318        grid = self.panel.notebook.GetPage(pos)
1319        grid.on_remove_column(event=None)
1320       
1321    def on_menu_open(self, event):
1322        """
1323       
1324        """
1325        if self.edit == event.GetMenu():
1326            #get the selected column
1327            pos = self.panel.notebook.GetSelection()
1328            grid = self.panel.notebook.GetPage(pos)
1329            col_list = grid.GetSelectedCols()
1330            if len(col_list) > 0:
1331                self.remove_menu.Enable(True)
1332            else:
1333                self.remove_menu.Enable(False)
1334            if len(col_list) == 0 or len(col_list) > 1:
1335                self.insert_sub_menu.Enable(False)
1336               
1337                label = "Insert Column Before"
1338                self.insert_sub_menu.SetText(label)
1339            else:
1340                self.insert_sub_menu.Enable(True)
1341               
1342                col = col_list[0]
1343                #GetColLabelValue(self, col)
1344                col_name = grid.GetCellValue(row=0, col=col)
1345                label = "Insert Column Before " + str(col_name)
1346                self.insert_sub_menu.SetText(label)
1347                for item in self.insert_before_menu.GetMenuItems():
1348                    self.insert_before_menu.DeleteItem(item)
1349                grid.insert_col_menu(menu=self.insert_before_menu, 
1350                                     label=col_name, window=self)
1351        event.Skip()
1352       
1353 
1354       
1355    def on_save_page(self, event):
1356        """
1357        """
1358        if self.parent is not None:
1359            pos = self.panel.notebook.GetSelection()
1360            grid = self.panel.notebook.GetPage(pos)
1361            if grid.file_name is None or grid.file_name.strip() == "" or \
1362                grid.data is None or len(grid.data) == 0:
1363                name = self.panel.notebook.GetPageText(pos)
1364                msg = " %s has not data to save" % str(name)
1365                wx.PostEvent(self.parent, 
1366                             StatusEvent(status=msg, info="error")) 
1367           
1368                return
1369            reader, ext = os.path.splitext(grid.file_name)
1370            path = None
1371            if self.parent is not None: 
1372                location = os.path.dirname(grid.file_name)
1373                dlg = wx.FileDialog(self, "Save Project file",
1374                            location, grid.file_name, ext, wx.SAVE)
1375                path = None
1376                if dlg.ShowModal() == wx.ID_OK:
1377                    path = dlg.GetPath()
1378                dlg.Destroy()
1379                if path != None:
1380                    if self.parent is not None:
1381                        data = grid.get_grid_view()
1382                        self.parent.write_batch_tofile(data=data, 
1383                                               file_name=path,
1384                                               details=grid.details)
1385   
1386    def on_open(self, event):
1387        """
1388        Open file containg batch result
1389        """
1390        if self.parent is not None:
1391            self.parent.on_read_batch_tofile(self)
1392           
1393    def open_with_excel(self, event):
1394        """
1395        open excel and display batch result in Excel
1396        """
1397        if self.parent is not None:
1398            pos = self.panel.notebook.GetSelection()
1399            grid = self.panel.notebook.GetPage(pos)
1400            data = grid.get_grid_view()
1401            if grid.file_name is None or grid.file_name.strip() == "" or \
1402                grid.data is None or len(grid.data) == 0:
1403                name = self.panel.notebook.GetPageText(pos)
1404                msg = " %s has not data to open on excel" % str(name)
1405                wx.PostEvent(self.parent, 
1406                             StatusEvent(status=msg, info="error")) 
1407           
1408                return
1409            self.parent.open_with_externalapp(data=data,
1410                                              file_name=grid.file_name, 
1411                                              details=grid.details)
1412           
1413    def on_close(self, event):
1414        """
1415        """
1416        self.Hide()
1417       
1418   
1419    def on_append_column(self, event):
1420        """
1421        Append a new column to the grid
1422        """
1423        self.panel.add_column()
1424       
1425    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
1426        """
1427        """
1428       
1429        self.panel.notebook.set_data(data_inputs=data_inputs, 
1430                            file_name=file_name,
1431                            details=details,
1432                            data_outputs=data_outputs)
1433     
1434     
1435class BatchOutputFrame(wx.Frame):
1436    """
1437    Allow to select where the result of batch will be displayed or stored
1438    """
1439    def __init__(self, parent, data_inputs, data_outputs, file_name="",
1440                 details="", *args, **kwds):
1441        """
1442        :param parent: Window instantiating this dialog
1443        :param result: result to display in a grid or export to an external
1444                application.
1445        """
1446        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
1447        wx.Frame.__init__(self, parent, *args, **kwds)
1448        self.parent = parent
1449        self.panel = wx.Panel(self)
1450        self.file_name = file_name
1451        self.details = details
1452        self.data_inputs = data_inputs
1453        self.data_outputs = data_outputs
1454        self.data = {}
1455        for item in (self.data_outputs, self.data_inputs):
1456            self.data.update(item)
1457        self.flag = 1
1458        self.SetSize((300, 200))
1459        self.local_app_selected = None
1460        self.external_app_selected = None
1461        self.save_to_file = None
1462        self._do_layout()
1463   
1464    def _do_layout(self):
1465        """
1466        Draw the content of the current dialog window
1467        """
1468        vbox = wx.BoxSizer(wx.VERTICAL)
1469        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
1470        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1471        selection_sizer = wx.GridBagSizer(5, 5)
1472        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1473        text = "Open with %s" % self.parent.application_name
1474        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
1475                                                style=wx.RB_GROUP)
1476        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1477                    id=self.local_app_selected.GetId())
1478        text = "Open with Excel"
1479        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
1480        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1481                    id=self.external_app_selected.GetId())
1482        text = "Save to File"
1483        self.save_to_file = wx.CheckBox(self.panel, -1, text)
1484        self.Bind(wx.EVT_CHECKBOX, self.onselect,
1485                    id=self.save_to_file.GetId())
1486        self.local_app_selected.SetValue(True)
1487        self.external_app_selected.SetValue(False)
1488        self.save_to_file.SetValue(False)
1489        button_close = wx.Button(self.panel, -1, "Close")
1490        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
1491                           handler=self.on_close)
1492        button_apply = wx.Button(self.panel, -1, "Apply")
1493        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
1494                        handler=self.on_apply)
1495        button_apply.SetFocus()
1496        hint = ""
1497        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
1498        hint_sizer.Add(selection_sizer)
1499        #draw area containing radio buttons
1500        ix = 0
1501        iy = 0
1502        selection_sizer.Add(self.local_app_selected, (iy, ix),
1503                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1504        iy += 1
1505        selection_sizer.Add(self.external_app_selected, (iy, ix),
1506                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1507        iy += 1
1508        selection_sizer.Add(self.save_to_file, (iy, ix),
1509                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1510        #contruction the sizer contaning button
1511        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1512
1513        button_sizer.Add(button_close, 0,
1514                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1515        button_sizer.Add(button_apply, 0,
1516                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1517        vbox.Add(hint_sizer, 0, wx.EXPAND|wx.ALL, 10)
1518        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
1519        vbox.Add(button_sizer, 0, wx.TOP|wx.BOTTOM, 10)
1520        self.SetSizer(vbox)
1521       
1522    def on_apply(self, event):
1523        """
1524        Get the user selection and display output to the selected application
1525        """
1526        if self.flag == 1:
1527            self.parent.open_with_localapp(data_inputs=self.data_inputs,
1528                                           data_outputs=self.data_outputs)
1529        elif self.flag == 2:
1530            self.parent.open_with_externalapp(data=self.data, 
1531                                              file_name=self.file_name,
1532                                              details=self.details)
1533    def on_close(self, event):
1534        """
1535        close the Window
1536        """
1537        self.Close()
1538       
1539    def onselect(self, event=None):
1540        """
1541        Receive event and display data into third party application
1542        or save data to file.
1543       
1544        """
1545        if self.save_to_file.GetValue():
1546            reader, ext = os.path.splitext(self.file_name)
1547            path = None
1548            location = os.getcwd()
1549            if self.parent is not None: 
1550                location = os.path.dirname(self.file_name)
1551                dlg = wx.FileDialog(self, "Save Project file",
1552                            location, self.file_name, ext, wx.SAVE)
1553                path = None
1554                if dlg.ShowModal() == wx.ID_OK:
1555                    path = dlg.GetPath()
1556                dlg.Destroy()
1557                if path != None:
1558                    if self.parent is not None and  self.data is not None:
1559                        self.parent.write_batch_tofile(data=self.data, 
1560                                                       file_name=path,
1561                                                       details=self.details)
1562        if self.local_app_selected.GetValue():
1563            self.flag = 1
1564        else:
1565            self.flag = 2
1566        return self.flag
1567   
1568 
1569       
1570if __name__ == "__main__":
1571    app = wx.App()
1572   
1573    try:
1574        data = {}
1575        j = 0
1576        for i in range(4):
1577            j += 1
1578            data["index"+str(i)] = [i/j, i*j, i, i+j]
1579       
1580        data_input =  copy.deepcopy(data)   
1581        data_input["index5"] = [10, 20, 40, 50]
1582        frame = GridFrame(data_outputs=data, data_inputs=data_input)
1583        frame.Show(True)
1584    except:
1585        print sys.exc_value
1586       
1587    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.