Laurent@814: # Laurent@814: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD Laurent@814: # Laurent@814: #See COPYING file for copyrights details. Laurent@814: # Laurent@814: #This library is free software; you can redistribute it and/or Laurent@814: #modify it under the terms of the GNU General Public Laurent@814: #License as published by the Free Software Foundation; either Laurent@814: #version 2.1 of the License, or (at your option) any later version. Laurent@814: # Laurent@814: #This library is distributed in the hope that it will be useful, Laurent@814: #but WITHOUT ANY WARRANTY; without even the implied warranty of Laurent@814: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Laurent@814: #General Public License for more details. Laurent@814: # Laurent@814: #You should have received a copy of the GNU General Public Laurent@814: #License along with this library; if not, write to the Free Software Laurent@814: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Laurent@814: Laurent@814: import os Laurent@814: Laurent@814: import wx Laurent@814: Laurent@814: from plcopen.structures import LOCATIONDATATYPES Laurent@814: from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Helpers Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: CWD = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] Laurent@814: Laurent@814: def GetDirChoiceOptions(): Laurent@814: _ = lambda x : x Laurent@814: return [(_("All"), [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]), Laurent@814: (_("Input"), [LOCATION_VAR_INPUT]), Laurent@814: (_("Output"), [LOCATION_VAR_OUTPUT]), Laurent@814: (_("Memory"), [LOCATION_VAR_MEMORY])] Laurent@814: DIRCHOICE_OPTIONS_FILTER = dict([(_(option), filter) for option, filter in GetDirChoiceOptions()]) Laurent@814: Laurent@814: # turn LOCATIONDATATYPES inside-out Laurent@814: LOCATION_SIZES = {} Laurent@814: for size, types in LOCATIONDATATYPES.iteritems(): Laurent@814: for type in types: Laurent@814: LOCATION_SIZES[type] = size Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Browse Locations Dialog Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: class BrowseLocationsDialog(wx.Dialog): Laurent@814: Laurent@814: def __init__(self, parent, var_type, locations): Laurent@814: wx.Dialog.__init__(self, parent, Laurent@814: size=wx.Size(600, 400), title=_('Browse Locations')) Laurent@814: Laurent@814: main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10) Laurent@814: main_sizer.AddGrowableCol(0) Laurent@814: main_sizer.AddGrowableRow(1) Laurent@814: Laurent@814: locations_label = wx.StaticText(self, label=_('Locations available:')) Laurent@814: main_sizer.AddWindow(locations_label, border=20, Laurent@814: flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW) Laurent@814: Laurent@814: self.LocationsTree = wx.TreeCtrl(self, Laurent@814: style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_HIDE_ROOT|wx.TR_LINES_AT_ROOT) Laurent@814: self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnLocationsTreeItemActivated, Laurent@814: self.LocationsTree) Laurent@814: main_sizer.AddWindow(self.LocationsTree, border=20, Laurent@814: flag=wx.LEFT|wx.RIGHT|wx.GROW) Laurent@814: Laurent@814: button_gridsizer = wx.FlexGridSizer(cols=3, hgap=5, rows=1, vgap=0) Laurent@814: button_gridsizer.AddGrowableCol(2) Laurent@814: button_gridsizer.AddGrowableRow(0) Laurent@814: main_sizer.AddSizer(button_gridsizer, border=20, Laurent@814: flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.GROW) Laurent@814: Laurent@814: direction_label = wx.StaticText(self, label=_('Direction:')) Laurent@814: button_gridsizer.AddWindow(direction_label, Laurent@814: flag=wx.ALIGN_CENTER_VERTICAL) Laurent@814: Laurent@814: self.DirChoice = wx.ComboBox(self, style=wx.CB_READONLY) Laurent@814: self.Bind(wx.EVT_COMBOBOX, self.OnDirChoice, self.DirChoice) Laurent@814: button_gridsizer.AddWindow(self.DirChoice, Laurent@814: flag=wx.ALIGN_CENTER_VERTICAL) Laurent@814: Laurent@814: button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) Laurent@814: self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton()) Laurent@814: button_gridsizer.AddWindow(button_sizer, flag=wx.ALIGN_RIGHT) Laurent@814: Laurent@814: self.SetSizer(main_sizer) Laurent@814: Laurent@814: self.VarType = var_type Laurent@814: self.Locations = locations Laurent@814: Laurent@814: # Define Tree item icon list Laurent@814: self.TreeImageList = wx.ImageList(16, 16) Laurent@814: self.TreeImageDict = {} Laurent@814: Laurent@814: # Icons for items Laurent@814: for imgname, itemtype in [ Laurent@814: ("CONFIGURATION", LOCATION_CONFNODE), Laurent@814: ("RESOURCE", LOCATION_MODULE), Laurent@814: ("PROGRAM", LOCATION_GROUP), Laurent@814: ("VAR_INPUT", LOCATION_VAR_INPUT), Laurent@814: ("VAR_OUTPUT", LOCATION_VAR_OUTPUT), Laurent@814: ("VAR_LOCAL", LOCATION_VAR_MEMORY)]: Laurent@814: self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname))) Laurent@814: Laurent@814: # Assign icon list to TreeCtrls Laurent@814: self.LocationsTree.SetImageList(self.TreeImageList) Laurent@814: Laurent@814: # Set a options for the choice Laurent@814: for option, filter in GetDirChoiceOptions(): Laurent@814: self.DirChoice.Append(_(option)) Laurent@814: self.DirChoice.SetStringSelection(_("All")) Laurent@814: self.RefreshFilter() Laurent@814: Laurent@814: self.RefreshLocationsTree() Laurent@814: Laurent@814: def RefreshFilter(self): Laurent@814: self.Filter = DIRCHOICE_OPTIONS_FILTER[self.DirChoice.GetStringSelection()] Laurent@814: Laurent@814: def RefreshLocationsTree(self): Laurent@814: root = self.LocationsTree.GetRootItem() Laurent@814: if not root.IsOk(): Laurent@814: root = self.LocationsTree.AddRoot("") Laurent@814: self.GenerateLocationsTreeBranch(root, self.Locations) Laurent@814: Laurent@814: def GenerateLocationsTreeBranch(self, root, locations): Laurent@814: to_delete = [] Laurent@814: item, root_cookie = self.LocationsTree.GetFirstChild(root) Laurent@814: for loc_infos in locations: Laurent@814: infos = loc_infos.copy() Laurent@814: if infos["type"] in [LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP] or\ Laurent@814: infos["type"] in self.Filter and (infos["IEC_type"] == self.VarType or Laurent@814: infos["IEC_type"] is None and LOCATION_SIZES[self.VarType] == infos["size"]): Laurent@814: children = [child for child in infos.pop("children")] Laurent@814: if not item.IsOk(): Laurent@814: item = self.LocationsTree.AppendItem(root, infos["name"]) Laurent@814: if wx.Platform != '__WXMSW__': Laurent@814: item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie) Laurent@814: else: Laurent@814: self.LocationsTree.SetItemText(item, infos["name"]) Laurent@814: self.LocationsTree.SetPyData(item, infos) Laurent@814: self.LocationsTree.SetItemImage(item, self.TreeImageDict[infos["type"]]) Laurent@814: self.GenerateLocationsTreeBranch(item, children) Laurent@814: item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie) Laurent@814: while item.IsOk(): Laurent@814: to_delete.append(item) Laurent@814: item, root_cookie = self.LocationsTree.GetNextChild(root, root_cookie) Laurent@814: for item in to_delete: Laurent@814: self.LocationsTree.Delete(item) Laurent@814: Laurent@814: def OnLocationsTreeItemActivated(self, event): Laurent@814: infos = self.LocationsTree.GetPyData(event.GetItem()) Laurent@814: if infos["type"] not in [LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP]: Laurent@814: wx.CallAfter(self.EndModal, wx.ID_OK) Laurent@814: event.Skip() Laurent@814: Laurent@814: def OnDirChoice(self, event): Laurent@814: self.RefreshFilter() Laurent@814: self.RefreshLocationsTree() Laurent@814: Laurent@814: def GetValues(self): Laurent@814: selected = self.LocationsTree.GetSelection() Laurent@814: return self.LocationsTree.GetPyData(selected) Laurent@814: Laurent@814: def OnOK(self, event): Laurent@814: selected = self.LocationsTree.GetSelection() Laurent@814: var_infos = None Laurent@814: if selected.IsOk(): Laurent@814: var_infos = self.LocationsTree.GetPyData(selected) Laurent@814: if var_infos is None or var_infos["type"] in [LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP]: Laurent@814: dialog = wx.MessageDialog(self, _("A location must be selected!"), _("Error"), wx.OK|wx.ICON_ERROR) Laurent@814: dialog.ShowModal() Laurent@814: dialog.Destroy() Laurent@814: else: Laurent@814: self.EndModal(wx.ID_OK)