Fix BrowseVariableDialog to be used in PLCOpenEditor without Beremiz plugins
authorlaurent
Thu, 24 Sep 2009 18:18:04 +0200
changeset 436 f3bb091f803f
parent 435 893d04aff708
child 437 59e33406eea8
Fix BrowseVariableDialog to be used in PLCOpenEditor without Beremiz plugins
VariablePanel.py
--- a/VariablePanel.py	Thu Sep 24 18:16:04 2009 +0200
+++ b/VariablePanel.py	Thu Sep 24 18:18:04 2009 +0200
@@ -21,11 +21,15 @@
 #License along with this library; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+import os
 import wx, wx.grid
 
 from types import TupleType
 
 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS
+from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+
+CWD = os.path.split(os.path.realpath(__file__))[0]
 
 # Compatibility function for wx versions < 2.6
 def AppendMenu(parent, help, id, kind, text):
@@ -168,7 +172,6 @@
 
         Otherwise default to the default renderer.
         """
-        
         for row in range(self.GetNumberRows()):
             for col in range(self.GetNumberCols()):
                 editor = None
@@ -187,7 +190,7 @@
                         renderer = wx.grid.GridCellStringRenderer()
                     elif colname == "Location":
                         if self.GetValueByName(row, "Class") in ["Local", "Global"]:
-                            editor = LocationCellEditor(self.Parent)
+                            editor = LocationCellEditor(self, self.Parent.Controler)
                             renderer = wx.grid.GridCellStringRenderer()
                         else:
                             grid.SetReadOnly(row, col, True)
@@ -854,325 +857,311 @@
         self.Table.ResetView(self.VariablesGrid)
 
 class LocationCellControl(wx.PyControl):
+    
+    def _init_coll_MainSizer_Items(self, parent):
+        parent.AddWindow(self.Location, 0, border=0, flag=wx.GROW)
+        parent.AddWindow(self.BrowseButton, 0, border=0, flag=wx.GROW)
+        
+    def _init_coll_MainSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(0)
+    
+    def _init_sizers(self):
+        self.MainSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
+        
+        self._init_coll_MainSizer_Items(self.MainSizer)
+        self._init_coll_MainSizer_Growables(self.MainSizer)
+        
+        self.SetSizer(self.MainSizer)
+    
+    def _init_ctrls(self, prnt):
+        wx.Control.__init__(self, id=-1, 
+              name='LocationCellControl', parent=prnt,  
+              size=wx.DefaultSize, style=0)
+        
+        # create location text control
+        self.Location = wx.TextCtrl(id=-1, name='Location', parent=self,
+              pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
+        
+        # create browse button
+        self.BrowseButton = wx.Button(id=-1, label='...', 
+              name='staticText1', parent=self, pos=wx.Point(0, 0), 
+              size=wx.Size(30, 0), style=0)
+        self.BrowseButton.Bind(wx.EVT_BUTTON, self.OnBrowseButtonClick)
+
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        
+        self._init_sizers()
+
     '''
     Custom cell editor control with a text box and a button that launches
     the BrowseVariableLocationsDialog.
     '''
-    def __init__(self, parent, var_panel):
-        wx.Control.__init__(self, parent, -1)
-        self.ParentWindow = parent
-        self.VarPanel = var_panel
-        self.Row = -1
-
-        self.Bind(wx.EVT_SIZE, self.OnSize)
-
-        # create text control
-        self.txt = wx.TextCtrl(self, -1, '', size=wx.Size(0, 0))
-
-        # create browse button
-        self.btn = wx.Button(self, -1, label='...', size=wx.Size(30, 0))
-        self.btn.Bind(wx.EVT_BUTTON, self.OnBtnBrowseClick)
-
-        self.Sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
-        self.Sizer.AddWindow(self.txt, 0, border=0, flag=wx.ALL|wx.GROW)
-        self.Sizer.AddWindow(self.btn, 0, border=0, flag=wx.ALL|wx.GROW)
-        self.Sizer.AddGrowableCol(0)
-        self.Sizer.AddGrowableRow(0)
-
-        self.SetSizer(self.Sizer)
-
-    def SetRow(self, row):
-        '''set the grid row that we're working on'''
-        self.Row = row
+    def __init__(self, parent, locations):
+        self._init_ctrls(parent)
+        self.Locations = locations
+        self.VarType = None
+
+    def SetVarType(self, vartype):
+        self.VarType = vartype
+
+    def SetValue(self, value):
+        self.Location.SetValue(value)
+    
+    def GetValue(self):
+        return self.Location.GetValue()
 
     def OnSize(self, event):
-        '''resize the button and text control to fit'''
-        #overall_width = self.GetSize()[0]
-        #btn_width, btn_height = self.btn.GetSize()
-        #new_txt_width = overall_width - btn_width
-
-        #self.txt.SetSize(wx.Size(new_txt_width, -1))
-        #self.btn.SetDimensions(new_txt_width, -1, btn_width, btn_height)
         self.Layout()
 
-    def OnBtnBrowseClick(self, event):
+    def OnBrowseButtonClick(self, event):
         # pop up the location browser dialog
-        dia = BrowseVariableLocationsDialog(self.ParentWindow, self.VarPanel)
-        dia.ShowModal()
-
-        if dia.Selection:
-            loc, iec_type, doc = dia.Selection
+        dialog = BrowseLocationsDialog(self, self.VarType, self.Locations)
+        if dialog.ShowModal() == wx.ID_OK:
+            infos = dialog.GetValues()
 
             # set the location
-            self.SetText(loc)
-
-            # set the variable type and documentation
-            # NOTE: this update won't be displayed until editing is complete
-            # (when EndEdit is called).
-            # we can't call VarPanel.RefreshValues() here because it causes
-            # an exception. 
-            self.VarPanel.Table.SetValueByName(self.Row, 'Type', iec_type)
-            self.VarPanel.Table.SetValueByName(self.Row, 'Documentation', doc)
-
-        self.txt.SetFocus()
-
-    def SetText(self, text):
-        self.txt.SetValue(text)
+            self.Location.SetValue(infos["location"])
+
+        dialog.Destroy()
+
+        self.Location.SetFocus()
 
     def SetInsertionPoint(self, i):
-        self.txt.SetInsertionPoint(i)
-
-    def GetText(self):
-        return self.txt.GetValue()
-
+        self.Location.SetInsertionPoint(i)
+    
     def SetFocus(self):
-        self.txt.SetFocus()
+        self.Location.SetFocus()
 
 class LocationCellEditor(wx.grid.PyGridCellEditor):
     '''
     Grid cell editor that uses LocationCellControl to display a browse button.
     '''
-    def __init__(self, var_panel):
+    def __init__(self, table, controler):
         wx.grid.PyGridCellEditor.__init__(self)
-        self.VarPanel = var_panel
-
+        self.Table = table
+        self.Controler = controler
+        
     def Create(self, parent, id, evt_handler):
-        self.text_browse = LocationCellControl(parent, self.VarPanel)
-        self.SetControl(self.text_browse)
+        locations = self.Controler.GetVariableLocationTree()
+        if len(locations) > 0:
+            self.CellControl = LocationCellControl(parent, locations)
+        else:
+            self.CellControl = wx.TextCtrl(parent, -1)
+        self.SetControl(self.CellControl)
         if evt_handler:
-            self.text_browse.PushEventHandler(evt_handler)
+            self.CellControl.PushEventHandler(evt_handler)
 
     def BeginEdit(self, row, col, grid):
-        loc = self.VarPanel.Table.GetValueByName(row, 'Location')
-        self.text_browse.SetText(loc)
-        self.text_browse.SetRow(row)
-        self.text_browse.SetFocus()
+        self.CellControl.SetValue(self.Table.GetValueByName(row, 'Location'))
+        if isinstance(self.CellControl, LocationCellControl):
+            self.CellControl.SetVarType(self.Controler.GetBaseType(self.Table.GetValueByName(row, 'Type')))
+        self.CellControl.SetFocus()
 
     def EndEdit(self, row, col, grid):
-        loc = self.text_browse.GetText()
-        old_loc = self.VarPanel.Table.GetValueByName(row, 'Location')
-
+        loc = self.CellControl.GetValue()
+        old_loc = self.Table.GetValueByName(row, 'Location')
         if loc != old_loc:
-            self.VarPanel.Table.SetValueByName(row, 'Location', loc)
-            
-            # NOTE: this is a really lame hack to force this row's
-            # 'Type' cell to redraw (since it may have changed). 
-            # There's got to be a better way than this.
-            self.VarPanel.VariablesGrid.AutoSizeRow(row)
+            self.Table.SetValueByName(row, 'Location', loc)
             return True
+        return False
 
     def SetSize(self, rect):
-        self.text_browse.SetDimensions(rect.x + 1, rect.y,
+        self.CellControl.SetDimensions(rect.x + 1, rect.y,
                                         rect.width, rect.height,
                                         wx.SIZE_ALLOW_MINUS_ONE)
 
     def Clone(self):
-        return LocationCellEditor(self.VarPanel)
-
-class BrowseVariableLocationsDialog(wx.Dialog):
-    # turn LOCATIONDATATYPES inside-out
-    LOCATION_SIZES = {}
-    for size, types in LOCATIONDATATYPES.iteritems():
-        for type in types:
-            LOCATION_SIZES[type] = size
-
-    class PluginData:
-        '''contains a plugin's VariableLocationTree'''
-        def __init__(self, plugin):
-            self.subtree  = plugin.GetVariableLocationTree()
-
-    class SubtreeData:
-        '''contains a subtree of a plugin's VariableLocationTree'''
-        def __init__(self, subtree):
-            self.subtree = subtree
-
-    class VariableData:
-        '''contains all the information about a valid variable location'''
-        def __init__(self, type, dir, loc):
-            self.type   = type
-
-            loc_suffix = '.'.join([str(x) for x in loc])
-
-            size = BrowseVariableLocationsDialog.LOCATION_SIZES[type]
-            self.loc = size + loc_suffix
-
-            # if a direction was given, use it
-            # (if not we'll prompt the user to select one)
-            if dir:
-                self.loc = '%' + dir + self.loc
-
-    def __init__(self, parent, var_panel):
-        self.VarPanel   = var_panel
-        self.Selection  = None
-
-        # create the dialog
-        wx.Dialog.__init__(self, parent=parent, title=_('Browse Variables'),
-                            style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
-                            size=(-1, 400))
-
-        # create the root sizer
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        self.SetSizer(sizer)
-
-        # create the tree control
-        self.tree = wx.TreeCtrl(self, style=wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT)
-        sizer.Add(self.tree, 1, wx.EXPAND|wx.ALL, border=20)
-
-        # create the Direction sizer and field
-        dsizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(dsizer, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, border=20)
-
-        #   direction label
-        ltext = wx.StaticText(self, -1, _('Direction:'))
-        dsizer.Add(ltext, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=20)
-
-        #   direction choice
-        self.DirChoice = wx.Choice(id=-1, parent=self, choices=[_('Input'), _('Output'), _('Memory')])
-        dsizer.Add(self.DirChoice, flag=wx.EXPAND)
-        #   set a default for the choice   
-        self.SetSelectedDirection('I')
-
-        # create the button sizer
-        btsizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(btsizer, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_RIGHT, border=20)
-
-        # add plugins to the tree
-        root = self.tree.AddRoot(_('Plugins'))
-        ctrl = self.VarPanel.Controler
-        self.AddChildPluginsToTree(ctrl, root)
-
-        #       -- buttons --
-
-        # ok button
-        self.OkButton = wx.Button(self, wx.ID_OK, _('Use Location'))
-        self.OkButton.SetDefault()
-        btsizer.Add(self.OkButton, flag=wx.RIGHT, border=5)
-
-        # cancel button
-        b = wx.Button(self, wx.ID_CANCEL, _('Cancel'))
-        btsizer.Add(b)
-
-        #       -- event handlers --
-
-        # accept the location on doubleclick or clicking the Use Location button
-        self.Bind(wx.EVT_BUTTON, self.OnOk, self.OkButton)
-        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnOk, self.tree)
-
-        # disable the Add button when we're not on a valid variable
-        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChange, self.tree)
-
-        # handle the Expand event. this lets us create the tree as it's expanded
-        # (trying to create it all at once is slow since plugin variable location
-        # trees can be big)
-        wx.EVT_TREE_ITEM_EXPANDING(self.tree, self.tree.GetId(), self.OnExpand)
-
-    def OnExpand(self, event):
-        item = event.GetItem()
-        if not item.IsOk():
-            item = self.tree.GetSelection()
-        
-        data = self.tree.GetPyData(item)
-        self.ExpandTree(item, data.subtree)
-
-    def AddChildPluginsToTree(self, plugin, root):
-        for p in plugin.IECSortedChilds():
-            plug_name = p.BaseParams.getName()
-            new_item = self.tree.AppendItem(root, plug_name)
-
-            # make it look like the tree item has children (since it doesn't yet)
-            self.tree.SetItemHasChildren(new_item) 
-
-            # attach the plugin data to the tree item
-            self.tree.SetPyData(new_item, BrowseVariableLocationsDialog.PluginData(p))
-
-            # add child plugins recursively
-            self.AddChildPluginsToTree(p, new_item)
-
-    def ExpandTree(self, root, subtree):
-            items = subtree.items()
-            items.sort()
-
-            for node_name, data in items:
-                if isinstance(data, dict):
-                    # this is a new subtree
-
-                    new_item = self.tree.AppendItem(root, node_name)
-                    self.tree.SetItemHasChildren(new_item)
-
-                    # attach the new subtree's data to the tree item
-                    new_data = BrowseVariableLocationsDialog.SubtreeData(data)
-                    self.tree.SetPyData(new_item, new_data)
+        return LocationCellEditor(self.Table, self.Locations)
+
+def GetDirChoiceOptions():
+    _ = lambda x : x
+    return [(_("All"), [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]), 
+            (_("Input"), [LOCATION_VAR_INPUT]), 
+            (_("Output"), [LOCATION_VAR_OUTPUT]), 
+            (_("Memory"), [LOCATION_VAR_MEMORY])]
+DIRCHOICE_OPTIONS_FILTER = dict([(_(option), filter) for option, filter in GetDirChoiceOptions()])
+
+# turn LOCATIONDATATYPES inside-out
+LOCATION_SIZES = {}
+for size, types in LOCATIONDATATYPES.iteritems():
+    for type in types:
+        LOCATION_SIZES[type] = size
+
+[ID_BROWSELOCATIONSDIALOG, ID_BROWSELOCATIONSDIALOGLOCATIONSTREE, 
+ ID_BROWSELOCATIONSDIALOGDIRCHOICE, ID_BROWSELOCATIONSDIALOGSTATICTEXT1, 
+ ID_BROWSELOCATIONSDIALOGSTATICTEXT2, 
+] = [wx.NewId() for _init_ctrls in range(5)]
+
+class BrowseLocationsDialog(wx.Dialog):
+    
+    if wx.VERSION < (2, 6, 0):
+        def Bind(self, event, function, id = None):
+            if id is not None:
+                event(self, id, function)
+            else:
+                event(self, function)
+    
+    def _init_coll_MainSizer_Items(self, parent):
+        parent.AddWindow(self.staticText1, 0, border=20, flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddWindow(self.LocationsTree, 0, border=20, flag=wx.LEFT|wx.RIGHT|wx.GROW)
+        parent.AddSizer(self.ButtonGridSizer, 0, border=20, flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
+        
+    def _init_coll_MainSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(1)
+    
+    def _init_coll_ButtonGridSizer_Items(self, parent):
+        parent.AddWindow(self.staticText2, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
+        parent.AddWindow(self.DirChoice, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
+        parent.AddSizer(self.ButtonSizer, 0, border=0, flag=wx.ALIGN_RIGHT)
+        
+    def _init_coll_ButtonGridSizer_Growables(self, parent):
+        parent.AddGrowableCol(2)
+        parent.AddGrowableRow(0)
+    
+    def _init_sizers(self):
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
+        self.ButtonGridSizer = wx.FlexGridSizer(cols=3, hgap=5, rows=1, vgap=0)
+        
+        self._init_coll_MainSizer_Items(self.MainSizer)
+        self._init_coll_MainSizer_Growables(self.MainSizer)
+        self._init_coll_ButtonGridSizer_Items(self.ButtonGridSizer)
+        self._init_coll_ButtonGridSizer_Growables(self.ButtonGridSizer)
+        
+        self.SetSizer(self.MainSizer)
+    
+    def _init_ctrls(self, prnt):
+        wx.Dialog.__init__(self, id=ID_BROWSELOCATIONSDIALOG, 
+              name='BrowseLocationsDialog', parent=prnt,  
+              size=wx.Size(600, 400), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
+              title=_('Browse Locations'))
+    
+        self.staticText1 = wx.StaticText(id=ID_BROWSELOCATIONSDIALOGSTATICTEXT1,
+              label=_('Locations available:'), name='staticText1', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        
+        if wx.Platform == '__WXMSW__':
+            treestyle = wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER
+        else:
+            treestyle = wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER
+        self.LocationsTree = wx.TreeCtrl(id=ID_BROWSELOCATIONSDIALOGLOCATIONSTREE,
+              name='LocationsTree', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(0, 0), style=treestyle)
+        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnLocationsTreeItemActivated, 
+                  id=ID_BROWSELOCATIONSDIALOGLOCATIONSTREE)
+        
+        self.staticText2 = wx.StaticText(id=ID_BROWSELOCATIONSDIALOGSTATICTEXT2,
+              label=_('Direction:'), name='staticText2', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        
+        self.DirChoice = wx.ComboBox(id=ID_BROWSELOCATIONSDIALOGDIRCHOICE,
+              name='DirChoice', parent=self, pos=wx.Point(0, 0),
+              size=wx.DefaultSize, style=wx.CB_READONLY)
+        self.Bind(wx.EVT_COMBOBOX, self.OnDirChoice, id=ID_BROWSELOCATIONSDIALOGDIRCHOICE)
+        
+        self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
+        if wx.VERSION >= (2, 5, 0):
+            self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
+        else:
+            self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId())
+        
+        self._init_sizers()
+    
+    def __init__(self, parent, var_type, locations):
+        self._init_ctrls(parent)
+        self.VarType = var_type
+        self.Locations = locations
+        
+        # Define Tree item icon list
+        self.TreeImageList = wx.ImageList(16, 16)
+        self.TreeImageDict = {}
+        
+        # Icons for items
+        for imgname, itemtype in [
+            ("CONFIGURATION", LOCATION_PLUGIN), 
+            ("RESOURCE",      LOCATION_MODULE), 
+            ("PROGRAM",       LOCATION_GROUP), 
+            ("VAR_INPUT",     LOCATION_VAR_INPUT), 
+            ("VAR_OUTPUT",    LOCATION_VAR_OUTPUT), 
+            ("VAR_LOCAL",     LOCATION_VAR_MEMORY)]:
+            self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname)))
+        
+        # Assign icon list to TreeCtrls
+        self.LocationsTree.SetImageList(self.TreeImageList)
+        
+        # Set a options for the choice
+        for option, filter in GetDirChoiceOptions():
+            self.DirChoice.Append(_(option))
+        self.DirChoice.SetStringSelection(_("All"))
+        self.RefreshFilter()
+        
+        self.RefreshLocationsTree()
+    
+    def RefreshFilter(self):
+        self.Filter = DIRCHOICE_OPTIONS_FILTER[self.DirChoice.GetStringSelection()]
+    
+    def RefreshLocationsTree(self):
+        root = self.LocationsTree.GetRootItem()
+        if not root.IsOk():
+            if wx.Platform == '__WXMSW__':
+                root = self.LocationsTree.AddRoot(_('Plugins'))
+            else:
+                root = self.LocationsTree.AddRoot("")
+        self.GenerateLocationsTreeBranch(root, self.Locations)
+        self.LocationsTree.Expand(root)
+    
+    def GenerateLocationsTreeBranch(self, root, locations):
+        to_delete = []
+        if wx.VERSION >= (2, 6, 0):
+            item, root_cookie = self.LocationsTree.GetFirstChild(root)
+        else:
+            item, root_cookie = self.LocationsTree.GetFirstChild(root, 0)
+        for loc_infos in locations:
+            infos = loc_infos.copy()
+            if infos["type"] in [LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP] or\
+               infos["type"] in self.Filter and (infos["IEC_type"] == self.VarType or
+               infos["IEC_type"] is None and LOCATION_SIZES[self.VarType] == infos["size"]):
+                children = [child for child in infos.pop("children")]
+                if not item.IsOk():
+                    item = self.LocationsTree.AppendItem(root, infos["name"])
+                    if wx.Platform != '__WXMSW__':
+                        item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie)
                 else:
-                    # this is a new leaf.
-
-                    # data is a tuple containing (IEC type, I/Q/M/None, IEC path tuple)
-                    type, dir, loc = data
-
-                    node_name = '%s (%s)' % (node_name, type)
-                    new_item = self.tree.AppendItem(root, node_name)
-
-                    vd = BrowseVariableLocationsDialog.VariableData(type, dir, loc)
-                    self.tree.SetPyData(new_item, vd)
-
-    def OnSelChange(self, event):
-        '''updates the text field and the "Use Location"  button.'''
-        item = self.tree.GetSelection()
-        data = self.tree.GetPyData(item)
-
-        if isinstance(data, BrowseVariableLocationsDialog.VariableData):
-            self.OkButton.Enable()
-
-            location = data.loc
-            if location[0] == '%':
-                # location has a fixed direction
-                self.SetSelectedDirection(location[1])
-                self.DirChoice.Disable()
-            else:
-                # this location can have any direction (user selects)
-                self.DirChoice.Enable()
-        else:
-            self.OkButton.Disable()
-            self.DirChoice.Disable()
-
-    def GetSelectedDirection(self):
-        selected = self.DirChoice.GetSelection()
-        if selected == 0:
-            return 'I'
-        elif selected == 1:
-            return 'Q'
-        else:
-            return 'M'
-
-    def SetSelectedDirection(self, dir_letter):
-        if dir_letter == 'I':
-            self.DirChoice.SetSelection(0)
-        elif dir_letter == 'Q':
-            self.DirChoice.SetSelection(1)
-        else:
-            self.DirChoice.SetSelection(2)
-
-    def OnOk(self, event):
-        item = self.tree.GetSelection()
-        data = self.tree.GetPyData(item)
-
-        if not isinstance(data, BrowseVariableLocationsDialog.VariableData):
-            return
-
-        location = data.loc
-
-        if location[0] != '%':
-            # no direction was given, grab the one from the wxChoice
-            dir = self.GetSelectedDirection()
-            location = '%' + dir + location
-
-        # walk up the tree, building documentation for the variable
-        documentation = self.tree.GetItemText(item)
-        parent = self.tree.GetItemParent(item)
-        root = self.tree.GetRootItem()
-        while parent != root:
-            text = self.tree.GetItemText(parent)
-            documentation = text + ":" + documentation
-            parent = self.tree.GetItemParent(parent)
-
-        self.Selection = (location, data.type, documentation)
-        self.Destroy() 
+                    self.LocationsTree.SetItemText(item, infos["name"])
+                self.LocationsTree.SetPyData(item, infos)
+                self.LocationsTree.SetItemImage(item, self.TreeImageDict[infos["type"]])
+                self.GenerateLocationsTreeBranch(item, children)
+                item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie)
+        while item.IsOk():
+            to_delete.append(item)
+            item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie)
+        for item in to_delete:
+            self.LocationsTree.Delete(item)
+    
+    def OnLocationsTreeItemActivated(self, event):
+        infos = self.LocationsTree.GetPyData(event.GetItem())
+        if infos["type"] not in [LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP]:
+            wx.CallAfter(self.EndModal, wx.ID_OK)
+        event.Skip()
+    
+    def OnDirChoice(self, event):
+        self.RefreshFilter()
+        self.RefreshLocationsTree()
+        
+    def GetValues(self):
+        selected = self.LocationsTree.GetSelection()
+        return self.LocationsTree.GetPyData(selected)
+        
+    def OnOK(self, event):
+        selected = self.LocationsTree.GetSelection()
+        var_infos = None
+        if selected.IsOk():
+            var_infos = self.LocationsTree.GetPyData(selected)
+        if var_infos is None or var_infos["type"] in [LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP]:
+            message = wx.MessageDialog(self, _("A location must be selected!"), _("Error"), wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        else:
+            self.EndModal(wx.ID_OK)
+        
\ No newline at end of file