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

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 507c68f was 3553ad2, checked in by Jae Cho <jhjcho@…>, 13 years ago

improved cell selection behaviors

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