source: sasview/src/sas/sasgui/guiframe/data_panel.py @ 66aeb15

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.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 66aeb15 was 66aeb15, checked in by Paul Kienzle <pkienzle@…>, 7 years ago

data panel: put the data/theory label in the tree root so it is visible even when the tree is closed

  • Property mode set to 100644
File size: 56.3 KB
RevLine 
[3c44c66]1################################################################################
[c8e1996]2# This software was developed by the University of Tennessee as part of the
3# Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4# project funded by the US National Science Foundation.
[3c44c66]5#
[c8e1996]6# See the license text in license.txt
[3c44c66]7#
[c8e1996]8# copyright 2010, University of Tennessee
[3c44c66]9################################################################################
10"""
11This module provides Graphic interface for the data_manager module.
12"""
13import wx
[31f3222b]14from wx.build import build_options
[1941e6a]15
[3c44c66]16import sys
17from wx.lib.scrolledpanel import ScrolledPanel
[c8e1996]18import wx.lib.agw.customtreectrl as CT
[d85c194]19from sas.sasgui.guiframe.dataFitting import Data1D
20from sas.sasgui.guiframe.dataFitting import Data2D
21from sas.sasgui.guiframe.panel_base import PanelBase
22from sas.sasgui.guiframe.events import StatusEvent
23from sas.sasgui.guiframe.events import EVT_DELETE_PLOTPANEL
24from sas.sasgui.guiframe.events import NewLoadDataEvent
25from sas.sasgui.guiframe.events import NewPlotEvent
26from sas.sasgui.guiframe.gui_style import GUIFRAME
27from sas.sasgui.guiframe.events import NewBatchEvent
[b699768]28from sas.sascalc.dataloader.loader import Loader
[c8e1996]29# from sas.sasgui.guiframe.local_perspectives.plotting.masking \
[318b5bbb]30#    import FloatPanel as QucikPlotDialog
[c8e1996]31from sas.sasgui.guiframe.local_perspectives.plotting.SimplePlot \
32    import PlotFrame as QucikPlotDialog
[d85c194]33import sas.sasgui.guiframe.config as config
[e767897]34
[c8e1996]35# Check version
36toks = str(wx.__version__).split('.')
37if int(toks[1]) < 9:
38    if int(toks[2]) < 12:
39        wx_version = 811
40    else:
41        wx_version = 812
42else:
43    wx_version = 900
44
[2a62d5c]45extension_list = []
46if config.APPLICATION_STATE_EXTENSION is not None:
47    extension_list.append(config.APPLICATION_STATE_EXTENSION)
[e767897]48EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
[99f9ecf]49PLUGINS_WLIST = config.PLUGINS_WLIST
50APPLICATION_WLIST = config.APPLICATION_WLIST
[3f0c330]51
[c8e1996]52# Control panel width
[57f537a]53if sys.platform.count("win32") > 0:
[3f0c330]54    PANEL_WIDTH = 235
55    PANEL_HEIGHT = 700
56    CBOX_WIDTH = 140
57    BUTTON_WIDTH = 80
58    FONT_VARIANT = 0
[234a3fa]59    IS_MAC = False
[3f0c330]60else:
61    PANEL_WIDTH = 255
62    PANEL_HEIGHT = 750
63    CBOX_WIDTH = 155
64    BUTTON_WIDTH = 100
65    FONT_VARIANT = 1
[234a3fa]66    IS_MAC = True
[3f0c330]67
[c8e1996]68STYLE_FLAG = wx.RAISED_BORDER | CT.TR_HAS_BUTTONS | CT.TR_HIDE_ROOT |\
69                    wx.WANTS_CHARS | CT.TR_HAS_VARIABLE_ROW_HEIGHT
[e767897]70
71
[3feed3e]72class DataTreeCtrl(CT.CustomTreeCtrl):
[3c44c66]73    """
74    Check list control to be used for Data Panel
75    """
[66aeb15]76    def __init__(self, parent, root, *args, **kwds):
[c8e1996]77        # agwstyle is introduced in wx.2.8.11 but is not working for mac
[228a8bb]78        if IS_MAC and wx_version < 812:
[91bdf87]79            try:
80                kwds['style'] = STYLE_FLAG
[d34f9f6]81                CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
[91bdf87]82            except:
[af7ba61]83                del kwds['style']
[d34f9f6]84                CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
[73581ce]85        else:
[6605880]86            # agwstyle is introduced in wx.2.8.11
87            # argument working only for windows
[73581ce]88            try:
89                kwds['agwStyle'] = STYLE_FLAG
[d34f9f6]90                CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
[73581ce]91            except:
92                try:
[d34f9f6]93                    del kwds['agwStyle']
[73581ce]94                    kwds['style'] = STYLE_FLAG
[d34f9f6]95                    CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
[73581ce]96                except:
[d34f9f6]97                    del kwds['style']
98                    CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
[66aeb15]99        self.root = self.AddRoot(root)
[e767897]100
[0b705915]101    def OnCompareItems(self, item1, item2):
[e767897]102        """
103        Overrides OnCompareItems in wx.TreeCtrl.
104        Used by the SortChildren method.
[0b705915]105        """
106        # Get the item data
[d4d4c8a]107        data_1 = self.GetItemText(item1)
108        data_2 = self.GetItemText(item2)
[0b705915]109        # Compare the item data
[d4d4c8a]110        if data_1 < data_2:
[0b705915]111            return -1
[d4d4c8a]112        elif data_1 > data_2:
[0b705915]113            return 1
114        else:
115            return 0
[e767897]116
[c8e1996]117
[52725d6]118class DataPanel(ScrolledPanel, PanelBase):
[3c44c66]119    """
[e767897]120    This panel displays data available in the application and widgets to
[3c44c66]121    interact with data.
122    """
[c8e1996]123    # Internal name for the AUI manager
[3feed3e]124    window_name = "Data Panel"
[c8e1996]125    # Title to appear on top of the window
[1b1bbf9]126    window_caption = "Data Explorer"
[c8e1996]127    # type of window
[3feed3e]128    window_type = "Data Panel"
[c8e1996]129    # Flag to tell the GUI manager that this panel is not
[3feed3e]130    #  tied to any perspective
[c8e1996]131    # ALWAYS_ON = True
132
[e767897]133    def __init__(self, parent,
[600eca2]134                 list=None,
[ea4dfe0]135                 size=(PANEL_WIDTH, PANEL_HEIGHT),
[cb6a2b7]136                 id=-1,
[ea4dfe0]137                 list_of_perspective=None, manager=None, *args, **kwds):
[c8e1996]138        # kwds['size'] = size
139        # kwds['style'] = STYLE_FLAG
[cb6a2b7]140        ScrolledPanel.__init__(self, parent=parent, id=id, *args, **kwds)
[31ac4a1]141        PanelBase.__init__(self, parent)
[3c44c66]142        self.SetupScrolling()
[c8e1996]143        # Set window's font size
[3f0c330]144        self.SetWindowVariant(variant=FONT_VARIANT)
[e767897]145        self.loader = Loader()
[c8e1996]146        # Default location
[e767897]147        self._default_save_location = None
[ee2b492]148        self.all_data1d = True
[ae84427]149        self.parent = parent.parent
150        self._manager = manager
[31ac4a1]151        self.frame = parent
[600eca2]152        if list is None:
153            list = []
[3c44c66]154        self.list_of_data = list
[600eca2]155        if list_of_perspective is None:
156            list_of_perspective = []
[3feed3e]157        self.list_of_perspective = list_of_perspective
[6605880]158        self.list_rb_perspectives = []
[c70eb7c]159        self.list_cb_data = {}
160        self.list_cb_theory = {}
[61ffd1e]161        self.tree_ctrl = None
162        self.tree_ctrl_theory = None
[600eca2]163        self.perspective_cbox = None
[c8e1996]164        # Create context menu for page
[bf39777]165        self.data_menu = None
[dc0cfa4]166        self.popUpMenu = None
[5e5704d]167        self.plot3d_id = None
168        self.editmask_id = None
169        # Default attr
[c8e1996]170        self.vbox = None
[5e5704d]171        self.sizer1 = None
172        self.sizer2 = None
173        self.sizer3 = None
174        self.sizer4 = None
175        self.sizer5 = None
176        self.selection_cbox = None
177        self.bt_add = None
178        self.bt_remove = None
179        self.bt_import = None
180        self.bt_append_plot = None
181        self.bt_plot = None
182        self.bt_freeze = None
183        self.cb_plotpanel = None
184        self.rb_single_mode = None
185        self.rb_batch_mode = None
186
[3feed3e]187        self.owner = None
188        self.do_layout()
[600eca2]189        self.fill_cbox_analysis(self.list_of_perspective)
[1b1bbf9]190        self.Bind(wx.EVT_SHOW, self.on_close_page)
[13a63ab]191        if self.parent is not None:
192            self.parent.Bind(EVT_DELETE_PLOTPANEL, self._on_delete_plot_panel)
[e767897]193
[3feed3e]194    def do_layout(self):
[6db811e]195        """
[6605880]196            Create the panel layout
[6db811e]197        """
[3c44c66]198        self.define_panel_structure()
199        self.layout_selection()
[5c4b674]200        self.layout_data_list()
[8f19b69]201        self.layout_batch()
[64f9fa6]202        self.layout_button()
[e767897]203
[7fb69f26]204    def disable_app_combo(self, enable):
205        """
[5e5704d]206        Disable app combo box
[7fb69f26]207        """
208        self.perspective_cbox.Enable(enable)
[e767897]209
[3c44c66]210    def define_panel_structure(self):
211        """
212        Define the skeleton of the panel
213        """
[3feed3e]214        w, h = self.parent.GetSize()
[c8e1996]215        self.vbox = wx.BoxSizer(wx.VERTICAL)
[3c44c66]216        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
[e095c3a9]217        self.sizer1.SetMinSize(wx.Size(w/13, h*2/5))
[e767897]218
[3feed3e]219        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
[2990dd3]220        self.sizer3 = wx.FlexGridSizer(9, 2, 4, 1)
[64f9fa6]221        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
[18ec684]222        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
[e767897]223
[c8e1996]224        self.vbox.Add(self.sizer5, 0, wx.EXPAND | wx.ALL, 1)
225        self.vbox.Add(self.sizer1, 1, wx.EXPAND | wx.ALL, 0)
226        self.vbox.Add(self.sizer2, 0, wx.EXPAND | wx.ALL, 1)
227        self.vbox.Add(self.sizer3, 0, wx.EXPAND | wx.ALL, 10)
228        # self.vbox.Add(self.sizer4, 0, wx.EXPAND|wx.ALL,5)
[e767897]229
[3c44c66]230        self.SetSizer(self.vbox)
[e767897]231
[3feed3e]232    def layout_selection(self):
[3c44c66]233        """
[6605880]234            Create selection option combo box
[3c44c66]235        """
[3feed3e]236        select_txt = wx.StaticText(self, -1, 'Selection Options')
[bffa3d0]237        select_txt.SetForegroundColour('blue')
[3feed3e]238        self.selection_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
239        list_of_options = ['Select all Data',
[c8e1996]240                           'Unselect all Data',
[3feed3e]241                           'Select all Data 1D',
242                           'Unselect all Data 1D',
243                           'Select all Data 2D',
[c8e1996]244                           'Unselect all Data 2D']
[3feed3e]245        for option in list_of_options:
246            self.selection_cbox.Append(str(option))
[18ec684]247        self.selection_cbox.SetValue('Select all Data')
[5e5704d]248        wx.EVT_COMBOBOX(self.selection_cbox, -1, self._on_selection_type)
[e767897]249        self.sizer5.AddMany([(select_txt, 0, wx.ALL, 5),
[c8e1996]250                            (self.selection_cbox, 0, wx.ALL, 5)])
[61ffd1e]251        self.enable_selection()
[e767897]252
[3feed3e]253    def _on_selection_type(self, event):
[3c44c66]254        """
[6605880]255            Select data according to patterns
256            :param event: UI event
[3c44c66]257        """
[e767897]258        def check_item_and_children(control, check_value=True):
259            self.tree_ctrl.CheckItem(data_ctrl, check_value)
260            if data_ctrl.HasChildren():
[c8e1996]261                if check_value and not control.IsExpanded():
[e767897]262                    # Only select children if control is expanded
263                    # Always deselect children, regardless (see ticket #259)
264                    return
265                for child_ctrl in data_ctrl.GetChildren():
266                    self.tree_ctrl.CheckItem(child_ctrl, check_value)
267
[3feed3e]268        option = self.selection_cbox.GetValue()
[e767897]269
[18ec684]270        pos = self.selection_cbox.GetSelection()
271        if pos == wx.NOT_FOUND:
[e767897]272            return
[18ec684]273        option = self.selection_cbox.GetString(pos)
[b5e79f7]274        for item in self.list_cb_data.values():
[5e5704d]275            data_ctrl, _, _, _, _, _, _, _ = item
[e767897]276            _, data_class, _ = self.tree_ctrl.GetItemPyData(data_ctrl)
[18ec684]277            if option == 'Select all Data':
[e767897]278                check_item_and_children(data_ctrl, check_value=True)
[18ec684]279            elif option == 'Unselect all Data':
[e767897]280                check_item_and_children(data_ctrl, check_value=False)
[18ec684]281            elif option == 'Select all Data 1D':
282                if data_class == 'Data1D':
[e767897]283                    check_item_and_children(data_ctrl, check_value=True)
[18ec684]284            elif option == 'Unselect all Data 1D':
[c70eb7c]285                if data_class == 'Data1D':
[e767897]286                    check_item_and_children(data_ctrl, check_value=False)
[18ec684]287            elif option == 'Select all Data 2D':
288                if data_class == 'Data2D':
[e767897]289                    check_item_and_children(data_ctrl, check_value=True)
[18ec684]290            elif option == 'Unselect all Data 2D':
291                if data_class == 'Data2D':
[e767897]292                    check_item_and_children(data_ctrl, check_value=False)
[1e3394f]293        self.enable_append()
294        self.enable_freeze()
295        self.enable_plot()
296        self.enable_import()
[248b918]297        self.enable_remove()
[e767897]298
[3c44c66]299    def layout_button(self):
300        """
301        Layout widgets related to buttons
302        """
[c8e1996]303        # Load Data Button
[e767897]304        self.bt_add = wx.Button(self, wx.NewId(), "Load Data",
[2567003]305                                size=(BUTTON_WIDTH, -1))
[c461ebe]306        self.bt_add.SetToolTipString("Load data files")
[2a62d5c]307        wx.EVT_BUTTON(self, self.bt_add.GetId(), self._load_data)
[e767897]308
[c8e1996]309        # Delete Data Button
[c5a769e]310        self.bt_remove = wx.Button(self, wx.NewId(), "Delete Data",
[c8e1996]311                                   size=(BUTTON_WIDTH, -1))
[c5a769e]312        self.bt_remove.SetToolTipString("Delete data from the application")
[248b918]313        wx.EVT_BUTTON(self, self.bt_remove.GetId(), self.on_remove)
[e767897]314
[c8e1996]315        # Send data to perspective button
[2567003]316        self.bt_import = wx.Button(self, wx.NewId(), "Send To",
[c8e1996]317                                   size=(BUTTON_WIDTH, -1))
[5e5704d]318        self.bt_import.SetToolTipString("Send Data set to active perspective")
[3c44c66]319        wx.EVT_BUTTON(self, self.bt_import.GetId(), self.on_import)
[e767897]320
[c8e1996]321        # Choose perspective to be send data to combo box
[df58ecab]322        self.perspective_cbox = wx.ComboBox(self, -1,
[c8e1996]323                                            style=wx.CB_READONLY)
[66f7016]324        if not IS_MAC:
325            self.perspective_cbox.SetMinSize((BUTTON_WIDTH*1.6, -1))
[e767897]326        wx.EVT_COMBOBOX(self.perspective_cbox, -1,
[600eca2]327                        self._on_perspective_selection)
[e767897]328
[c8e1996]329        # Append data to current Graph Button
[2567003]330        self.bt_append_plot = wx.Button(self, wx.NewId(), "Append Plot To",
331                                        size=(BUTTON_WIDTH, -1))
[c8e1996]332        self.bt_append_plot.SetToolTipString(
333            "Plot the selected data in the active panel")
[213892bc]334        wx.EVT_BUTTON(self, self.bt_append_plot.GetId(), self.on_append_plot)
[e767897]335
[c8e1996]336        # Create a new graph and send data to that new graph button
[e767897]337        self.bt_plot = wx.Button(self, wx.NewId(), "New Plot",
[2567003]338                                 size=(BUTTON_WIDTH, -1))
[3c44c66]339        self.bt_plot.SetToolTipString("To trigger plotting")
340        wx.EVT_BUTTON(self, self.bt_plot.GetId(), self.on_plot)
[e767897]341
[c8e1996]342        # Freeze current theory button - becomes a data set and stays on graph
[e767897]343        self.bt_freeze = wx.Button(self, wx.NewId(), "Freeze Theory",
[2567003]344                                   size=(BUTTON_WIDTH, -1))
[7360816]345        freeze_tip = "To trigger freeze a theory: making a copy\n"
346        freeze_tip += "of the theory checked to Data box,\n"
[2719255]347        freeze_tip += "     so that it can act like a real data set."
348        self.bt_freeze.SetToolTipString(freeze_tip)
[c70eb7c]349        wx.EVT_BUTTON(self, self.bt_freeze.GetId(), self.on_freeze)
[e767897]350
[c8e1996]351        # select plot to send to combo box (blank if no data)
[b9f6d83]352        if sys.platform == 'darwin':
[e767897]353            self.cb_plotpanel = wx.ComboBox(self, -1,
[31f3222b]354                                            style=wx.CB_READONLY)
355        else:
[e767897]356            self.cb_plotpanel = wx.ComboBox(self, -1,
[c8e1996]357                                            style=wx.CB_READONLY | wx.CB_SORT)
[5e5704d]358        wx.EVT_COMBOBOX(self.cb_plotpanel, -1, self._on_plot_selection)
[5e8e615]359        self.cb_plotpanel.Disable()
[e767897]360
[c8e1996]361        # Help button
[1941e6a]362        self.bt_help = wx.Button(self, wx.NewId(), "HELP",
363                                 size=(BUTTON_WIDTH, -1))
364        self.bt_help.SetToolTipString("Help for the Data Explorer.")
[c8e1996]365        wx.EVT_BUTTON(self, self.bt_help.GetId(), self.on_help)
[0a2fdca]366
[600eca2]367        self.sizer3.AddMany([(self.bt_add),
368                             ((10, 10)),
[248b918]369                             (self.bt_remove),
370                             ((10, 10)),
[7360816]371                             (self.bt_freeze),
372                             ((10, 10)),
373                             (self.bt_plot),
374                             ((10, 10)),
375                             (self.bt_append_plot),
[e767897]376                             (self.cb_plotpanel,
[c8e1996]377                              wx.EXPAND | wx.ADJUST_MINSIZE, 5),
[64f9fa6]378                             ((5, 5)),
379                             ((5, 5)),
[c8e1996]380                             (self.bt_import, 0, wx.EXPAND | wx.RIGHT, 5),
[e767897]381                             (self.perspective_cbox,
[c8e1996]382                              wx.EXPAND | wx.ADJUST_MINSIZE, 5),
[64f9fa6]383                             ((10, 10)),
384                             (self.sizer4),
[1941e6a]385                             ((10, 10)),
[b5c44f0]386                             (self.bt_help, 0, wx.RIGHT, 5)])
[c461ebe]387
[600eca2]388        self.sizer3.AddGrowableCol(1, 1)
[a03d419]389        self.show_data_button()
[248b918]390        self.enable_remove()
[f7d0b74]391        self.enable_import()
392        self.enable_plot()
393        self.enable_append()
394        self.enable_freeze()
[e26d0db]395        self.enable_remove_plot()
[e767897]396
[3feed3e]397    def layout_batch(self):
[3c44c66]398        """
[6605880]399            Set up batch mode options
[3c44c66]400        """
[3feed3e]401        self.rb_single_mode = wx.RadioButton(self, -1, 'Single Mode',
402                                             style=wx.RB_GROUP)
403        self.rb_batch_mode = wx.RadioButton(self, -1, 'Batch Mode')
[24adb89]404        self.Bind(wx.EVT_RADIOBUTTON, self.on_single_mode,
[c8e1996]405                  id=self.rb_single_mode.GetId())
[24adb89]406        self.Bind(wx.EVT_RADIOBUTTON, self.on_batch_mode,
[c8e1996]407                  id=self.rb_batch_mode.GetId())
[e767897]408
[d03a356]409        self.rb_single_mode.SetValue(not self.parent.batch_on)
410        self.rb_batch_mode.SetValue(self.parent.batch_on)
[6605880]411        self.sizer4.AddMany([(self.rb_single_mode, 0, wx.ALL, 4),
412                             (self.rb_batch_mode, 0, wx.ALL, 4)])
[e767897]413
[80ddbd0]414    def on_single_mode(self, event):
415        """
[6605880]416            Change to single mode
417            :param event: UI event
[80ddbd0]418        """
419        if self.parent is not None:
[5e5704d]420            wx.PostEvent(self.parent, NewBatchEvent(enable=False))
[e767897]421
[80ddbd0]422    def on_batch_mode(self, event):
423        """
[6605880]424            Change to batch mode
425            :param event: UI event
[80ddbd0]426        """
427        if self.parent is not None:
[e767897]428            wx.PostEvent(self.parent,
[6605880]429                         NewBatchEvent(enable=True))
[e767897]430
431    def _get_data_selection(self, event):
[176fbf1]432        """
[6605880]433            Get data selection from the right click
434            :param event: UI event
[176fbf1]435        """
[8ae522c]436        data = None
[c8e1996]437        # selection = event.GetSelection()
[176fbf1]438        id, _, _ = self.FindFocus().GetSelection().GetData()
439        data_list, theory_list = \
[c8e1996]440            self.parent.get_data_manager().get_by_id(id_list=[id])
[176fbf1]441        if data_list:
442            data = data_list.values()[0]
[c8e1996]443        if data is None:
[176fbf1]444            data = theory_list.values()[0][0]
445        return data
[e767897]446
[bf39777]447    def on_edit_data(self, event):
448        """
449        Pop Up Data Editor
450        """
[176fbf1]451        data = self._get_data_selection(event)
[d85c194]452        from sas.sasgui.guiframe.local_perspectives.plotting.masking \
[5cf5f51]453            import MaskPanel as MaskDialog
[e767897]454
455        panel = MaskDialog(parent=self.parent, base=self,
[7434020]456                           data=data, id=wx.NewId())
[5cf5f51]457        panel.ShowModal()
[e767897]458
[7434020]459    def on_plot_3d(self, event):
460        """
461        Frozen image of 3D
462        """
463        data = self._get_data_selection(event)
[d85c194]464        from sas.sasgui.guiframe.local_perspectives.plotting.masking \
[c8e1996]465            import FloatPanel as Float3dDialog
[e767897]466
467        panel = Float3dDialog(base=self, data=data,
[7434020]468                              dimension=3, id=wx.NewId())
[e767897]469        panel.ShowModal()
470
[7434020]471    def on_quick_plot(self, event):
472        """
473        Frozen plot
474        """
475        data = self._get_data_selection(event)
476        if data.__class__.__name__ == "Data2D":
477            dimension = 2
478        else:
[e767897]479            dimension = 1
[c8e1996]480        # panel = QucikPlotDialog(base=self, data=data,
[318b5bbb]481        #                        dimension=dimension, id=wx.NewId())
482        frame = QucikPlotDialog(self, -1, "Plot " + data.name, 'log_{10}')
483        self.parent.put_icon(frame)
484        frame.add_plot(data)
[c8e1996]485        # frame.SetTitle(title)
[318b5bbb]486        frame.Show(True)
487        frame.SetFocus()
[c8e1996]488        # panel.ShowModal()
[e767897]489
[0aca693]490    def on_data_info(self, event):
491        """
492        Data Info panel
493        """
494        data = self._get_data_selection(event)
495        if data.__class__.__name__ == "Data2D":
496            self.parent.show_data2d(data, data.name)
497        else:
498            self.parent.show_data1d(data, data.name)
[e767897]499
[176fbf1]500    def on_save_as(self, event):
501        """
502        Save data as a file
503        """
504        data = self._get_data_selection(event)
[c8e1996]505        # path = None
[176fbf1]506        default_name = data.name
507        if default_name.count('.') > 0:
508            default_name = default_name.split('.')[0]
509        default_name += "_out"
[c8e1996]510        if self.parent is not None:
[176fbf1]511            if issubclass(data.__class__, Data1D):
512                self.parent.save_data1d(data, default_name)
513            elif issubclass(data.__class__, Data2D):
514                self.parent.save_data2d(data, default_name)
515            else:
516                print "unable to save this type of data"
[e767897]517
[91bdf87]518    def layout_data_list(self):
[bffa3d0]519        """
520        Add a listcrtl in the panel
521        """
[8fa53f7]522        # Add splitter
523        w, h = self.parent.GetSize()
524        splitter = wx.SplitterWindow(self)
525        splitter.SetMinimumPaneSize(50)
526        splitter.SetSashGravity(1.0)
527
528        file_sizer = wx.BoxSizer(wx.VERTICAL)
529        file_sizer.SetMinSize(wx.Size(w/13, h*2/5))
530        theory_sizer = wx.BoxSizer(wx.VERTICAL)
531        theory_sizer.SetMinSize(wx.Size(w/13, h*2/5))
532
[66aeb15]533        self.tree_ctrl = DataTreeCtrl(parent=splitter,
534                                      style=wx.SUNKEN_BORDER,
535                                      root="Available Data")
[8fa53f7]536
[bffa3d0]537        self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
[176fbf1]538        self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_MENU, self.on_right_click_data)
[c8e1996]539        # Create context menu for page
[bf39777]540        self.data_menu = wx.Menu()
541        id = wx.NewId()
[0aca693]542        name = "Data Info"
543        msg = "Show Data Info"
544        self.data_menu.Append(id, name, msg)
545        wx.EVT_MENU(self, id, self.on_data_info)
[e767897]546
[0aca693]547        id = wx.NewId()
[176fbf1]548        name = "Save As"
549        msg = "Save Theory/Data as a file"
[bf39777]550        self.data_menu.Append(id, name, msg)
[176fbf1]551        wx.EVT_MENU(self, id, self.on_save_as)
[e767897]552
[5e5704d]553        quickplot_id = wx.NewId()
[7434020]554        name = "Quick Plot"
555        msg = "Plot the current Data"
[5e5704d]556        self.data_menu.Append(quickplot_id, name, msg)
557        wx.EVT_MENU(self, quickplot_id, self.on_quick_plot)
[e767897]558
[7434020]559        self.plot3d_id = wx.NewId()
560        name = "Quick 3DPlot (Slow)"
561        msg = "Plot3D the current 2D Data"
562        self.data_menu.Append(self.plot3d_id, name, msg)
563        wx.EVT_MENU(self, self.plot3d_id, self.on_plot_3d)
[e767897]564
[176fbf1]565        self.editmask_id = wx.NewId()
566        name = "Edit Mask"
567        msg = "Edit Mask for the current 2D Data"
568        self.data_menu.Append(self.editmask_id, name, msg)
569        wx.EVT_MENU(self, self.editmask_id, self.on_edit_data)
[e767897]570
[8fa53f7]571        self.tree_ctrl_theory = DataTreeCtrl(parent=splitter,
[66aeb15]572                                             style=wx.SUNKEN_BORDER,
573                                             root="Available Theory")
[e767897]574        self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_CHECKING,
[c8e1996]575                                   self.on_check_item)
[e767897]576        self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_MENU,
[176fbf1]577                                   self.on_right_click_theory)
[8fa53f7]578        splitter.SplitHorizontally(self.tree_ctrl, self.tree_ctrl_theory)
579        self.sizer1.Add(splitter, 1, wx.EXPAND | wx.ALL, 10)
[e767897]580
[176fbf1]581    def on_right_click_theory(self, event):
582        """
583        On click theory data
584        """
[c668b1b]585        try:
[a8db60c]586            id, data_class_name, _ = \
587                            self.tree_ctrl_theory.GetSelection().GetData()
[d4d4c8a]588            _, _ = self.parent.get_data_manager().get_by_id(id_list=[id])
[c668b1b]589        except:
590            return
[176fbf1]591        if self.data_menu is not None:
[a8db60c]592            menu_enable = (data_class_name == "Data2D")
[176fbf1]593            self.data_menu.Enable(self.editmask_id, False)
[a8db60c]594            self.data_menu.Enable(self.plot3d_id, menu_enable)
[e767897]595            self.PopupMenu(self.data_menu)
596
[176fbf1]597    def on_right_click_data(self, event):
[bf39777]598        """
599        Allow Editing Data
600        """
[c8e1996]601        # selection = event.GetSelection()
[176fbf1]602        is_data = True
603        try:
604            id, data_class_name, _ = self.tree_ctrl.GetSelection().GetData()
605            data_list, _ = \
[c8e1996]606                self.parent.get_data_manager().get_by_id(id_list=[id])
[176fbf1]607            if not data_list:
608                is_data = False
609        except:
610            return
611        if self.data_menu is not None:
[7434020]612            menu_enable = (data_class_name == "Data2D")
613            maskmenu_enable = (menu_enable and is_data)
614            self.data_menu.Enable(self.editmask_id, maskmenu_enable)
615            self.data_menu.Enable(self.plot3d_id, menu_enable)
[e767897]616            self.PopupMenu(self.data_menu)
617
618    def onContextMenu(self, event):
[3c44c66]619        """
[3feed3e]620        Retrieve the state selected state
[3c44c66]621        """
[3feed3e]622        # Skipping the save state functionality for release 0.9.0
[c8e1996]623        # return
[3feed3e]624        pos = event.GetPosition()
625        pos = self.ScreenToClient(pos)
[e767897]626        self.PopupMenu(self.popUpMenu, pos)
627
[3feed3e]628    def on_check_item(self, event):
[3c44c66]629        """
[5e5704d]630        On check item
[3c44c66]631        """
[3feed3e]632        item = event.GetItem()
[e767897]633        item.Check(not item.IsChecked())
[1e3394f]634        self.enable_append()
635        self.enable_freeze()
636        self.enable_plot()
637        self.enable_import()
[248b918]638        self.enable_remove()
[ee2b492]639        event.Skip()
[e767897]640
[600eca2]641    def fill_cbox_analysis(self, plugin):
[ee2b492]642        """
[600eca2]643        fill the combobox with analysis name
[ee2b492]644        """
[600eca2]645        self.list_of_perspective = plugin
646        if self.parent is None or \
647            not hasattr(self.parent, "get_current_perspective") or \
[c8e1996]648                        len(self.list_of_perspective) == 0:
[600eca2]649            return
[c8e1996]650        if self.parent is not None and self.perspective_cbox is not None:
[600eca2]651            for plug in self.list_of_perspective:
652                if plug.get_perspective():
653                    self.perspective_cbox.Append(plug.sub_menu, plug)
[e767897]654
[600eca2]655            curr_pers = self.parent.get_current_perspective()
[911cae5]656            if curr_pers:
657                self.perspective_cbox.SetStringSelection(curr_pers.sub_menu)
[1ba8201d]658                self.enable_import()
[e767897]659
[3feed3e]660    def load_data_list(self, list):
[3c44c66]661        """
[c70eb7c]662        add need data with its theory under the tree
[3c44c66]663        """
[61ffd1e]664        if list:
665            for state_id, dstate in list.iteritems():
666                data = dstate.get_data()
667                theory_list = dstate.get_theory()
668                if data is not None:
[755cac4]669                    data_name = str(data.name)
[b2aef1c]670                    data_title = str(data.title)
671                    data_run = str(data.run)
[61ffd1e]672                    data_class = data.__class__.__name__
[e767897]673                    path = dstate.get_path()
[61ffd1e]674                    process_list = data.process
675                    data_id = data.id
[76703da]676                    s_path = str(path)
[61ffd1e]677                    if state_id not in self.list_cb_data:
[c8e1996]678                        # new state
[5e5704d]679                        data_c = self.tree_ctrl.InsertItem(self.tree_ctrl.root,
[c8e1996]680                                                           0, data_name,
681                                                           ct_type=1,
[5e5704d]682                                        data=(data_id, data_class, state_id))
[61ffd1e]683                        data_c.Check(True)
684                        d_i_c = self.tree_ctrl.AppendItem(data_c, 'Info')
[e767897]685                        d_t_c = self.tree_ctrl.AppendItem(d_i_c,
[c8e1996]686                                                          'Title: %s' %
687                                                          data_title)
[e767897]688                        r_n_c = self.tree_ctrl.AppendItem(d_i_c,
[c8e1996]689                                                          'Run: %s' % data_run)
[e767897]690                        i_c_c = self.tree_ctrl.AppendItem(d_i_c,
[c8e1996]691                                                          'Type: %s' %
692                                                          data_class)
[61ffd1e]693                        p_c_c = self.tree_ctrl.AppendItem(d_i_c,
[c8e1996]694                                                          "Path: '%s'" % s_path)
[61ffd1e]695                        d_p_c = self.tree_ctrl.AppendItem(d_i_c, 'Process')
[e767897]696
[61ffd1e]697                        for process in process_list:
[c8e1996]698                            process_str = str(process).replace('\n', ' ')
699                            if len(process_str) > 20:
700                                process_str = process_str[:20] + ' [...]'
[5e5704d]701                            self.tree_ctrl.AppendItem(d_p_c, process_str)
[e767897]702                        theory_child = self.tree_ctrl.AppendItem(data_c,
[5e5704d]703                                                                 "THEORIES")
[e767897]704                        self.list_cb_data[state_id] = [data_c,
[61ffd1e]705                                                       d_i_c,
[b2aef1c]706                                                       d_t_c,
707                                                       r_n_c,
[61ffd1e]708                                                       i_c_c,
[5e5704d]709                                                       p_c_c,
710                                                       d_p_c,
711                                                       theory_child]
[61ffd1e]712                    else:
[c8e1996]713                        data_ctrl_list = self.list_cb_data[state_id]
714                        # This state is already display replace it contains
[d4d4c8a]715                        data_c, d_i_c, d_t_c, r_n_c,  i_c_c, p_c_c, d_p_c, _ \
[5e5704d]716                                = data_ctrl_list
[e767897]717                        self.tree_ctrl.SetItemText(data_c, data_name)
[61ffd1e]718                        temp = (data_id, data_class, state_id)
[e767897]719                        self.tree_ctrl.SetItemPyData(data_c, temp)
720                        self.tree_ctrl.SetItemText(i_c_c,
[5e5704d]721                                                   'Type: %s' % data_class)
[e767897]722                        self.tree_ctrl.SetItemText(p_c_c,
723                                                   'Path: %s' % s_path)
724                        self.tree_ctrl.DeleteChildren(d_p_c)
[61ffd1e]725                        for process in process_list:
[3a5f7c8]726                            if not process.is_empty():
727                                _ = self.tree_ctrl.AppendItem(d_p_c,
[c8e1996]728                                                    process.single_line_desc())
[98fdccd]729                wx.CallAfter(self.append_theory, state_id, theory_list)
[0b705915]730            # Sort by data name
731            if self.tree_ctrl.root:
[e767897]732                self.tree_ctrl.SortChildren(self.tree_ctrl.root)
[248b918]733        self.enable_remove()
[f7d0b74]734        self.enable_import()
735        self.enable_plot()
736        self.enable_freeze()
[61ffd1e]737        self.enable_selection()
[e767897]738
[48665ed]739    def _uncheck_all(self):
740        """
741        Uncheck all check boxes
742        """
743        for item in self.list_cb_data.values():
[5e5704d]744            data_ctrl, _, _, _, _, _, _, _ = item
[e767897]745            self.tree_ctrl.CheckItem(data_ctrl, False)
[1e3394f]746        self.enable_append()
747        self.enable_freeze()
748        self.enable_plot()
749        self.enable_import()
[248b918]750        self.enable_remove()
[e767897]751
[91bdf87]752    def append_theory(self, state_id, theory_list):
[bffa3d0]753        """
754        append theory object under data from a state of id = state_id
755        replace that theory if  already displayed
756        """
757        if not theory_list:
[e767897]758            return
[bffa3d0]759        if state_id not in self.list_cb_data.keys():
760            root = self.tree_ctrl_theory.root
[91bdf87]761            tree = self.tree_ctrl_theory
[bffa3d0]762        else:
763            item = self.list_cb_data[state_id]
[b2aef1c]764            data_c, _, _, _, _, _, _, _ = item
[bffa3d0]765            root = data_c
[91bdf87]766            tree = self.tree_ctrl
[bffa3d0]767        if root is not None:
[e767897]768            wx.CallAfter(self.append_theory_helper, tree=tree, root=root,
769                                       state_id=state_id,
[bffa3d0]770                                       theory_list=theory_list)
[e767897]771
[91bdf87]772    def append_theory_helper(self, tree, root, state_id, theory_list):
[71bd773]773        """
[5e5704d]774        Append theory helper
[71bd773]775        """
776        if state_id in self.list_cb_theory.keys():
[c8e1996]777            # update current list of theory for this data
[71bd773]778            theory_list_ctrl = self.list_cb_theory[state_id]
[c70eb7c]779
780            for theory_id, item in theory_list.iteritems():
[5e5704d]781                theory_data, _ = item
[c70eb7c]782                if theory_data is None:
783                    name = "Unknown"
784                    theory_class = "Unknown"
785                    theory_id = "Unknown"
786                    temp = (None, None, None)
787                else:
788                    name = theory_data.name
789                    theory_class = theory_data.__class__.__name__
790                    theory_id = theory_data.id
[c8e1996]791                    # if theory_state is not None:
[ee2b492]792                    #    name = theory_state.model.name
[c70eb7c]793                    temp = (theory_id, theory_class, state_id)
794                if theory_id not in theory_list_ctrl:
[c8e1996]795                    # add new theory
[91bdf87]796                    t_child = tree.AppendItem(root,
[c70eb7c]797                                                    name, ct_type=1, data=temp)
[91bdf87]798                    t_i_c = tree.AppendItem(t_child, 'Info')
[e767897]799                    i_c_c = tree.AppendItem(t_i_c,
[c70eb7c]800                                                  'Type: %s' % theory_class)
[91bdf87]801                    t_p_c = tree.AppendItem(t_i_c, 'Process')
[e767897]802
[c70eb7c]803                    for process in theory_data.process:
[5e5704d]804                        tree.AppendItem(t_p_c, process.__str__())
[e767897]805                    theory_list_ctrl[theory_id] = [t_child,
806                                                   i_c_c,
[c70eb7c]807                                                   t_p_c]
808                else:
[c8e1996]809                    # replace theory
[c70eb7c]810                    t_child, i_c_c, t_p_c = theory_list_ctrl[theory_id]
[e767897]811                    tree.SetItemText(t_child, name)
812                    tree.SetItemPyData(t_child, temp)
813                    tree.SetItemText(i_c_c, 'Type: %s' % theory_class)
814                    tree.DeleteChildren(t_p_c)
[c70eb7c]815                    for process in theory_data.process:
[5e5704d]816                        tree.AppendItem(t_p_c, process.__str__())
[e767897]817
[c70eb7c]818        else:
[c8e1996]819            # data didn't have a theory associated it before
[c70eb7c]820            theory_list_ctrl = {}
821            for theory_id, item in theory_list.iteritems():
[d4d4c8a]822                theory_data, _ = item
[c70eb7c]823                if theory_data is not None:
[e88ebfd]824                    name = theory_data.name
[c70eb7c]825                    theory_class = theory_data.__class__.__name__
[e88ebfd]826                    theory_id = theory_data.id
[c8e1996]827                    # if theory_state is not None:
[e767897]828                    #    name = theory_state.model.name
[e88ebfd]829                    temp = (theory_id, theory_class, state_id)
[91bdf87]830                    t_child = tree.AppendItem(root,
[e767897]831                            name, ct_type=1,
[c70eb7c]832                            data=(theory_data.id, theory_class, state_id))
[91bdf87]833                    t_i_c = tree.AppendItem(t_child, 'Info')
[e767897]834                    i_c_c = tree.AppendItem(t_i_c,
[c70eb7c]835                                                  'Type: %s' % theory_class)
[91bdf87]836                    t_p_c = tree.AppendItem(t_i_c, 'Process')
[e767897]837
[c70eb7c]838                    for process in theory_data.process:
[5e5704d]839                        tree.AppendItem(t_p_c, process.__str__())
[e767897]840
[c70eb7c]841                    theory_list_ctrl[theory_id] = [t_child, i_c_c, t_p_c]
[c8e1996]842                # self.list_cb_theory[data_id] = theory_list_ctrl
[71bd773]843                self.list_cb_theory[state_id] = theory_list_ctrl
[e767897]844
[3feed3e]845    def set_data_helper(self):
[3c44c66]846        """
[5e5704d]847        Set data helper
[3c44c66]848        """
[3feed3e]849        data_to_plot = []
[e88ebfd]850        state_to_plot = []
851        theory_to_plot = []
[c70eb7c]852        for value in self.list_cb_data.values():
[b2aef1c]853            item, _, _, _, _, _, _,  _ = value
[3feed3e]854            if item.IsChecked():
[3658717e]855                data_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
856                data_to_plot.append(data_id)
857                if state_id not in state_to_plot:
858                    state_to_plot.append(state_id)
[e767897]859
[c70eb7c]860        for theory_dict in self.list_cb_theory.values():
[5e5704d]861            for _, value in theory_dict.iteritems():
[c70eb7c]862                item, _, _ = value
863                if item.IsChecked():
[e88ebfd]864                    theory_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
[c70eb7c]865                    theory_to_plot.append(theory_id)
[e88ebfd]866                    if state_id not in state_to_plot:
867                        state_to_plot.append(state_id)
868        return data_to_plot, theory_to_plot, state_to_plot
[e767897]869
[c70eb7c]870    def remove_by_id(self, id):
871        """
[5e5704d]872        Remove_dat by id
[c70eb7c]873        """
874        for item in self.list_cb_data.values():
[5e5704d]875            data_c, _, _, _, _, _,  _, _ = item
[e767897]876            data_id, _, state_id = self.tree_ctrl.GetItemPyData(data_c)
[c70eb7c]877            if id == data_id:
878                self.tree_ctrl.Delete(data_c)
879                del self.list_cb_data[state_id]
880                del self.list_cb_theory[data_id]
[e767897]881
[2a62d5c]882    def load_error(self, error=None):
883        """
884        Pop up an error message.
[e767897]885
[2a62d5c]886        :param error: details error message to be displayed
887        """
[8cb8c89]888        if error is not None or str(error).strip() != "":
[e767897]889            dial = wx.MessageDialog(self.parent, str(error),
[5e5704d]890                                    'Error Loading File',
891                                    wx.OK | wx.ICON_EXCLAMATION)
[e767897]892            dial.ShowModal()
893
[2a62d5c]894    def _load_data(self, event):
895        """
[a03d419]896        send an event to the parent to trigger load from plugin module
[2a62d5c]897        """
898        if self.parent is not None:
[a03d419]899            wx.PostEvent(self.parent, NewLoadDataEvent())
[e767897]900
[c8e1996]901    def on_remove(self, event, prompt=True):
[18ec684]902        """
[3658717e]903        Get a list of item checked and remove them from the treectrl
[e767897]904        Ask the parent to remove reference to this item
[18ec684]905        """
[c8e1996]906        if prompt:
[998ca90]907            msg = "This operation will delete the data sets checked "
908            msg += "and all the dependents."
[c8e1996]909            msg_box = wx.MessageDialog(None, msg, 'Warning', wx.OK|wx.CANCEL)
910            if msg_box.ShowModal() != wx.ID_OK:
911                return
[e767897]912
[665c083]913        data_to_remove, theory_to_remove, _ = self.set_data_helper()
914        data_key = []
915        theory_key = []
[c8e1996]916        # remove  data from treectrl
[3658717e]917        for d_key, item in self.list_cb_data.iteritems():
[5e5704d]918            data_c, _, _, _,  _, _, _, _ = item
[665c083]919            if data_c.IsChecked():
920                self.tree_ctrl.Delete(data_c)
[3658717e]921                data_key.append(d_key)
922                if d_key in self.list_cb_theory.keys():
923                    theory_list_ctrl = self.list_cb_theory[d_key]
924                    theory_to_remove += theory_list_ctrl.keys()
[e767897]925        # Remove theory from treectrl
[5e5704d]926        for _, theory_dict in self.list_cb_theory.iteritems():
[c8e1996]927            for key, value in theory_dict.iteritems():
[665c083]928                item, _, _ = value
929                if item.IsChecked():
[e26d0db]930                    try:
931                        self.tree_ctrl.Delete(item)
932                    except:
933                        pass
[665c083]934                    theory_key.append(key)
[e767897]935
[c8e1996]936        # Remove data and related theory references
[665c083]937        for key in data_key:
938            del self.list_cb_data[key]
[3658717e]939            if key in theory_key:
940                del self.list_cb_theory[key]
[c8e1996]941        # remove theory  references independently of data
[665c083]942        for key in theory_key:
[d4d4c8a]943            for _, theory_dict in self.list_cb_theory.iteritems():
[71bd773]944                if key in theory_dict:
[c8e1996]945                    for key, value in theory_dict.iteritems():
[e26d0db]946                        item, _, _ = value
947                        if item.IsChecked():
948                            try:
949                                self.tree_ctrl_theory.Delete(item)
950                            except:
951                                pass
[71bd773]952                    del theory_dict[key]
[e767897]953
[18ec684]954        self.parent.remove_data(data_id=data_to_remove,
[665c083]955                                  theory_id=theory_to_remove)
[248b918]956        self.enable_remove()
[f7d0b74]957        self.enable_freeze()
[e26d0db]958        self.enable_remove_plot()
[e767897]959
[3feed3e]960    def on_import(self, event=None):
[3c44c66]961        """
[3feed3e]962        Get all select data and set them to the current active perspetive
[3c44c66]963        """
[c8e1996]964        if event is not None:
[3603b2e]965            event.Skip()
[e88ebfd]966        data_id, theory_id, state_id = self.set_data_helper()
[248b918]967        temp = data_id + state_id
968        self.parent.set_data(data_id=temp, theory_id=theory_id)
[e767897]969
[213892bc]970    def on_append_plot(self, event=None):
971        """
972        append plot to plot panel on focus
973        """
[0a2fdca]974        self._on_plot_selection()
[e88ebfd]975        data_id, theory_id, state_id = self.set_data_helper()
[e767897]976        self.parent.plot_data(data_id=data_id,
[e88ebfd]977                              state_id=state_id,
978                              theory_id=theory_id,
979                              append=True)
[e767897]980
[3feed3e]981    def on_plot(self, event=None):
[3c44c66]982        """
[3feed3e]983        Send a list of data names to plot
[3c44c66]984        """
[e88ebfd]985        data_id, theory_id, state_id = self.set_data_helper()
[e767897]986        self.parent.plot_data(data_id=data_id,
[e88ebfd]987                              state_id=state_id,
988                              theory_id=theory_id,
989                              append=False)
[e26d0db]990        self.enable_remove_plot()
[e767897]991
[1b1bbf9]992    def on_close_page(self, event=None):
993        """
994        On close
995        """
[c8e1996]996        if event is not None:
[1b1bbf9]997            event.Skip()
998        # send parent to update menu with no show nor hide action
999        self.parent.show_data_panel(action=False)
[e767897]1000
[c70eb7c]1001    def on_freeze(self, event):
1002        """
[2719255]1003        On freeze to make a theory to a data set
[c70eb7c]1004        """
[e88ebfd]1005        _, theory_id, state_id = self.set_data_helper()
[2719255]1006        if len(theory_id) > 0:
1007            self.parent.freeze(data_id=state_id, theory_id=theory_id)
1008            msg = "Freeze Theory:"
1009            msg += " The theory(s) copied to the Data box as a data set."
1010        else:
1011            msg = "Freeze Theory: Requires at least one theory checked."
1012        wx.PostEvent(self.parent, StatusEvent(status=msg))
[e767897]1013
[3feed3e]1014    def set_active_perspective(self, name):
[3c44c66]1015        """
[3feed3e]1016        set the active perspective
[3c44c66]1017        """
[600eca2]1018        self.perspective_cbox.SetStringSelection(name)
[2a62d5c]1019        self.enable_import()
[e767897]1020
[13a63ab]1021    def _on_delete_plot_panel(self, event):
1022        """
[e767897]1023        get an event with attribute name and caption to delete existing name
[13a63ab]1024        from the combobox of the current panel
1025        """
[c8e1996]1026        # name = event.name
[13a63ab]1027        caption = event.caption
1028        if self.cb_plotpanel is not None:
[e767897]1029            pos = self.cb_plotpanel.FindString(str(caption))
[13a63ab]1030            if pos != wx.NOT_FOUND:
1031                self.cb_plotpanel.Delete(pos)
1032        self.enable_append()
[e767897]1033
[83a75c5]1034    def set_panel_on_focus(self, name=None):
[3c44c66]1035        """
[3feed3e]1036        set the plot panel on focus
[3c44c66]1037        """
[f22d219]1038        if self.cb_plotpanel and self.cb_plotpanel.IsBeingDeleted():
1039            return
[5e5704d]1040        for _, value in self.parent.plot_panels.iteritems():
[0a2fdca]1041            name_plot_panel = str(value.window_caption)
1042            if name_plot_panel not in self.cb_plotpanel.GetItems():
1043                self.cb_plotpanel.Append(name_plot_panel, value)
[c8e1996]1044            if name is not None and name == name_plot_panel:
[83a75c5]1045                self.cb_plotpanel.SetStringSelection(name_plot_panel)
1046                break
[f7d0b74]1047        self.enable_append()
[e26d0db]1048        self.enable_remove_plot()
[e767897]1049
[ae84427]1050    def set_plot_unfocus(self):
1051        """
1052        Unfocus plot
1053        """
1054        return
[e767897]1055
[600eca2]1056    def _on_perspective_selection(self, event=None):
1057        """
1058        select the current perspective for guiframe
1059        """
1060        selection = self.perspective_cbox.GetSelection()
1061        if self.perspective_cbox.GetValue() != 'None':
1062            perspective = self.perspective_cbox.GetClientData(selection)
1063            perspective.on_perspective(event=None)
[e4d790f]1064            self.parent.check_multimode(perspective=perspective)
[e767897]1065
[e26d0db]1066    def _on_plot_selection(self, event=None):
[0a2fdca]1067        """
1068        On source combobox selection
1069        """
[c8e1996]1070        if event is not None:
[0a2fdca]1071            combo = event.GetEventObject()
[b113128]1072            event.Skip()
[0a2fdca]1073        else:
1074            combo = self.cb_plotpanel
1075        selection = combo.GetSelection()
1076
1077        if combo.GetValue() != 'None':
1078            panel = combo.GetClientData(selection)
[e767897]1079            self.parent.on_set_plot_focus(panel)
1080
[e26d0db]1081    def on_close_plot(self, event):
1082        """
1083        clseo the panel on focus
[e767897]1084        """
[e26d0db]1085        self.enable_append()
1086        selection = self.cb_plotpanel.GetSelection()
1087        if self.cb_plotpanel.GetValue() != 'None':
1088            panel = self.cb_plotpanel.GetClientData(selection)
1089            if self.parent is not None and panel is not None:
[e767897]1090                wx.PostEvent(self.parent,
[e26d0db]1091                             NewPlotEvent(group_id=panel.group_id,
1092                                          action="delete"))
1093        self.enable_remove_plot()
[e767897]1094
[ae84427]1095    def set_frame(self, frame):
1096        """
1097        """
1098        self.frame = frame
[e767897]1099
[ae84427]1100    def get_frame(self):
1101        """
1102        """
[e767897]1103        return self.frame
1104
[1941e6a]1105    def on_help(self, event):
1106        """
1107        Bring up the data manager Documentation whenever
1108        the HELP button is clicked.
1109
1110        Calls DocumentationWindow with the path of the location within the
1111        documentation tree (after /doc/ ....".  Note that when using old
1112        versions of Wx (before 2.9) and thus not the release version of
1113        installers, the help comes up at the top level of the file as
1114        webbrowser does not pass anything past the # to the browser when it is
1115        running "file:///...."
1116
[c8e1996]1117    :param event: Triggers on clicking the help button
[1941e6a]1118    """
1119
1120        #import documentation window here to avoid circular imports
1121        #if put at top of file with rest of imports.
1122        from documentation_window import DocumentationWindow
1123
1124        _TreeLocation = "user/sasgui/guiframe/data_explorer_help.html"
1125        _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",
1126                                          "Data Explorer Help")
1127
[af72b2e]1128    def on_close(self, event):
1129        """
1130        On close event
1131        """
1132        self.parent.show_data_panel(event)
[e767897]1133
[ae84427]1134    def set_schedule_full_draw(self, panel=None, func='del'):
1135        """
1136        Send full draw to guimanager
1137        """
1138        self.parent.set_schedule_full_draw(panel, func)
[e767897]1139
[e26d0db]1140    def enable_remove_plot(self):
1141        """
1142        enable remove plot button if there is a plot panel on focus
1143        """
[c5a769e]1144        pass
1145        #if self.cb_plotpanel.GetCount() == 0:
1146        #    self.bt_close_plot.Disable()
1147        #else:
1148        #    self.bt_close_plot.Enable()
[e767897]1149
[2a62d5c]1150    def enable_remove(self):
1151        """
1152        enable or disable remove button
1153        """
1154        n_t = self.tree_ctrl.GetCount()
1155        n_t_t = self.tree_ctrl_theory.GetCount()
1156        if n_t + n_t_t <= 0:
1157            self.bt_remove.Disable()
1158        else:
1159            self.bt_remove.Enable()
[e767897]1160
[2a62d5c]1161    def enable_import(self):
1162        """
1163        enable or disable send button
1164        """
[61ffd1e]1165        n_t = 0
[c8e1996]1166        if self.tree_ctrl is not None:
[61ffd1e]1167            n_t = self.tree_ctrl.GetCount()
[600eca2]1168        if n_t > 0 and len(self.list_of_perspective) > 0:
1169            self.bt_import.Enable()
1170        else:
[2a62d5c]1171            self.bt_import.Disable()
[600eca2]1172        if len(self.list_of_perspective) <= 0 or \
1173            self.perspective_cbox.GetValue()  in ["None",
1174                                                "No Active Application"]:
1175            self.perspective_cbox.Disable()
[2a62d5c]1176        else:
[600eca2]1177            self.perspective_cbox.Enable()
[e767897]1178
[f7d0b74]1179    def enable_plot(self):
1180        """
1181        enable or disable plot button
1182        """
[e767897]1183        n_t = 0
[600eca2]1184        n_t_t = 0
[c8e1996]1185        if self.tree_ctrl is not None:
[600eca2]1186            n_t = self.tree_ctrl.GetCount()
[c8e1996]1187        if self.tree_ctrl_theory is not None:
[600eca2]1188            n_t_t = self.tree_ctrl_theory.GetCount()
[f7d0b74]1189        if n_t + n_t_t <= 0:
1190            self.bt_plot.Disable()
1191        else:
1192            self.bt_plot.Enable()
[5e8e615]1193        self.enable_append()
[e767897]1194
[f7d0b74]1195    def enable_append(self):
1196        """
1197        enable or disable append button
1198        """
[e767897]1199        n_t = 0
[600eca2]1200        n_t_t = 0
[c8e1996]1201        if self.tree_ctrl is not None:
[600eca2]1202            n_t = self.tree_ctrl.GetCount()
[c8e1996]1203        if self.tree_ctrl_theory is not None:
[600eca2]1204            n_t_t = self.tree_ctrl_theory.GetCount()
[e767897]1205        if n_t + n_t_t <= 0:
[f7d0b74]1206            self.bt_append_plot.Disable()
[600eca2]1207            self.cb_plotpanel.Disable()
[5e8e615]1208        elif self.cb_plotpanel.GetCount() <= 0:
[5e5704d]1209            self.cb_plotpanel.Disable()
1210            self.bt_append_plot.Disable()
[f7d0b74]1211        else:
1212            self.bt_append_plot.Enable()
[df8cc63]1213            self.cb_plotpanel.Enable()
[e767897]1214
[1e3394f]1215    def check_theory_to_freeze(self):
1216        """
[d4d4c8a]1217        Check_theory_to_freeze
[1e3394f]1218        """
[f7d0b74]1219    def enable_freeze(self):
1220        """
1221        enable or disable the freeze button
1222        """
[61ffd1e]1223        n_t_t = 0
1224        n_l = 0
[c8e1996]1225        if self.tree_ctrl_theory is not None:
[61ffd1e]1226            n_t_t = self.tree_ctrl_theory.GetCount()
[f7d0b74]1227        n_l = len(self.list_cb_theory)
[5e8e615]1228        if (n_t_t + n_l > 0):
[f7d0b74]1229            self.bt_freeze.Enable()
[1e3394f]1230        else:
1231            self.bt_freeze.Disable()
[e767897]1232
[61ffd1e]1233    def enable_selection(self):
1234        """
1235        enable or disable combobo box selection
1236        """
1237        n_t = 0
1238        n_t_t = 0
[c8e1996]1239        if self.tree_ctrl is not None:
[61ffd1e]1240            n_t = self.tree_ctrl.GetCount()
[c8e1996]1241        if self.tree_ctrl_theory is not None:
[61ffd1e]1242            n_t_t = self.tree_ctrl_theory.GetCount()
[c8e1996]1243        if n_t + n_t_t > 0 and self.selection_cbox is not None:
[61ffd1e]1244            self.selection_cbox.Enable()
1245        else:
1246            self.selection_cbox.Disable()
[e767897]1247
[a03d419]1248    def show_data_button(self):
1249        """
[e767897]1250        show load data and remove data button if
[a03d419]1251        dataloader on else hide them
1252        """
1253        try:
1254            gui_style = self.parent.get_style()
1255            style = gui_style & GUIFRAME.DATALOADER_ON
[e767897]1256            if style == GUIFRAME.DATALOADER_ON:
[a03d419]1257                #self.bt_remove.Show(True)
[e767897]1258                self.bt_add.Show(True)
[a03d419]1259            else:
1260                #self.bt_remove.Hide()
1261                self.bt_add.Hide()
[e767897]1262        except:
[a03d419]1263            #self.bt_remove.Hide()
[e767897]1264            self.bt_add.Hide()
1265
[60fff67]1266
1267WIDTH = 400
1268HEIGHT = 300
1269
1270
1271class DataDialog(wx.Dialog):
1272    """
1273    Allow file selection at loading time
1274    """
1275    def __init__(self, data_list, parent=None, text='', *args, **kwds):
1276        wx.Dialog.__init__(self, parent, *args, **kwds)
1277        self.SetTitle("Data Selection")
1278        self.SetSize((WIDTH, HEIGHT))
1279        self.list_of_ctrl = []
1280        if not data_list:
[e767897]1281            return
[60fff67]1282        self._sizer_main = wx.BoxSizer(wx.VERTICAL)
1283        self._sizer_txt = wx.BoxSizer(wx.VERTICAL)
1284        self._sizer_button = wx.BoxSizer(wx.HORIZONTAL)
1285        self.sizer = wx.GridBagSizer(5, 5)
1286        self._panel = ScrolledPanel(self, style=wx.RAISED_BORDER,
1287                               size=(WIDTH-20, HEIGHT-50))
1288        self._panel.SetupScrolling()
1289        self.__do_layout(data_list, text=text)
[e767897]1290
[60fff67]1291    def __do_layout(self, data_list, text=''):
1292        """
1293        layout the dialog
1294        """
1295        if not data_list or len(data_list) <= 1:
[e767897]1296            return
[c8e1996]1297        # add text
[e767897]1298
[60fff67]1299        text = "Deleting these file reset some panels.\n"
1300        text += "Do you want to proceed?\n"
1301        text_ctrl = wx.StaticText(self, -1, str(text))
1302        self._sizer_txt.Add(text_ctrl)
1303        iy = 0
1304        ix = 0
[c8e1996]1305        # data_count = 0
[60fff67]1306        for (data_name, in_use, sub_menu) in range(len(data_list)):
[c8e1996]1307            if in_use:
[60fff67]1308                ctrl_name = wx.StaticBox(self, -1, str(data_name))
1309                ctrl_in_use = wx.StaticBox(self, -1, " is used by ")
1310                plug_name = str(sub_menu) + "\n"
[c8e1996]1311                # ctrl_sub_menu = wx.StaticBox(self, -1, plug_name)
[60fff67]1312                self.sizer.Add(ctrl_name, (iy, ix),
1313                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1314                ix += 1
1315                self._sizer_button.Add(ctrl_in_use, 1,
1316                                        wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1317                ix += 1
1318                self._sizer_button.Add(plug_name, 1,
1319                                        wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1320            iy += 1
1321        self._panel.SetSizer(self.sizer)
[c8e1996]1322        # add sizer
[60fff67]1323        self._sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1324        button_cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
1325        self._sizer_button.Add(button_cancel, 0,
1326                          wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1327        button_OK = wx.Button(self, wx.ID_OK, "Ok")
1328        button_OK.SetFocus()
1329        self._sizer_button.Add(button_OK, 0,
1330                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1331        static_line = wx.StaticLine(self, -1)
[e767897]1332
[60fff67]1333        self._sizer_txt.Add(self._panel, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
1334        self._sizer_main.Add(self._sizer_txt, 1, wx.EXPAND|wx.ALL, 10)
[e767897]1335        #self._sizer_main.Add(self._data_text_ctrl, 0,
[38226d26]1336        #                     wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
[60fff67]1337        self._sizer_main.Add(static_line, 0, wx.EXPAND, 0)
1338        self._sizer_main.Add(self._sizer_button, 0, wx.EXPAND|wx.ALL, 10)
1339        self.SetSizer(self._sizer_main)
1340        self.Layout()
[e767897]1341
[60fff67]1342    def get_data(self):
1343        """
1344        return the selected data
1345        """
1346        temp = []
1347        for item in self.list_of_ctrl:
1348            cb, data = item
1349            if cb.GetValue():
1350                temp.append(data)
1351        return temp
[e767897]1352
[3c44c66]1353class DataFrame(wx.Frame):
[5e5704d]1354    """
1355    Data Frame
1356    """
[3feed3e]1357    ## Internal name for the AUI manager
1358    window_name = "Data Panel"
1359    ## Title to appear on top of the window
1360    window_caption = "Data Panel"
1361    ## Flag to tell the GUI manager that this panel is not
1362    #  tied to any perspective
1363    ALWAYS_ON = True
[e767897]1364
[5e5704d]1365    def __init__(self, parent=None, owner=None, manager=None, size=(300, 800),
1366                         list_of_perspective=[], list=[], *args, **kwds):
[cc061c3]1367        kwds['size'] = size
[3c44c66]1368        kwds['id'] = -1
[5e5704d]1369        kwds['title'] = "Loaded Data"
[3c44c66]1370        wx.Frame.__init__(self, parent=parent, *args, **kwds)
1371        self.parent = parent
1372        self.owner = owner
[ae84427]1373        self._manager = manager
[e767897]1374        self.panel = DataPanel(parent=self,
[ae84427]1375                               manager=manager,
[32c0841]1376                               list_of_perspective=list_of_perspective)
[e767897]1377
[3feed3e]1378    def load_data_list(self, list=[]):
[3c44c66]1379        """
1380        Fill the list inside its panel
1381        """
[3feed3e]1382        self.panel.load_data_list(list=list)
[e767897]1383
1384
[d85c194]1385from sas.sasgui.guiframe.dataFitting import Theory1D
1386from sas.sasgui.guiframe.data_state import DataState
[5e5704d]1387
[c8e1996]1388
[3feed3e]1389class State():
[5e5704d]1390    """
1391    DataPanel State
1392    """
[3feed3e]1393    def __init__(self):
1394        self.msg = ""
1395    def __str__(self):
1396        self.msg = "model mane : model1\n"
1397        self.msg += "params : \n"
1398        self.msg += "name  value\n"
[dc0cfa4]1399        return self.msg
[e767897]1400
[c8e1996]1401
[71bd773]1402def set_data_state(data=None, path=None, theory=None, state=None):
[5e5704d]1403    """
1404    Set data state
1405    """
[3feed3e]1406    dstate = DataState(data=data)
1407    dstate.set_path(path=path)
[c70eb7c]1408    dstate.set_theory(theory, state)
[e767897]1409
[3feed3e]1410    return dstate
[e767897]1411
[3c44c66]1412if __name__ == "__main__":
[e767897]1413
[3c44c66]1414    app = wx.App()
[3feed3e]1415    try:
[c8e1996]1416        # list_of_perspective = [('perspective2', False), ('perspective1', True)]
[5e5704d]1417        data_list1 = {}
[c70eb7c]1418        # state 1
[5e5704d]1419        data1 = Data2D()
1420        data1.name = "data2"
1421        data1.id = 1
1422        data1.append_empty_process()
1423        process1 = data1.process[len(data1.process)-1]
1424        process1.data = "07/01/2010"
[4cc25e9]1425        theory1 = Data2D()
1426        theory1.id = 34
1427        theory1.name = "theory1"
1428        path1 = "path1"
[5e5704d]1429        state1 = State()
[4cc25e9]1430        data_list1['1'] = set_data_state(data1, path1, theory1, state1)
[c8e1996]1431        # state 2
[5e5704d]1432        data1 = Data2D()
1433        data1.name = "data2"
1434        data1.id = 76
[4cc25e9]1435        theory1 = Data2D()
1436        theory1.id = 78
1437        theory1.name = "CoreShell 07/24/25"
1438        path1 = "path2"
[c8e1996]1439        # state3
[5e5704d]1440        state1 = State()
[4cc25e9]1441        data_list1['2'] = set_data_state(data1, path1, theory1, state1)
[5e5704d]1442        data1 = Data1D()
1443        data1.id = 3
1444        data1.name = "data2"
[4cc25e9]1445        theory1 = Theory1D()
1446        theory1.name = "CoreShell"
1447        theory1.id = 4
1448        theory1.append_empty_process()
1449        process1 = theory1.process[len(theory1.process)-1]
[5e5704d]1450        process1.description = "this is my description"
[4cc25e9]1451        path1 = "path3"
[5e5704d]1452        data1.append_empty_process()
1453        process1 = data1.process[len(data1.process)-1]
1454        process1.data = "07/22/2010"
[4cc25e9]1455        data_list1['4'] = set_data_state(data1, path1, theory1, state1)
[c8e1996]1456        # state 4
[c70eb7c]1457        temp_data_list = {}
[5e5704d]1458        data1.name = "data5 erasing data2"
[4cc25e9]1459        temp_data_list['4'] = set_data_state(data1, path1, theory1, state1)
[c8e1996]1460        # state 5
[5e5704d]1461        data1 = Data2D()
1462        data1.name = "data3"
1463        data1.id = 5
1464        data1.append_empty_process()
[d4d4c8a]1465        process1 = data1.process[len(data1.process)-1]
[5e5704d]1466        process1.data = "07/01/2010"
[4cc25e9]1467        theory1 = Theory1D()
1468        theory1.name = "Cylinder"
1469        path1 = "path2"
[5e5704d]1470        state1 = State()
[4cc25e9]1471        dstate1 = set_data_state(data1, path1, theory1, state1)
1472        theory1 = Theory1D()
1473        theory1.id = 6
1474        theory1.name = "CoreShell"
1475        dstate1.set_theory(theory1)
1476        theory1 = Theory1D()
1477        theory1.id = 6
1478        theory1.name = "CoreShell replacing coreshell in data3"
1479        dstate1.set_theory(theory1)
[d4d4c8a]1480        data_list1['3'] = dstate1
[c70eb7c]1481        #state 6
[4cc25e9]1482        data_list1['6'] = set_data_state(None, path1, theory1, state1)
1483        data_list1['6'] = set_data_state(theory=theory1, state=None)
1484        theory1 = Theory1D()
1485        theory1.id = 7
1486        data_list1['6'] = set_data_state(theory=theory1, state=None)
1487        data_list1['7'] = set_data_state(theory=theory1, state=None)
[5e5704d]1488        window = DataFrame(list=data_list1)
1489        window.load_data_list(list=data_list1)
[3feed3e]1490        window.Show(True)
[c70eb7c]1491        window.load_data_list(list=temp_data_list)
[3feed3e]1492    except:
[c8e1996]1493        # raise
[5e5704d]1494        print "error", sys.exc_value
[e767897]1495
1496    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.