clean-up for PEP8: fix W291 trailing whitespace
authorAndrey Skvortsov <andrej.skvortzov@gmail.com>
Mon, 14 Aug 2017 19:13:01 +0300
changeset 1730 64d8f52bc8c8
parent 1726 d51af006fa6b
child 1731 6ebd9c40b2be
clean-up for PEP8: fix W291 trailing whitespace
Beremiz.py
BeremizIDE.py
Beremiz_service.py
CodeFileTreeNode.py
ConfigTreeNode.py
IDEFrame.py
NativeLib.py
PLCGenerator.py
PLCOpenEditor.py
POULibrary.py
ProjectController.py
c_ext/CFileEditor.py
canfestival/NetworkEditor.py
canfestival/SlaveEditor.py
canfestival/canfestival.py
canfestival/config_utils.py
controls/CustomToolTip.py
controls/CustomTree.py
controls/DebugVariablePanel/DebugVariableGraphicViewer.py
controls/DebugVariablePanel/DebugVariableItem.py
controls/DebugVariablePanel/DebugVariablePanel.py
controls/DebugVariablePanel/DebugVariableTextViewer.py
controls/DebugVariablePanel/DebugVariableViewer.py
controls/DebugVariablePanel/GraphButton.py
controls/DurationCellEditor.py
controls/EnhancedStatusBar.py
controls/FolderTree.py
controls/LibraryPanel.py
controls/LocationCellEditor.py
controls/PouInstanceVariablesPanel.py
controls/ProjectPropertiesPanel.py
controls/SearchResultPanel.py
controls/VariablePanel.py
dialogs/ActionBlockDialog.py
dialogs/ArrayTypeDialog.py
dialogs/BlockPreviewDialog.py
dialogs/BrowseLocationsDialog.py
dialogs/BrowseValuesLibraryDialog.py
dialogs/ConnectionDialog.py
dialogs/DiscoveryDialog.py
dialogs/DurationEditorDialog.py
dialogs/FBDBlockDialog.py
dialogs/FBDVariableDialog.py
dialogs/FindInPouDialog.py
dialogs/ForceVariableDialog.py
dialogs/LDElementDialog.py
dialogs/LDPowerRailDialog.py
dialogs/PouActionDialog.py
dialogs/PouNameDialog.py
dialogs/PouTransitionDialog.py
dialogs/ProjectDialog.py
dialogs/SFCDivergenceDialog.py
dialogs/SFCStepDialog.py
dialogs/SFCStepNameDialog.py
dialogs/SFCTransitionDialog.py
dialogs/SearchInProjectDialog.py
editors/DebugViewer.py
editors/FileManagementPanel.py
editors/LDViewer.py
editors/SFCViewer.py
editors/TextViewer.py
editors/Viewer.py
graphics/DebugDataConsumer.py
graphics/FBD_Objects.py
graphics/GraphicCommons.py
graphics/LD_Objects.py
graphics/RubberBand.py
graphics/SFC_Objects.py
graphics/ToolTipProducer.py
i18n/mki18n.py
plcopen/plcopen.py
plcopen/structures.py
py_ext/PythonEditor.py
py_ext/py_ext.py
runtime/PLCObject.py
runtime/ServicePublisher.py
svgui/pyjs/build.py
svgui/pyjs/jsonrpc/django/jsonrpc.py
svgui/pyjs/jsonrpc/jsonrpc.py
svgui/pyjs/lib/pyjslib.py
svgui/pyjs/lib/sys.py
svgui/pyjs/pyjs.py
svgui/svgui.py
svgui/svgui_server.py
svgui/svguilib.py
targets/__init__.py
targets/toolchain_makefile.py
util/ProcessLogger.py
util/TranslationCatalogs.py
util/Zeroconf.py
wxglade_hmi/wxglade_hmi.py
xmlclass/xmlclass.py
xmlclass/xsdschema.py
--- a/Beremiz.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/Beremiz.py	Mon Aug 14 19:13:01 2017 +0300
@@ -60,14 +60,14 @@
 
     def Usage(self):
         print "Usage:"
-        print "%s [Options] [Projectpath] [Buildpath]"%sys.argv[0]        
+        print "%s [Options] [Projectpath] [Buildpath]"%sys.argv[0]
         print ""
         print "Supported options:"
         print "-h --help                    Print this help"
         print "-u --updatecheck URL         Retrieve update information by checking URL"
         print "-e --extend PathToExtension  Extend IDE functionality by loading at start additional extensions"
         print ""
-        print ""        
+        print ""
 
     def SetCmdOptions(self):
         self.shortCmdOpts = "hu:e:"
--- a/BeremizIDE.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/BeremizIDE.py	Mon Aug 14 19:13:01 2017 +0300
@@ -276,9 +276,9 @@
             wx.MessageBox(version.GetCommunityHelpMsg(), _(u'Community support'), wx.OK | wx.ICON_INFORMATION)
         }
         id = wx.NewId()
-        parent.Append(help='', id=id, kind=wx.ITEM_NORMAL, text=_(u'Community support'))        
+        parent.Append(help='', id=id, kind=wx.ITEM_NORMAL, text=_(u'Community support'))
         self.Bind(wx.EVT_MENU, handler, id=id)
-        
+
         parent.Append(help='', id=wx.ID_ABOUT,
               kind=wx.ITEM_NORMAL, text=_(u'About'))
         self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
@@ -371,7 +371,7 @@
         self.ConnectionStatusBar = esb.EnhancedStatusBar(self, style=wx.ST_SIZEGRIP)
         self._init_coll_ConnectionStatusBar_Fields(self.ConnectionStatusBar)
         self.ProgressStatusBar = wx.Gauge(self.ConnectionStatusBar, -1, range = 100)
-        self.ConnectionStatusBar.AddWidget(self.ProgressStatusBar, esb.ESB_EXACT_FIT, esb.ESB_EXACT_FIT, 2)        
+        self.ConnectionStatusBar.AddWidget(self.ProgressStatusBar, esb.ESB_EXACT_FIT, esb.ESB_EXACT_FIT, 2)
         self.ProgressStatusBar.Hide()
         self.SetStatusBar(self.ConnectionStatusBar)
 
@@ -383,13 +383,13 @@
             # commands invoked by build process by default are
             # found here.
             os.environ["PATH"] = os.getcwd()+';'+os.environ["PATH"]
-        
-        
+
+
     def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
         # Add beremiz's icon in top left corner of the frame
         self.icon = wx.Icon(Bpath("images", "brz.ico"), wx.BITMAP_TYPE_ICO)
         self.__init_execute_path()
-        
+
         IDEFrame.__init__(self, parent, debug)
         self.Log = LogPseudoFile(self.LogConsole,self.SelectTab)
 
@@ -932,7 +932,7 @@
         self.Close()
 
     def OnAboutMenu(self, event):
-        info = version.GetAboutDialogInfo()        
+        info = version.GetAboutDialogInfo()
         ShowAboutDialog(self, info)
 
     def OnProjectTreeItemBeginEdit(self, event):
--- a/Beremiz_service.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/Beremiz_service.py	Mon Aug 14 19:13:01 2017 +0300
@@ -306,7 +306,7 @@
             def OnTaskBarChangeInterface(self, evt):
                 ip_addr = self.pyroserver.ip_addr
                 ip_addr = '' if ip_addr is None else ip_addr
-                dlg = ParamsEntryDialog(None, _("Enter the IP of the interface to bind"), defaultValue=ip_addr)                
+                dlg = ParamsEntryDialog(None, _("Enter the IP of the interface to bind"), defaultValue=ip_addr)
                 dlg.SetTests([(re.compile('\d{1,3}(?:\.\d{1,3}){3}$').match, _("IP is not valid!")),
                                ( lambda x :len([x for x in x.split(".") if 0 <= int(x) <= 255]) == 4, _("IP is not valid!"))
                                ])
--- a/CodeFileTreeNode.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/CodeFileTreeNode.py	Mon Aug 14 19:13:01 2017 +0300
@@ -81,10 +81,10 @@
 SECTION_TAG_ELEMENT = "<xsd:element name=\"%s\" type=\"CodeText\"/>"
 
 class CodeFile:
-    
+
     CODEFILE_NAME = "CodeFile"
     SECTIONS_NAMES = []
-    
+
     def __init__(self):
         sections_str = {"codefile_name": self.CODEFILE_NAME}
         if "includes" in self.SECTIONS_NAMES:
@@ -94,26 +94,26 @@
         sections_str["sections"] = "\n".join(
             [SECTION_TAG_ELEMENT % name
              for name in self.SECTIONS_NAMES if name != "includes"])
-        
+
         self.CodeFileParser = GenerateParserFromXSDstring(
             CODEFILE_XSD % sections_str)
         self.CodeFileVariables = etree.XPath("variables/variable")
-        
+
         filepath = self.CodeFileName()
-        
+
         if os.path.isfile(filepath):
             xmlfile = open(filepath, 'r')
             codefile_xml = xmlfile.read()
             xmlfile.close()
-            
+
             codefile_xml = codefile_xml.replace(
-                '<%s>' % self.CODEFILE_NAME, 
+                '<%s>' % self.CODEFILE_NAME,
                 '<%s xmlns:xhtml="http://www.w3.org/1999/xhtml">' % self.CODEFILE_NAME)
             for cre, repl in [
                 (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
                 (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
                 codefile_xml = cre.sub(repl, codefile_xml)
-            
+
             try:
                 self.CodeFile, error = self.CodeFileParser.LoadXMLString(codefile_xml)
                 if error is not None:
@@ -138,7 +138,7 @@
     def GenerateNewName(self, format, start_idx):
         return self.GetCTRoot().GenerateNewName(
             None, None, format, start_idx,
-            dict([(var.getname().upper(), True) 
+            dict([(var.getname().upper(), True)
                   for var in self.CodeFile.variables.getvariable()]))
 
     def SetVariables(self, variables):
@@ -152,12 +152,12 @@
             variable.setonchange(var["OnChange"])
             variable.setopts(var["Options"])
             self.CodeFile.variables.appendvariable(variable)
-    
+
     def GetVariables(self):
         datas = []
         for var in self.CodeFileVariables(self.CodeFile):
-            datas.append({"Name" : var.getname(), 
-                          "Type" : var.gettype(), 
+            datas.append({"Name" : var.getname(),
+                          "Type" : var.gettype(),
                           "Initial" : var.getinitial(),
                           "Description" : var.getdesc(),
                           "OnChange"    : var.getonchange(),
@@ -170,25 +170,25 @@
             section_code = parts.get(section)
             if section_code is not None:
                 getattr(self.CodeFile, section).setanyText(section_code)
-    
+
     def GetTextParts(self):
         return dict([(section, getattr(self.CodeFile, section).getanyText())
                      for section in self.SECTIONS_NAMES])
-            
+
     def CTNTestModified(self):
-        return self.ChangesToSave or not self.CodeFileIsSaved()    
+        return self.ChangesToSave or not self.CodeFileIsSaved()
 
     def OnCTNSave(self, from_project_path=None):
         filepath = self.CodeFileName()
-        
+
         xmlfile = open(filepath,"w")
         xmlfile.write(etree.tostring(
-            self.CodeFile, 
-            pretty_print=True, 
-            xml_declaration=True, 
+            self.CodeFile,
+            pretty_print=True,
+            xml_declaration=True,
             encoding='utf-8'))
         xmlfile.close()
-        
+
         self.MarkCodeFileAsSaved()
         return True
 
@@ -196,7 +196,7 @@
         variables = self.CodeFileVariables(self.CodeFile)
         ret =  [(variable.getname(),
                  variable.gettype(),
-                 variable.getinitial()) 
+                 variable.getinitial())
                 for variable in variables]
         ret.extend([("On"+variable.getname()+"Change", "python_poll", "")
                 for variable in variables
@@ -219,31 +219,30 @@
 
     def BufferCodeFile(self):
         self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))
-    
+
     def StartBuffering(self):
         self.Buffering = True
-        
+
     def EndBuffering(self):
         if self.Buffering:
             self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))
             self.Buffering = False
-    
+
     def MarkCodeFileAsSaved(self):
         self.EndBuffering()
         self.CodeFileBuffer.CurrentSaved()
-    
+
     def CodeFileIsSaved(self):
         return self.CodeFileBuffer.IsCurrentSaved() and not self.Buffering
-        
+
     def LoadPrevious(self):
         self.EndBuffering()
         self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Previous())
-    
+
     def LoadNext(self):
         self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Next())
-    
+
     def GetBufferState(self):
         first = self.CodeFileBuffer.IsFirst() and not self.Buffering
         last = self.CodeFileBuffer.IsLast()
         return not first, not last
-
--- a/ConfigTreeNode.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/ConfigTreeNode.py	Mon Aug 14 19:13:01 2017 +0300
@@ -67,7 +67,7 @@
     LibraryControler = None
     EditorType = ConfTreeNodeEditor
     IconPath = None
-    
+
     def _AddParamsMembers(self):
         self.CTNParams = None
         if self.XSD:
@@ -78,7 +78,7 @@
             setattr(self, name, obj)
 
     def __init__(self):
-        # Create BaseParam 
+        # Create BaseParam
         self.BaseParams = _BaseParamsParser.CreateRoot()
         self.MandatoryParams = ("BaseParams", self.BaseParams)
         self._AddParamsMembers()
@@ -86,10 +86,10 @@
         self._View = None
         # copy ConfNodeMethods so that it can be later customized
         self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
-        
+
     def ConfNodeBaseXmlFilePath(self, CTNName=None):
         return os.path.join(self.CTNPath(CTNName), "baseconfnode.xml")
-    
+
     def ConfNodeXmlFilePath(self, CTNName=None):
         return os.path.join(self.CTNPath(CTNName), "confnode.xml")
 
@@ -103,22 +103,22 @@
             project_path = self.CTNParent.CTNPath()
         return os.path.join(project_path,
                             CTNName + NameTypeSeparator + self.CTNType)
-    
+
     def CTNName(self):
         return self.BaseParams.getName()
-    
+
     def CTNEnabled(self):
         return self.BaseParams.getEnabled()
-    
+
     def CTNFullName(self):
         parent = self.CTNParent.CTNFullName()
         if parent != "":
             return parent + "." + self.CTNName()
         return self.BaseParams.getName()
-    
+
     def GetIconName(self):
         return None
-    
+
     def CTNTestModified(self):
         return self.ChangesToSave
 
@@ -134,10 +134,10 @@
                 return True
 
         return False
-    
+
     def RemoteExec(self, script, **kwargs):
         return self.CTNParent.RemoteExec(script, **kwargs)
-    
+
     def OnCTNSave(self, from_project_path=None):
         #Default, do nothing and return success
         return True
@@ -154,7 +154,7 @@
             if self.CTNParams:
                 params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0]))
             return params
-        
+
     def SetParamsAttribute(self, path, value):
         self.ChangesToSave = True
         # Filter IEC_Channel and Name, that have specific behavior
@@ -169,7 +169,7 @@
             res = self.FindNewName(value)
             self.CTNRequestSave()
             return res, True
-        
+
         parts = path.split(".", 1)
         if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
             self.MandatoryParams[1].setElementValue(parts[1], value)
@@ -189,32 +189,32 @@
             if not os.path.isdir(ctnpath):
                 # Create it
                 os.mkdir(ctnpath)
-    
+
             # generate XML for base XML parameters controller of the confnode
             if self.MandatoryParams:
                 BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
                 BaseXMLFile.write(etree.tostring(
-                    self.MandatoryParams[1], 
-                    pretty_print=True, 
-                    xml_declaration=True, 
+                    self.MandatoryParams[1],
+                    pretty_print=True,
+                    xml_declaration=True,
                     encoding='utf-8'))
                 BaseXMLFile.close()
-            
+
             # generate XML for XML parameters controller of the confnode
             if self.CTNParams:
                 XMLFile = open(self.ConfNodeXmlFilePath(),'w')
                 XMLFile.write(etree.tostring(
-                    self.CTNParams[1], 
-                    pretty_print=True, 
-                    xml_declaration=True, 
+                    self.CTNParams[1],
+                    pretty_print=True,
+                    xml_declaration=True,
                     encoding='utf-8'))
                 XMLFile.close()
-            
+
             # Call the confnode specific OnCTNSave method
             result = self.OnCTNSave(from_project_path)
             if not result:
                 return _("Error while saving \"%s\"\n")%self.CTNPath()
-    
+
             # mark confnode as saved
             self.ChangesToSave = False
             # go through all children and do the same
@@ -226,7 +226,7 @@
                 if result:
                     return result
         return None
-    
+
     def CTNImport(self, src_CTNPath):
         shutil.copytree(src_CTNPath, self.CTNPath)
         return True
@@ -236,13 +236,13 @@
         @return: [(instance_name, instance_type),...]
         """
         return []
-    
+
     def _GlobalInstances(self):
         instances = self.CTNGlobalInstances()
         for CTNChild in self.IECSortedChildren():
             instances.extend(CTNChild._GlobalInstances())
         return instances
-    
+
     def CTNGenerate_C(self, buildpath, locations):
         """
         Generate C code
@@ -257,7 +257,7 @@
         """
         self.GetCTRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
         return [],"",False
-    
+
     def _Generate_C(self, buildpath, locations):
         # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
         # extra_files = [(fname,fobject), ...]
@@ -280,7 +280,7 @@
                 LDFLAGS=CTNLDFLAGS[:]
         else:
             LDFLAGS=[]
-        
+
         # recurse through all children, and stack their results
         for CTNChild in self.IECSortedChildren():
             new_location = CTNChild.GetCurrentLocation()
@@ -296,14 +296,14 @@
             LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
             LDFLAGS += _LDFLAGS
             extra_files += _extra_files
-        
+
         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
 
     def IterChildren(self):
         for CTNType, Children in self.Children.items():
             for CTNInstance in Children:
                 yield CTNInstance
-    
+
     def IECSortedChildren(self):
         # reorder children by IEC_channels
         ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChildren()]
@@ -312,7 +312,7 @@
             return zip(*ordered)[1]
         else:
             return []
-    
+
     def _GetChildBySomething(self, something, toks):
         for CTNInstance in self.IterChildren():
             # if match component of the name
@@ -338,7 +338,7 @@
             return self._GetChildBySomething("IEC_Channel", Location)
         else:
             return self
-    
+
     def GetCurrentLocation(self):
         """
         @return:  Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
@@ -372,7 +372,7 @@
         This function is meant to be overridden by confnodes.
 
         It should returns an list of dictionaries
-        
+
         - IEC_type is an IEC type like BOOL/BYTE/SINT/...
         - location is a string of this variable's location, like "%IX0.0.0"
         '''
@@ -409,7 +409,7 @@
         while res in AllNames:
             res = "%s_%d"%(BaseDesiredName, suffix)
             suffix += 1
-        
+
         # Get old path
         oldname = self.CTNPath()
         # Check previous confnode existance
@@ -444,7 +444,7 @@
         #if CurrentChannel == DesiredChannel: return CurrentChannel
         # Build a list of used Channels out of parent's Children
         AllChannels = self.GetAllChannels()
-        
+
         # Now, try to guess the nearest available channel
         res = DesiredChannel
         while res in AllChannels: # While channel not free
@@ -466,14 +466,14 @@
         if self.EditorType is not None:
             app_frame = self.GetCTRoot().AppFrame
             if self._View is None and not onlyopened:
-                
+
                 self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
-            
+
             if self._View is not None:
                 if name is None:
                     name = self.CTNFullName()
                 app_frame.EditProjectElement(self._View, name)
-            
+
             return self._View
         return None
 
@@ -527,23 +527,23 @@
             CTNClass, CTNHelp = CTNChildrenTypes[CTNType]
         except KeyError:
             raise Exception, _("Cannot create child {a1} of type {a2} ").format(a1 = CTNName, a2 = CTNType)
-        
+
         # if CTNClass is a class factory, call it. (prevent unneeded imports)
         if type(CTNClass) == types.FunctionType:
             CTNClass = CTNClass()
-        
+
         # Eventualy Initialize child instance list for this class of confnode
         ChildrenWithSameClass = self.Children.setdefault(CTNType, list())
         # Check count
         if getattr(CTNClass, "CTNMaxCount", None) and len(ChildrenWithSameClass) >= CTNClass.CTNMaxCount:
             msg = _("Max count ({a1}) reached for this confnode of type {a2} ").format(a1 = CTNClass.CTNMaxCount, a2 = CTNType)
             raise Exception, msg
-        
+
         # create the final class, derived of provided confnode and template
         class FinalCTNClass(CTNClass, ConfigTreeNode):
             """
             ConfNode class is derivated into FinalCTNClass before being instanciated
-            This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called 
+            This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called
             before CTNClass.__init__, and to do the file related stuff.
             """
             def __init__(_self):
@@ -568,7 +568,7 @@
                         raise Exception, msg
 
                     # Now, self.CTNPath() should be OK
-                    
+
                     # Check that IEC_Channel is not already in use.
                     _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
                     # Call the confnode real __init__
@@ -589,29 +589,29 @@
                     _self.CTNRequestSave()
                     #just created, must be saved
                     _self.ChangesToSave = True
-                
+
             def _getBuildPath(_self):
                 return self._getBuildPath()
-            
+
         # Create the object out of the resulting class
         newConfNodeOpj = FinalCTNClass()
         # Store it in CTNgedChils
         ChildrenWithSameClass.append(newConfNodeOpj)
-        
+
         return newConfNodeOpj
-    
+
     def ClearChildren(self):
         for child in self.IterChildren():
             child.ClearChildren()
         self.Children = {}
-    
+
     def LoadXMLParams(self, CTNName = None):
         methode_name = os.path.join(self.CTNPath(CTNName), "methods.py")
         if os.path.isfile(methode_name):
             execfile(methode_name)
-        
+
         ConfNodeName = CTNName if CTNName is not None else self.CTNName()
-        
+
         # Get the base xml tree
         if self.MandatoryParams:
             try:
@@ -626,7 +626,7 @@
                 msg = _("Couldn't load confnode base parameters {a1} :\n {a2}").format(a1 =  ConfNodeName, a2 = unicode(exc))
                 self.GetCTRoot().logger.write_error(msg)
                 self.GetCTRoot().logger.write_error(traceback.format_exc())
-        
+
         # Get the xml tree
         if self.CTNParams:
             try:
@@ -643,7 +643,7 @@
                 msg = _("Couldn't load confnode parameters {a1} :\n {a2}").format(a1 = ConfNodeName, a2 = unicode(exc))
                 self.GetCTRoot().logger.write_error(msg)
                 self.GetCTRoot().logger.write_error(traceback.format_exc())
-        
+
     def LoadChildren(self):
         # Iterate over all CTNName@CTNType in confnode directory, and try to open them
         for CTNDir in os.listdir(self.CTNPath()):
@@ -656,4 +656,3 @@
                     msg = _("Could not add child \"{a1}\", type {a2} :\n{a3}\n").format(a1 = pname, a2 = ptype, a3 = unicode(exc))
                     self.GetCTRoot().logger.write_error(msg)
                     self.GetCTRoot().logger.write_error(traceback.format_exc())
-
--- a/IDEFrame.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/IDEFrame.py	Mon Aug 14 19:13:01 2017 +0300
@@ -474,10 +474,10 @@
 
     def _init_icon(self, parent):
         if self.icon:
-            self.SetIcon(self.icon)                            
+            self.SetIcon(self.icon)
         elif parent and parent.icon:
-            self.SetIcon(parent.icon)                
-        
+            self.SetIcon(parent.icon)
+
     def _init_ctrls(self, prnt):
         wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame',
               parent=prnt, pos=wx.DefaultPosition, size=wx.Size(1000, 600),
@@ -1626,7 +1626,7 @@
                         self.RefreshPageTitles()
                 elif item_infos["type"] == ITEM_TRANSITION:
                     pou_item = self.ProjectTree.GetItemParent(event.GetItem())
-                    pou_name = self.ProjectTree.GetItemText(pou_item)                    
+                    pou_name = self.ProjectTree.GetItemText(pou_item)
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
                         message = _("A POU named \"%s\" already exists!")%new_name
                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames(pou_name) if name != old_name]:
@@ -2630,4 +2630,3 @@
         self.Viewer.DoDrawing(dc, True)
 
         return True
-
--- a/NativeLib.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/NativeLib.py	Mon Aug 14 19:13:01 2017 +0300
@@ -29,5 +29,4 @@
 
 class NativeLibrary(POULibrary):
     def GetLibraryPath(self):
-        return paths.AbsNeighbourFile(__file__, "NativeLib.xml") 
-
+        return paths.AbsNeighbourFile(__file__, "NativeLib.xml")
--- a/PLCGenerator.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/PLCGenerator.py	Mon Aug 14 19:13:01 2017 +0300
@@ -771,7 +771,7 @@
                         connections = content["value"].getconnections()
                         if not connections:
                             raise PLCGenException, _("SFC transition in POU \"%s\" must be connected.") % self.Name
-                        for link in connections:                        
+                        for link in connections:
                             connected = self.GetLinkedConnector(link, body)
                             if connected is not None and not self.ConnectionTypes.has_key(connected):
                                 for related in self.ExtractRelatedConnections(connected):
@@ -1662,4 +1662,3 @@
     generator = ProgramGenerator(controler, project, errors, warnings)
     generator.GenerateProgram()
     return generator.GetGeneratedProgram()
-
--- a/PLCOpenEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/PLCOpenEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -156,14 +156,14 @@
         #      kind=wx.ITEM_NORMAL, text=u'PLCOpen\tF2')
         #AppendMenu(parent, help='', id=wx.ID_HELP_CONTEXT,
         #      kind=wx.ITEM_NORMAL, text=u'IEC 61131-3\tF3')
-        
+
         handler=lambda event: {
             wx.MessageBox(version.GetCommunityHelpMsg(), _(u'Community support'), wx.OK | wx.ICON_INFORMATION)
         }
         id = wx.NewId()
-        parent.Append(help='', id=id, kind=wx.ITEM_NORMAL, text=_(u'Community support'))        
+        parent.Append(help='', id=id, kind=wx.ITEM_NORMAL, text=_(u'Community support'))
         self.Bind(wx.EVT_MENU, handler, id=id)
-        
+
         AppendMenu(parent, help='', id=wx.ID_ABOUT,
             kind=wx.ITEM_NORMAL, text=_(u'About'))
         self.Bind(wx.EVT_MENU, self.OnPLCOpenEditorMenu, id=wx.ID_HELP)
@@ -505,4 +505,3 @@
 
     frame.Show()
     app.MainLoop()
-
--- a/POULibrary.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/POULibrary.py	Mon Aug 14 19:13:01 2017 +0300
@@ -38,14 +38,14 @@
     def GetSTCode(self):
         if not self.program:
             self.program = self.LibraryControler.GenerateProgram()[0]+"\n"
-        return self.program 
+        return self.program
 
     def GetName(self):
         return self.LibName
 
     def GetCTR(self):
         return self.CTR()
-        
+
     def GetTypes(self):
         return {"name" : self.GetName(), "types": self.LibraryControler.Project}
 
--- a/ProjectController.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/ProjectController.py	Mon Aug 14 19:13:01 2017 +0300
@@ -98,9 +98,9 @@
         for p in paths:
             if test(p):
                 path = p
-                break           
+                break
         return path
-        
+
     def findCmd(self):
         cmd="iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "")
         paths=[
@@ -113,7 +113,7 @@
             cmd=os.path.join(path, cmd)
 
         return cmd
-    
+
     def findLibPath(self):
         paths=[
             os.path.join(base_folder, "matiec", "lib"),
@@ -121,7 +121,7 @@
         ]
         path = self.findObject(paths, lambda p:os.path.isfile(os.path.join(p, "ieclib.txt")))
         return path
-        
+
     def findLibCPath(self):
         path=None
         paths=[
@@ -1158,14 +1158,14 @@
     def ShowError(self, logger, from_location, to_location):
         chunk_infos = self.GetChunkInfos(from_location, to_location)
         for infos, (start_row, start_col) in chunk_infos:
-            row = 1 if from_location[0] < start_row else (from_location[0] - start_row)            
+            row = 1 if from_location[0] < start_row else (from_location[0] - start_row)
             col = 1 if (start_row != from_location[0]) else (from_location[1] - start_col)
             start = (row, col)
 
-            row = 1 if to_location[0] < start_row else (to_location[0] - start_row)            
+            row = 1 if to_location[0] < start_row else (to_location[0] - start_row)
             col = 1 if (start_row != to_location[0]) else (to_location[1] - start_col)
             end = (row, col)
-            
+
             if self.AppFrame is not None:
                 self.AppFrame.ShowError(infos, start, end)
 
@@ -1198,7 +1198,7 @@
                 except:
                     text = '(* No IEC code have been generated at that time ! *)'
                 self._IECCodeView.SetText(text = text)
-                self._IECCodeView.Editor.SetReadOnly(True)                                
+                self._IECCodeView.Editor.SetReadOnly(True)
                 self._IECCodeView.SetIcon(GetBitmap("ST"))
                 setattr(self._IECCodeView, "_OnClose", self.OnCloseEditor)
 
@@ -1305,11 +1305,11 @@
         self.ShowMethod("_showIECcode", os.path.isfile(self._getIECcodepath()))
         if self.AppFrame is not None and not self.UpdateMethodsFromPLCStatus():
             self.AppFrame.RefreshStatusToolBar()
-        
+
     def UpdateButtons(self):
         wx.CallAfter(self._UpdateButtons)
 
-        
+
     def UpdatePLCLog(self, log_count):
         if log_count:
             if self.AppFrame is not None:
@@ -1364,7 +1364,7 @@
             "Disconnected": _("Disconnected")
             }
         return msgs.get(status, status)
-    
+
     def ShowPLCProgress(self, status = "", progress = 0):
         self.AppFrame.ProgressStatusBar.Show()
         self.AppFrame.ConnectionStatusBar.SetStatusText(self.GetTextStatus(status), 1)
@@ -1376,7 +1376,7 @@
         self.previous_plcstate = ""
         self.AppFrame.ProgressStatusBar.Hide()
         self.UpdateMethodsFromPLCStatus()
-            
+
     def PullPLCStatusProc(self, event):
         self.UpdateMethodsFromPLCStatus()
 
@@ -1821,7 +1821,7 @@
                     self.AppFrame.LogViewer.ResetLogCounters();
                 else:
                     self.logger.write_error(_("Transfer failed\n"))
-                self.HidePLCProgress()                    
+                self.HidePLCProgress()
             else:
                 self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
 
--- a/c_ext/CFileEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/c_ext/CFileEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -29,20 +29,20 @@
 
 class CppEditor(CodeEditor):
 
-    KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
-        "const", "const_cast", "continue", "default", "delete", "do", "double", 
-        "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
-        "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
-        "namespace", "new", "operator", "private", "protected", "public", "register", 
-        "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
+    KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class",
+        "const", "const_cast", "continue", "default", "delete", "do", "double",
+        "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
+        "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
+        "namespace", "new", "operator", "private", "protected", "public", "register",
+        "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
         "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
-        "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
+        "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
         "void", "volatile", "wchar_t", "while"]
     COMMENT_HEADER = "/"
-    
+
     def SetCodeLexer(self):
         self.SetLexer(stc.STC_LEX_CPP)
-        
+
         self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060,size:%(size)d' % faces)
         self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060,size:%(size)d' % faces)
         self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060,size:%(size)d' % faces)
@@ -58,10 +58,7 @@
 #-------------------------------------------------------------------------------
 
 class CFileEditor(CodeFileEditor):
-    
+
     CONFNODEEDITOR_TABS = [
         (_("C code"), "_create_CodePanel")]
     CODE_EDITOR = CppEditor
-
-
-
--- a/canfestival/NetworkEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/canfestival/NetworkEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -28,16 +28,16 @@
 from networkeditortemplate import NetworkEditorTemplate
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
 
-[ID_NETWORKEDITOR, 
+[ID_NETWORKEDITOR,
 ] = [wx.NewId() for _init_ctrls in range(1)]
 
-[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, 
- ID_NETWORKEDITORCONFNODEMENUMASTER, 
+[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE,
+ ID_NETWORKEDITORCONFNODEMENUMASTER,
 ] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(3)]
 
 [ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
  ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
- ID_NETWORKEDITORMASTERMENUADD, 
+ ID_NETWORKEDITORMASTERMENUADD,
 ] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
 
 [ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
@@ -46,37 +46,37 @@
 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
 
 class NetworkEditor(ConfTreeNodeEditor, NetworkEditorTemplate):
-    
+
     ID = ID_NETWORKEDITOR
     CONFNODEEDITOR_TABS = [
         (_("CANOpen network"), "_create_NetworkEditor")]
-    
+
     def _create_NetworkEditor(self, prnt):
-        self.NetworkEditor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0), 
+        self.NetworkEditor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0),
                 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
+
         NetworkEditorTemplate._init_ctrls(self, self.NetworkEditor)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         main_sizer.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
-    
+
         self.NetworkEditor.SetSizer(main_sizer)
-    
+
         return self.NetworkEditor
-    
+
     def __init__(self, parent, controler, window):
         ConfTreeNodeEditor.__init__(self, parent, controler, window)
         NetworkEditorTemplate.__init__(self, controler, window, False)
-    
+
         self.RefreshNetworkNodes()
         self.RefreshBufferState()
-    
+
     def __del__(self):
         self.Controler.OnCloseEditor(self)
-    
+
     def GetConfNodeMenuItems(self):
         add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
                     (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
@@ -84,7 +84,7 @@
                     (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
                     (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
                     (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-        
+
         profile = self.Manager.GetCurrentProfileName()
         if profile not in ("None", "DS-301"):
             other_profile_text = _("%s Profile") % profile
@@ -93,35 +93,35 @@
                 add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
         else:
             other_profile_text = _('Other Profile')
-        
+
         master_menu = [(wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
                        (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
                        (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
                        (wx.ITEM_SEPARATOR, None),
                        (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
-        
+
         return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORCONFNODEMENUADDSLAVE, '', self.OnAddSlaveMenu)),
                 (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
                 (wx.ITEM_SEPARATOR, None),
                 (master_menu, (_('Master'), ID_NETWORKEDITORCONFNODEMENUMASTER))]
-    
+
     def RefreshMainMenu(self):
         pass
-    
+
     def RefreshConfNodeMenu(self, confnode_menu):
         confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
-    
+
     def RefreshView(self):
         ConfTreeNodeEditor.RefreshView(self)
         self.RefreshCurrentIndexList()
-    
+
     def RefreshBufferState(self):
         NetworkEditorTemplate.RefreshBufferState(self)
         self.ParentWindow.RefreshTitle()
         self.ParentWindow.RefreshFileMenu()
         self.ParentWindow.RefreshEditMenu()
         self.ParentWindow.RefreshPageTitles()
-    
+
     def OnNodeSelectedChanged(self, event):
         NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
         wx.CallAfter(self.ParentWindow.RefreshEditMenu)
--- a/canfestival/SlaveEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/canfestival/SlaveEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -30,7 +30,7 @@
 
 [ID_SLAVEEDITORCONFNODEMENUNODEINFOS, ID_SLAVEEDITORCONFNODEMENUDS301PROFILE,
  ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE,
- ID_SLAVEEDITORCONFNODEMENUADD, 
+ ID_SLAVEEDITORCONFNODEMENUADD,
 ] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(5)]
 
 [ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
@@ -39,22 +39,22 @@
 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
 
 class SlaveEditor(ConfTreeNodeEditor, NodeEditorTemplate):
-    
+
     CONFNODEEDITOR_TABS = [
         (_("CANOpen slave"), "_create_SlaveNodeEditor")]
-    
+
     def _create_SlaveNodeEditor(self, prnt):
         self.SlaveNodeEditor = EditingPanel(prnt, self, self.Controler, self.Editable)
         return self.SlaveNodeEditor
-        
+
     def __init__(self, parent, controler, window, editable=True):
         self.Editable = editable
         ConfTreeNodeEditor.__init__(self, parent, controler, window)
         NodeEditorTemplate.__init__(self, controler, window, False)
-    
+
     def __del__(self):
         self.Controler.OnCloseEditor(self)
-    
+
     def GetConfNodeMenuItems(self):
         if self.Editable:
             add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
@@ -63,7 +63,7 @@
                         (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
                         (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
                         (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-            
+
             profile = self.Controler.GetCurrentProfileName()
             if profile not in ("None", "DS-301"):
                 other_profile_text = _("%s Profile") % profile
@@ -72,14 +72,14 @@
                     add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
             else:
                 other_profile_text = _('Other Profile')
-            
+
             return [(wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, '', self.OnCommunicationMenu)),
                     (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
                     (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
                     (wx.ITEM_SEPARATOR, None),
                     (add_menu, (_('Add'), ID_SLAVEEDITORCONFNODEMENUADD))]
         return []
-    
+
     def RefreshConfNodeMenu(self, confnode_menu):
         if self.Editable:
             confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
@@ -90,7 +90,7 @@
 
     def RefreshCurrentIndexList(self):
         self.RefreshView()
-    
+
     def RefreshBufferState(self):
         self.ParentWindow.RefreshTitle()
         self.ParentWindow.RefreshFileMenu()
@@ -100,27 +100,26 @@
 class MasterViewer(SlaveEditor):
     SHOW_BASE_PARAMS = False
     SHOW_PARAMS = False
-    
+
     def __init__(self, parent, controler, window, tagname):
         SlaveEditor.__init__(self, parent, controler, window, False)
-    
+
         self.TagName = tagname
-    
+
     def GetTagName(self):
         return self.TagName
-    
+
     def GetCurrentNodeId(self):
         return None
-    
+
     def GetInstancePath(self):
         return self.Controler.CTNFullName() + ".generated_master"
-    
+
     def GetTitle(self):
         return self.GetInstancePath()
-        
+
     def IsViewing(self, tagname):
         return self.GetInstancePath() == tagname
 
     def RefreshView(self):
         self.SlaveNodeEditor.RefreshIndexList()
-
--- a/canfestival/canfestival.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/canfestival/canfestival.py	Mon Aug 14 19:13:01 2017 +0300
@@ -67,7 +67,7 @@
                 "size": size,
                 "IEC_type": IECTypeConversion.get(typeinfos["name"]),
                 "var_name": "%s_%4.4x_%2.2x" % ("_".join(name.split()), index, subindex),
-                "location": "%s%s"%(SizeConversion[size], ".".join(map(str, current_location + 
+                "location": "%s%s"%(SizeConversion[size], ".".join(map(str, current_location +
                                                                                 (index, subindex)))),
                 "description": "",
                 "children": []})
@@ -102,7 +102,7 @@
       </xsd:element>
     </xsd:schema>
     """
-    
+
     EditorType = SlaveEditor
     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
 
@@ -125,7 +125,7 @@
                 self.CreateNewNode(name,       # Name - will be changed at build time
                                    id,         # NodeID - will be changed at build time
                                    "slave",    # Type
-                                   description,# description 
+                                   description,# description
                                    profile,    # profile
                                    filepath,   # prfile filepath
                                    NMT,        # NMT
@@ -134,7 +134,7 @@
                 self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
                                    0x00,         # NodeID - will be changed at build time
                                    "slave",      # Type
-                                   "",           # description 
+                                   "",           # description
                                    "None",       # profile
                                    "", # prfile filepath
                                    "heartbeat",  # NMT
@@ -156,48 +156,48 @@
         if self._View is not None:
             self._View.SetBusId(self.GetCurrentLocation())
         return self._View
-    
+
     def _ExportSlave(self):
-        dialog = wx.FileDialog(self.GetCTRoot().AppFrame, 
-                               _("Choose a file"), 
-                               os.path.expanduser("~"), 
-                               "%s.eds" % self.CTNName(),  
+        dialog = wx.FileDialog(self.GetCTRoot().AppFrame,
+                               _("Choose a file"),
+                               os.path.expanduser("~"),
+                               "%s.eds" % self.CTNName(),
                                _("EDS files (*.eds)|*.eds|All files|*.*"),
                                wx.SAVE|wx.OVERWRITE_PROMPT)
         if dialog.ShowModal() == wx.ID_OK:
             result = eds_utils.GenerateEDSFile(dialog.GetPath(), self.GetCurrentNodeCopy())
             if result:
                 self.GetCTRoot().logger.write_error(_("Error: Export slave failed\n"))
-        dialog.Destroy()  
-        
+        dialog.Destroy()
+
     ConfNodeMethods = [
         {"bitmap" : "ExportSlave",
-         "name" : _("Export slave"), 
+         "name" : _("Export slave"),
          "tooltip" : _("Export CanOpen slave to EDS file"),
          "method" : "_ExportSlave"},
     ]
-    
+
     def CTNTestModified(self):
         return self.ChangesToSave or self.OneFileHasChanged()
-        
+
     def OnCTNSave(self, from_project_path=None):
         return self.SaveCurrentInFile(self.GetSlaveODPath())
 
     def SetParamsAttribute(self, path, value):
         result = ConfigTreeNode.SetParamsAttribute(self, path, value)
-        
+
         # Filter IEC_Channel and Name, that have specific behavior
         if path == "BaseParams.IEC_Channel" and self._View is not None:
             self._View.SetBusId(self.GetCurrentLocation())
-        
+
         return result
-    
+
     def GetVariableLocationTree(self):
         current_location = self.GetCurrentLocation()
-        return GetSlaveLocationTree(self.CurrentNode, 
-                                    self.GetCurrentLocation(), 
+        return GetSlaveLocationTree(self.CurrentNode,
+                                    self.GetCurrentLocation(),
                                     self.BaseParams.getName())
-    
+
     def CTNGenerate_C(self, buildpath, locations):
         """
         Generate C code
@@ -230,10 +230,10 @@
 
     def LoadPrevious(self):
         self.LoadCurrentPrevious()
-    
+
     def LoadNext(self):
         self.LoadCurrentNext()
-    
+
     def GetBufferState(self):
         return self.GetCurrentBufferState()
 
@@ -242,30 +242,30 @@
 #--------------------------------------------------
 
 class MiniNodeManager(NodeManager):
-    
+
     def __init__(self, parent, filepath, fullname):
         NodeManager.__init__(self)
-        
+
         self.OpenFileInCurrent(filepath)
-            
+
         self.Parent = parent
         self.Fullname = fullname
-    
+
     def GetIconName(self):
         return None
-    
+
     def OnCloseEditor(self, view):
         self.Parent.OnCloseEditor(view)
-    
+
     def CTNFullName(self):
         return self.Fullname
-    
+
     def CTNTestModified(self):
         return False
-    
+
     def GetBufferState(self):
         return self.GetCurrentBufferState()
-    
+
     ConfNodeMethods = []
 
 class _NodeManager(NodeManager):
@@ -273,16 +273,16 @@
     def __init__(self, parent, *args, **kwargs):
         NodeManager.__init__(self, *args, **kwargs)
         self.Parent = parent
-        
+
     def __del__(self):
         self.Parent = None
-        
+
     def GetCurrentNodeName(self):
         return self.Parent.CTNName()
-    
+
     def GetCurrentNodeID(self):
         return self.Parent.CanFestivalNode.getNodeId()
-    
+
 class _NodeListCTN(NodeList):
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -295,20 +295,20 @@
         </xsd:complexType>
       </xsd:element>
     </xsd:schema>
-    """ 
-    
+    """
+
     EditorType = NetworkEditor
     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
-    
+
     def __init__(self):
         manager = _NodeManager(self)
         NodeList.__init__(self, manager)
         self.LoadProject(self.CTNPath())
         self.SetNetworkName(self.BaseParams.getName())
-    
+
     def GetCanDevice(self):
         return self.CanFestivalNode.getCAN_Device()
-    
+
     def SetParamsAttribute(self, path, value):
         if path == "CanFestivalNode.NodeId":
             nodeid = self.CanFestivalNode.getNodeId()
@@ -319,10 +319,10 @@
                     value += dir
                 if value < 0:
                     value = nodeid
-        
+
         value, refresh = ConfigTreeNode.SetParamsAttribute(self, path, value)
         refresh_network = False
-        
+
         # Filter IEC_Channel and Name, that have specific behavior
         if path == "BaseParams.IEC_Channel" and self._View is not None:
             self._View.SetBusId(self.GetCurrentLocation())
@@ -331,11 +331,11 @@
             refresh_network = True
         elif path == "CanFestivalNode.NodeId":
             refresh_network = True
-            
+
         if refresh_network and self._View is not None:
             wx.CallAfter(self._View.RefreshBufferState)
         return value, refresh
-    
+
     def GetVariableLocationTree(self):
         current_location = self.GetCurrentLocation()
         nodeindexes = self.SlaveNodes.keys()
@@ -345,17 +345,17 @@
                  "location": self.GetFullIEC_Channel(),
                  "children": [GetSlaveLocationTree(self.Manager.GetCurrentNodeCopy(),
                                                    current_location,
-                                                   _("Local entries"))] + 
-                             [GetSlaveLocationTree(self.SlaveNodes[nodeid]["Node"], 
-                                                   current_location + (nodeid,), 
+                                                   _("Local entries"))] +
+                             [GetSlaveLocationTree(self.SlaveNodes[nodeid]["Node"],
+                                                   current_location + (nodeid,),
                                                    self.SlaveNodes[nodeid]["Name"])
                               for nodeid in nodeindexes]
         }
-    
+
     _GeneratedMasterView = None
     def _ShowGeneratedMaster(self):
         self._OpenView("Generated master")
-        
+
     def _OpenView(self, name=None, onlyopened=False):
         if name == "Generated master":
             app_frame = self.GetCTRoot().AppFrame
@@ -365,37 +365,37 @@
                 if not os.path.exists(buildpath):
                     self.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
                     return
-                
+
                 masterpath = os.path.join(buildpath, "MasterGenerated.od")
                 if not os.path.exists(masterpath):
                     self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
                     return
-                
+
                 manager = MiniNodeManager(self, masterpath, self.CTNFullName())
                 self._GeneratedMasterView = MasterViewer(app_frame.TabsOpened, manager, app_frame, name)
-                
+
             if self._GeneratedMasterView is not None:
                 app_frame.EditProjectElement(self._GeneratedMasterView, self._GeneratedMasterView.GetInstancePath())
-            
+
             return self._GeneratedMasterView
         else:
             ConfigTreeNode._OpenView(self, name, onlyopened)
             if self._View is not None:
                 self._View.SetBusId(self.GetCurrentLocation())
             return self._View
-    
+
     ConfNodeMethods = [
         {"bitmap" : "ShowMaster",
-         "name" : _("Show Master"), 
+         "name" : _("Show Master"),
          "tooltip" : _("Show Master generated by config_utils"),
          "method" : "_ShowGeneratedMaster"}
     ]
-    
+
     def OnCloseEditor(self, view):
         ConfigTreeNode.OnCloseEditor(self, view)
         if self._GeneratedMasterView == view:
             self._GeneratedMasterView = None
-    
+
     def OnCTNClose(self):
         ConfigTreeNode.OnCTNClose(self)
         self._CloseView(self._GeneratedMasterView)
@@ -403,11 +403,11 @@
 
     def CTNTestModified(self):
         return self.ChangesToSave or self.HasChanged()
-        
+
     def OnCTNSave(self, from_project_path=None):
         self.SetRoot(self.CTNPath())
         if from_project_path is not None:
-            shutil.copytree(self.GetEDSFolder(from_project_path), 
+            shutil.copytree(self.GetEDSFolder(from_project_path),
                             self.GetEDSFolder())
         return self.SaveProject() is None
 
@@ -438,22 +438,22 @@
         res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
         if res :
             raise Exception, res
-        
+
         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
         dump(master, file)
         file.close()
-        
+
         return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-    
+
     def LoadPrevious(self):
         self.Manager.LoadCurrentPrevious()
-    
+
     def LoadNext(self):
         self.Manager.LoadCurrentNext()
-    
+
     def GetBufferState(self):
         return self.Manager.GetCurrentBufferState()
-    
+
 class RootClass:
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -464,7 +464,7 @@
       </xsd:element>
     </xsd:schema>
     """
-    
+
     CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
                        ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")]
     def GetParamsAttributes(self, path = None):
@@ -475,13 +475,13 @@
                     if child["name"] == "CAN_Driver":
                         child["type"] = local_canfestival_config.DLL_LIST
         return infos
-    
+
     def GetCanDriver(self):
         res = self.CanFestivalInstance.getCAN_Driver()
         if not res :
             return ""
         return res
-        
+
     def CTNGenerate_C(self, buildpath, locations):
         can_driver = self.GetCanDriver()
         if can_driver is not None:
@@ -494,7 +494,7 @@
         else:
             can_driver_name = ""
 
-        
+
         format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
                        "candriver" : can_driver_name,
                        "nodes_includes" : "",
@@ -515,7 +515,7 @@
         for child in self.IECSortedChildren():
             childlocstr = "_".join(map(str,child.GetCurrentLocation()))
             nodename = "OD_%s" % childlocstr
-            
+
             # Try to get Slave Node
             child_data = getattr(child, "CanFestivalSlaveNode", None)
             if child_data is None:
@@ -569,7 +569,7 @@
                 format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n    '%(
                        nodename,
                        child_data.getNodeId())
-    
+
             # Include generated OD headers
             format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
             # Declare CAN channels according user filled config
@@ -580,7 +580,7 @@
             format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
             format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
             format_dict["nodes_stop"] += 'NODE_STOP(%s)\n    '%(nodename)
-        
+
         filename = paths.AbsNeighbourFile(__file__,"cf_runtime.c")
         cf_main = open(filename).read() % format_dict
         cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
@@ -589,11 +589,10 @@
         f.close()
 
         res = [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
-        
+
         if can_driver is not None:
             can_driver_path = os.path.join(CanFestivalPath,"drivers",can_driver,can_driver_name)
             if os.path.exists(can_driver_path):
                 res += ((can_driver_name, file(can_driver_path,"rb")),)
 
         return res
-
--- a/canfestival/config_utils.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/canfestival/config_utils.py	Mon Aug 14 19:13:01 2017 +0300
@@ -30,7 +30,7 @@
                "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
                "LWORD":0x1B,"WSTRING":0x0B}
 
-# Constants for PDO types 
+# Constants for PDO types
 RPDO = 1
 TPDO = 2
 
@@ -61,7 +61,7 @@
     @param size: number of bytes generated
     @return: a string containing the value converted
     """
-    
+
     data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
     list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
     list_car.reverse()
@@ -71,12 +71,12 @@
 def GetNodePDOIndexes(node, type, parameters = False):
     """
     Find the PDO indexes of a node
-    @param node: node 
+    @param node: node
     @param type: type of PDO searched (RPDO or TPDO or both)
     @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
     @return: a list of indexes found
     """
-    
+
     indexes = []
     if type & RPDO:
         indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
@@ -91,14 +91,14 @@
 def SearchNodePDOMapping(loc_infos, node):
     """
     Find the PDO indexes of a node
-    @param node: node 
+    @param node: node
     @param type: type of PDO searched (RPDO or TPDO or both)
     @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
     @return: a list of indexes found
     """
-    
+
     model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
-    
+
     for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
         values = node.GetEntry(PDOidx)
         if values != None:
@@ -115,9 +115,9 @@
     @param cobid: PDO generated COB ID
     @param transmittype : PDO transmit type
     @param pdomapping: list of PDO mappings
-    @return: a tuple of value and number of parameters to add to DCF 
-    """
-    
+    @return: a tuple of value and number of parameters to add to DCF
+    """
+
     dcfdata=[]
     # Create entry for RPDO or TPDO parameters and Disable PDO
     #           ---- INDEX -----   --- SUBINDEX ----   ----- SIZE ------   ------ DATA ------
@@ -152,7 +152,7 @@
         self.TrashVariables = {}
         # Dictionary of pointed variables
         self.PointedVariables = {}
-        
+
         self.NodeList = nodelist
         self.Manager = self.NodeList.Manager
         self.MasterNode = self.Manager.GetCurrentNodeCopy()
@@ -161,18 +161,18 @@
 
     def GetPointedVariables(self):
         return self.PointedVariables
-    
+
     def RemoveUsedNodeCobId(self, node):
         """
         Remove all PDO COB ID used by the given node from the list of available COB ID
         @param node: node
         @return: a tuple of number of RPDO and TPDO for the node
         """
-        
+
         # Get list of all node TPDO and RPDO indexes
         nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
         nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
-        
+
         # Mark all the COB ID of the node already mapped PDO as not available
         for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
             pdo_cobid = node.GetEntry(PdoIdx, 0x01)
@@ -182,20 +182,20 @@
             # Remove COB ID from the list of available COB ID
             if pdo_cobid in self.ListCobIDAvailable:
                 self.ListCobIDAvailable.remove(pdo_cobid)
-        
+
         return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
 
-    
+
     def PrepareMasterNode(self):
         """
         Add mandatory entries for DCF generation into MasterNode.
         """
-        
+
         # Adding DCF entry into Master node
         if not self.MasterNode.IsEntry(0x1F22):
             self.MasterNode.AddEntry(0x1F22, 1, "")
         self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
-        
+
         # Adding trash mappable variables for unused mapped datas
         idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
         # Add an entry for storing unexpected all variable
@@ -206,9 +206,9 @@
             self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
             # Store the mapping value for this entry
             self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
-        
+
         RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
-        
+
         # Store the indexes of the first RPDO and TPDO available for MasterNode
         self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
 
@@ -216,9 +216,9 @@
         for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
             node = nodeinfos["Node"]
             node.SetNodeID(nodeid)
-            
+
             RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
-            
+
             # Get Slave's default SDO server parameters
             RSDO_cobid = node.GetEntry(0x1200,0x01)
             if not RSDO_cobid:
@@ -226,20 +226,20 @@
             TSDO_cobid = node.GetEntry(0x1200,0x02)
             if not TSDO_cobid:
                 TSDO_cobid = 0x580 + nodeid
-            
+
             # Configure Master's SDO parameters entries
             self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
             self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
             self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
-            self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)        
-        
-    
+            self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)
+
+
     def GetMasterNode(self):
         """
         Return MasterNode.
         """
         return self.MasterNode
-    
+
     def AddParamsToDCF(self, nodeid, data, nbparams):
         """
         Add entry to DCF, for the requested nodeID
@@ -249,19 +249,19 @@
         """
         # Get current DCF for slave
         nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
-        
+
         # Extract data and number of params in current DCF
         if nodeDCF != None and nodeDCF != '':
             tmpnbparams = [i for i in nodeDCF[:4]]
             tmpnbparams.reverse()
             nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
             data = nodeDCF[4:] + data
-        
+
         # Build new DCF
         dcf = LE_to_BE(nbparams, 0x04) + data
         # Set new DCF for slave
         self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
-    
+
     def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
         """
         Search a not configured PDO for a slave
@@ -275,7 +275,7 @@
             index = PDOTypeBaseIndex[pdotype]
         else:
             index = start_index
-        
+
         # Search for all PDO possible index until find a configurable PDO
         # starting from start_index
         while index < PDOTypeBaseIndex[pdotype] + 0x200:
@@ -296,7 +296,7 @@
                     return index, cobid, values[0]
             index += 1
         return None
-    
+
     def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
         """
         Record a new mapping request for a slave, and add related slave config to the DCF
@@ -305,16 +305,16 @@
         @param pdomapping: list od variables to map with PDO
         """
         # Add an entry to MasterMapping
-        self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], 
+        self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype],
             "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
-        
+
         # Return the data to add to DCF
         if sync_TPDOs:
             return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
         else:
             return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
         return 0, ""
-    
+
     def GenerateDCF(self, locations, current_location, sync_TPDOs):
         """
         Generate Concise DCF of MasterNode for the locations list given
@@ -322,18 +322,18 @@
         @param current_location: tuple of the located prefixes not to be considered
         @param sync_TPDOs: indicate if TPDO must be synchronous
         """
-        
+
         #-------------------------------------------------------------------------------
         #               Verify that locations correspond to real slave variables
         #-------------------------------------------------------------------------------
-        
+
         # Get list of locations check if exists and mappables -> put them in IECLocations
         for location in locations:
             COlocationtype = IECToCOType[location["IEC_TYPE"]]
             name = location["NAME"]
             if name in self.IECLocations:
                 if self.IECLocations[name]["type"] != COlocationtype:
-                    raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
+                    raise PDOmappingException, _("Type conflict for location \"%s\"") % name
             else:
                 # Get only the part of the location that concern this node
                 loc = location["LOC"][len(current_location):]
@@ -342,30 +342,30 @@
                     raise PDOmappingException, _("Bad location size : %s") % str(loc)
                 elif len(loc) == 2:
                     continue
-                
+
                 direction = location["DIR"]
-                
+
                 sizelocation = location["SIZE"]
-                
+
                 # Extract and check nodeid
                 nodeid, index, subindex = loc[:3]
-                
+
                 # Check Id is in slave node list
                 if nodeid not in self.NodeList.SlaveNodes.keys():
                     raise PDOmappingException, _("Non existing node ID : {a1} (variable {a2})").format(a1 = nodeid, a2 = name)
-                
+
                 # Get the model for this node (made from EDS)
                 node = self.NodeList.SlaveNodes[nodeid]["Node"]
-                
+
                 # Extract and check index and subindex
                 if not node.IsEntry(index, subindex):
                     msg = _("No such index/subindex ({a1},{a2}) in ID : {a3} (variable {a4})").\
                           format(a1 = "%x" % index, a2 ="%x" % subindex, a3 = nodeid, a4 = name)
                     raise PDOmappingException, msg
-                
+
                 # Get the entry info
                 subentry_infos = node.GetSubentryInfos(index, subindex)
-                
+
                 # If a PDO mappable
                 if subentry_infos and subentry_infos["pdo"]:
                     if sizelocation == "X" and len(loc) > 3:
@@ -376,11 +376,11 @@
                         raise PDOmappingException, msg
                     else:
                         numbit = None
-                    
+
                     if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
                         raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3}  for location \"{a4}\"").\
                             format(a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name)
-                    
+
                     typeinfos = node.GetEntryInfos(COlocationtype)
                     self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
                                                 "nodeid": nodeid, "index": index,"subindex": subindex,
@@ -388,21 +388,21 @@
                 else:
                     raise PDOmappingException, _("Not PDO mappable variable : '{a1}' (ID:{a2},Idx:{a3},sIdx:{a4}))").\
                         format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex)
-        
+
         #-------------------------------------------------------------------------------
         #                         Search for locations already mapped
         #-------------------------------------------------------------------------------
-        
+
         for name, locationinfos in self.IECLocations.items():
             node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
-            
+
             # Search if slave has a PDO mapping this locations
             result = SearchNodePDOMapping(locationinfos, node)
             if result != None:
                 index, subindex = result
                 # Get COB ID of the PDO
                 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
-                
+
                 # Add PDO to MasterMapping
                 if cobid not in self.MasterMapping.keys():
                     # Verify that PDO transmit type is conform to sync_TPDOs
@@ -414,10 +414,10 @@
                         else:
                             # Change TransmitType to ASYCHRONE
                             data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
-                        
-                        # Add entry to slave dcf to change transmit type of 
+
+                        # Add entry to slave dcf to change transmit type of
                         self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
-                                    
+
                     mapping = [None]
                     values = node.GetEntry(index)
                     # Store the size of each entry mapped in PDO
@@ -425,7 +425,7 @@
                         if value != 0:
                             mapping.append(value % 0x100)
                     self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
-            
+
                 # Indicate that this PDO entry must be saved
                 if locationinfos["bit"] is not None:
                     if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
@@ -434,24 +434,24 @@
                         self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
                 else:
                     self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
-                
+
             else:
                 # Add location to those that haven't been mapped yet
                 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
                     self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
                 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
-    
+
         #-------------------------------------------------------------------------------
         #                         Build concise DCF for the others locations
         #-------------------------------------------------------------------------------
-        
+
         for nodeid, locations in self.LocationsNotMapped.items():
             node = self.NodeList.SlaveNodes[nodeid]["Node"]
-            
+
             # Initialize number of params and data to add to node DCF
             nbparams = 0
             dataparams = ""
-            
+
             # Generate the best PDO mapping for each type of PDO
             for pdotype in (TPDO, RPDO):
                 if len(locations[pdotype]) > 0:
@@ -483,78 +483,78 @@
                         data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
                         dataparams += data
                         nbparams += nbaddedparams
-                
+
             # Add number of params and data to node DCF
             self.AddParamsToDCF(nodeid, dataparams, nbparams)
-        
+
         #-------------------------------------------------------------------------------
         #                         Master Node Configuration
         #-------------------------------------------------------------------------------
-        
+
         # Generate Master's Configuration from informations stored in MasterMapping
         for cobid, pdo_infos in self.MasterMapping.items():
             # Get next PDO index in MasterNode for this PDO type
             current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
-            
+
             # Search if there is already a PDO in MasterNode with this cob id
             for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
                 if self.MasterNode.GetEntry(idx, 1) == cobid:
                     current_idx = idx
-            
+
             # Add a PDO to MasterNode if not PDO have been found
             if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
                 addinglist = [current_idx, current_idx + 0x200]
                 self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
                 self.MasterNode.SetEntry(current_idx, 0x01, cobid)
-                
+
                 # Increment the number of PDO for this PDO type
                 self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
-            
+
             # Change the transmit type of the PDO
             if sync_TPDOs:
                 self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
             else:
                 self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
-            
+
             mapping = []
             for item in pdo_infos["mapping"]:
                 if isinstance(item, ListType):
                     mapping.extend(item)
                 else:
                     mapping.append(item)
-            
+
             # Add some subentries to PDO mapping if there is not enough
             if len(mapping) > 1:
                 self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
-            
+
             # Generate MasterNode's PDO mapping
             for subindex, variable in enumerate(mapping):
                 if subindex == 0:
                     continue
                 new_index = False
-                
+
                 if isinstance(variable, (IntType, LongType)):
                     # If variable is an integer then variable is unexpected
                     self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
                 else:
                     typeidx, varname = variable
                     variable_infos = self.IECLocations[varname]
-                    
+
                     # Calculate base index for storing variable
                     mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
                                      VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
                                      variable_infos["nodeid"]
-                    
+
                     # Generate entry name
                     indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
                                                  variable_infos["sizelocation"],
                                                  '_'.join(map(str,current_location)),
-                                                 variable_infos["nodeid"])    
-                    
-                    # Search for an entry that has an empty subindex 
+                                                 variable_infos["nodeid"])
+
+                    # Search for an entry that has an empty subindex
                     while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
                         # Entry doesn't exist
-                        if not self.MasterNode.IsEntry(mapvariableidx):    
+                        if not self.MasterNode.IsEntry(mapvariableidx):
                             # Add entry to MasterNode
                             self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
                             new_index = True
@@ -567,7 +567,7 @@
                                 mapvariableidx += 8 * VariableIncrement
                             else:
                                 break
-                                
+
                     # Verify that a not full entry has been found
                     if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
                         # Generate subentry name
@@ -582,13 +582,13 @@
                         # Add informations to the new subentry created
                         self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
                         self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
-                        
+
                         # Set value of the PDO mapping
                         typeinfos = self.Manager.GetEntryInfos(typeidx)
                         if typeinfos != None:
                             value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
                             self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
-                        
+
                         # Add variable to pointed variables
                         self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
 
@@ -605,7 +605,7 @@
     @param nodelist: CanFestival network editor model
     @return: a modified copy of the given CanFestival network editor model
     """
-    
+
     dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
     dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
     masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
@@ -621,7 +621,7 @@
         name = location["NAME"]
         if name in IECLocations:
             if IECLocations[name] != COlocationtype:
-                raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
+                raise PDOmappingException, _("Type conflict for location \"%s\"") % name
         else:
             # Get only the part of the location that concern this node
             loc = location["LOC"][len(current_location):]
@@ -630,25 +630,25 @@
                 raise PDOmappingException, _("Bad location size : %s") % str(loc)
             elif len(loc) != 2:
                 continue
-            
+
             # Extract and check nodeid
             index, subindex = loc[:2]
-            
+
             # Extract and check index and subindex
             if not slave.IsEntry(index, subindex):
                 raise PDOmappingException, _("No such index/subindex ({a1},{a2}) (variable {a3})").\
                     format(a1 = "%x" % index, a2 = "%x" % subindex, a3 = name)
-            
+
             # Get the entry info
-            subentry_infos = slave.GetSubentryInfos(index, subindex)    
+            subentry_infos = slave.GetSubentryInfos(index, subindex)
             if subentry_infos["type"] != COlocationtype:
                 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\
                     format( a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name)
-            
+
             IECLocations[name] = COlocationtype
             pointers[(index, subindex)] = name
     return pointers
-        
+
 if __name__ == "__main__":
     import os, sys, getopt
 
@@ -667,7 +667,7 @@
             Use with caution. Be sure that config_utils
             is currently working properly.
 """%sys.argv[0]
-    
+
     # Boolean that indicate if reference result must be redefined
     reset = False
 
@@ -693,15 +693,15 @@
         base_folder = os.path.split(base_folder)[0]
     # Add CanFestival folder to search pathes
     sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
-    
+
     from nodemanager import *
     from nodelist import *
-    
+
     # Open the test nodelist contained into test_config folder
     manager = NodeManager()
     nodelist = NodeList(manager)
     result = nodelist.LoadProject("test_config")
-    
+
     # List of locations, we try to map for test
     locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
                  {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
@@ -713,34 +713,34 @@
                  {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
                  {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
                  {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
-    
+
     # Generate MasterNode configuration
     try:
         masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
     except ValueError, message:
         print "%s\nTest Failed!"%message
         sys.exit()
-    
+
     import pprint
-    # Get Text corresponding to MasterNode 
+    # Get Text corresponding to MasterNode
     result_node = masternode.PrintString()
     result_vars = pprint.pformat(pointedvariables)
     result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
-    
+
     # If reset has been choosen
     if reset:
         # Write Text into reference result file
         testfile = open("test_config/result.txt", "w")
         testfile.write(result)
         testfile.close()
-        
+
         print "Reset Successful!"
     else:
         import os
-        
+
         testfile = open("test_config/result_tmp.txt", "w")
         testfile.write(result)
         testfile.close()
-        
+
         os.system("diff test_config/result.txt test_config/result_tmp.txt")
         os.remove("test_config/result_tmp.txt")
--- a/controls/CustomToolTip.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/CustomToolTip.py	Mon Aug 14 19:13:01 2017 +0300
@@ -39,32 +39,32 @@
 """
 
 class CustomToolTip(wx.PopupWindow):
-    
+
     def __init__(self, parent, tip, restricted=True):
         """
         Constructor
         @param parent: Parent window
         @param tip: Tip text (may be multiline)
-        @param restricted: Tool tip must follow size restriction in line and 
+        @param restricted: Tool tip must follow size restriction in line and
             characters number defined (default True)
         """
         wx.PopupWindow.__init__(self, parent)
-        
+
         self.Restricted = restricted
-        
+
         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.SetTip(tip)
-        
+
         # Initialize text font style
         self.Font = wx.Font(
-            faces["size"], 
-            wx.SWISS, 
-            wx.NORMAL, 
-            wx.NORMAL, 
+            faces["size"],
+            wx.SWISS,
+            wx.NORMAL,
+            wx.NORMAL,
             faceName = faces["mono"])
-        
+
         self.Bind(wx.EVT_PAINT, self.OnPaint)
-    
+
     def SetFont(self, font):
         """
         Set tool tip text font style
@@ -72,7 +72,7 @@
         """
         self.Font = font
         self.RefreshTip()
-    
+
     def SetTip(self, tip):
         """
         Set tool tip text
@@ -97,11 +97,11 @@
                     self.Tip.append(new_line)
                 else:
                     self.Tip.append(line)
-            
+
             # Restrict number of lines
             if len(self.Tip) > TOOLTIP_MAX_LINE:
                 self.Tip = self.Tip[:TOOLTIP_MAX_LINE]
-                
+
                 # Add ... to the end of last line to indicate that tool tip
                 # text is too long
                 if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3:
@@ -111,10 +111,10 @@
                         [:TOOLTIP_MAX_CHARACTERS - 3] + "..."
         else:
             self.Tip = tip.splitlines()
-        
+
         # Prevent to call wx method in non-wx threads
         wx.CallAfter(self.RefreshTip)
-    
+
     def SetToolTipPosition(self, pos):
         """
         Set tool tip position
@@ -122,32 +122,32 @@
         """
         # Get screen size to prevent tool tip to go out of the screen
         screen_width, screen_height = wx.GetDisplaySize()
-        
+
         # Calculate position of tool tip to stay in screen limits
         tip_width, tip_height = self.GetToolTipSize()
         self.SetPosition(wx.Point(
             max(0, min(pos.x, screen_width - tip_width)),
             max(0, min(pos.y, screen_height - tip_height))))
-    
+
     def GetToolTipSize(self):
         """
         Get tool tip size according to tip text and restriction
         @return: wx.Size(tool_tip_width, tool_tip_height)
         """
         max_width = max_height = 0
-        
+
         # Create a memory DC for calculating text extent
         dc = wx.MemoryDC()
         dc.SetFont(self.Font)
-        
+
         # Compute max tip text size
         for line in self.Tip:
             w, h = dc.GetTextExtent(line)
             max_width = max(max_width, w)
             max_height += h
-        
+
         return wx.Size(max_width + 4, max_height + 4)
-    
+
     def RefreshTip(self):
         """
         Refresh tip on screen
@@ -156,10 +156,10 @@
         if self:
             # Refresh tool tip size and position
             self.SetClientSize(self.GetToolTipSize())
-            
+
             # Redraw tool tip
             self.Refresh()
-    
+
     def OnPaint(self, event):
         """
         Callback for Paint Event
@@ -168,26 +168,26 @@
         # Get buffered paint DC for tool tip
         dc = wx.AutoBufferedPaintDC(self)
         dc.Clear()
-        
+
         # Set DC drawing style
         dc.SetPen(wx.BLACK_PEN)
         dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170)))
         dc.SetFont(self.Font)
-        
+
         # Draw Tool tip
         dc.BeginDrawing()
         tip_width, tip_height = self.GetToolTipSize()
-        
+
         # Draw background rectangle
         dc.DrawRectangle(0, 0, tip_width, tip_height)
-        
+
         # Draw tool tip text
         line_offset = 0
         for line in self.Tip:
             dc.DrawText(line, 2, line_offset + 2)
             line_width, line_height = dc.GetTextExtent(line)
             line_offset += line_height
-        
+
         dc.EndDrawing()
-        
+
         event.Skip()
--- a/controls/CustomTree.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/CustomTree.py	Mon Aug 14 19:13:01 2017 +0300
@@ -44,30 +44,30 @@
 CT.GenericTreeItem.GetCurrentCheckedImage = GetCurrentCheckedImage
 
 class CustomTree(CT.CustomTreeCtrl):
-    
+
     def __init__(self, *args, **kwargs):
         CT.CustomTreeCtrl.__init__(self, *args, **kwargs)
-        
+
         self.BackgroundBitmap = None
         self.BackgroundAlign = wx.ALIGN_LEFT|wx.ALIGN_TOP
-        
+
         self.AddMenu = None
         self.Enabled = False
-        
+
         self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
-    
+
     def SetBackgroundBitmap(self, bitmap, align):
         self.BackgroundBitmap = bitmap
         self.BackgroundAlign = align
-    
+
     def SetImageListCheck(self, sizex, sizey, imglist=None):
         CT.CustomTreeCtrl.SetImageListCheck(self, sizex, sizey, imglist=None)
-        
+
         self.ExtraImages = {}
         for image in ["function", "functionBlock", "program"]:
             self.ExtraImages[image] = self._imageListCheck.Add(GetBitmap(image.upper()))
-    
+
     def SetItemExtraImage(self, item, bitmap):
         dc = wx.ClientDC(self)
         image = self.ExtraImages.get(bitmap)
@@ -76,45 +76,45 @@
         else:
             item.SetExtraImage(None)
         self.CalculateSize(item, dc)
-        self.RefreshLine(item)   
-        
+        self.RefreshLine(item)
+
     def SetAddMenu(self, add_menu):
         self.AddMenu = add_menu
-    
+
     def Enable(self, enabled):
         self.Enabled = enabled
-    
+
     def GetBitmapRect(self):
         client_size = self.GetClientSize()
         bitmap_size = self.BackgroundBitmap.GetSize()
-        
+
         if self.BackgroundAlign & wx.ALIGN_RIGHT:
             x = client_size[0] - bitmap_size[0]
         elif self.BackgroundAlign & wx.ALIGN_CENTER_HORIZONTAL:
             x = (client_size[0] - bitmap_size[0]) / 2
         else:
             x = 0
-        
+
         if self.BackgroundAlign & wx.ALIGN_BOTTOM:
             y = client_size[1] - bitmap_size[1]
         elif self.BackgroundAlign & wx.ALIGN_CENTER_VERTICAL:
             y = (client_size[1] - bitmap_size[1]) / 2
         else:
             y = 0
-        
+
         return wx.Rect(x, y, bitmap_size[0], bitmap_size[1])
-    
+
     def OnLeftUp(self, event):
         if self.Enabled:
             pos = event.GetPosition()
             item, flags = self.HitTest(pos)
-            
+
             bitmap_rect = self.GetBitmapRect()
-            if (bitmap_rect.InsideXY(pos.x, pos.y) or 
+            if (bitmap_rect.InsideXY(pos.x, pos.y) or
                 flags & wx.TREE_HITTEST_NOWHERE) and self.AddMenu is not None:
                 wx.CallAfter(self.PopupMenuXY, self.AddMenu, pos.x, pos.y)
         event.Skip()
-    
+
     def OnEraseBackground(self, event):
         dc = event.GetDC()
 
@@ -122,12 +122,12 @@
             dc = wx.ClientDC(self)
             rect = self.GetUpdateRegion().GetBox()
             dc.SetClippingRect(rect)
-        
+
         dc.Clear()
-        
+
         bitmap_rect = self.GetBitmapRect()
         dc.DrawBitmap(self.BackgroundBitmap, bitmap_rect.x, bitmap_rect.y)
-    
+
     def OnScroll(self, event):
         wx.CallAfter(self.Refresh)
         event.Skip()
--- a/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/DebugVariableGraphicViewer.py	Mon Aug 14 19:13:01 2017 +0300
@@ -83,23 +83,23 @@
             min_value = range_min
         elif range_min is not None:
             min_value = min(min_value, range_min)
-        
+
         # Update maximal range value
         if max_value is None:
             max_value = range_max
         elif range_min is not None:
             max_value = max(max_value, range_max)
-    
+
     # Calculate range center and width if at least one valid range is defined
     if min_value is not None and max_value is not None:
         center = (min_value + max_value) / 2.
         range_size = max(1.0, max_value - min_value)
-    
+
     # Set default center and with if no valid range is defined
     else:
         center = 0.5
         range_size = 1.0
-    
+
     # Return range expended from 10 %
     return center - range_size * 0.55, center + range_size * 0.55
 
@@ -113,7 +113,7 @@
 """
 
 class DebugVariableGraphicDropTarget(wx.TextDropTarget):
-    
+
     def __init__(self, parent, window):
         """
         Constructor
@@ -123,7 +123,7 @@
         wx.TextDropTarget.__init__(self)
         self.ParentControl = parent
         self.ParentWindow = window
-        
+
     def __del__(self):
         """
         Destructor
@@ -132,7 +132,7 @@
         # Panel
         self.ParentControl = None
         self.ParentWindow = None
-        
+
     def OnDragOver(self, x, y, d):
         """
         Function called when mouse is dragged over Drop Target
@@ -142,9 +142,9 @@
         """
         # Signal parent that mouse is dragged over
         self.ParentControl.OnMouseDragging(x, y)
-        
+
         return wx.TextDropTarget.OnDragOver(self, x, y, d)
-        
+
     def OnDropText(self, x, y, data):
         """
         Function called when mouse is released in Drop Target
@@ -154,9 +154,9 @@
         """
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
-        
+
         message = None
-        
+
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
@@ -165,54 +165,54 @@
         except:
             message = _("Invalid value \"%s\" for debug variable")%data
             values = None
-        
+
         # Display message if data is invalid
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
-        
+
         # Data contain a reference to a variable to debug
         elif values[1] == "debug":
             target_idx = self.ParentControl.GetIndex()
-            
+
             # If mouse is dropped in graph canvas bounding box and graph is
             # not 3D canvas, graphs will be merged
             rect = self.ParentControl.GetAxesBoundingBox()
             if not self.ParentControl.Is3DCanvas() and rect.InsideXY(x, y):
                 # Default merge type is parallel
                 merge_type = GRAPH_PARALLEL
-                
+
                 # If mouse is dropped in left part of graph canvas, graph
                 # wall be merged orthogonally
-                merge_rect = wx.Rect(rect.x, rect.y, 
+                merge_rect = wx.Rect(rect.x, rect.y,
                                      rect.width / 2., rect.height)
                 if merge_rect.InsideXY(x, y):
                     merge_type = GRAPH_ORTHOGONAL
-                
+
                 # Merge graphs
-                wx.CallAfter(self.ParentWindow.MergeGraphs, 
-                             values[0], target_idx, 
+                wx.CallAfter(self.ParentWindow.MergeGraphs,
+                             values[0], target_idx,
                              merge_type, force=True)
-                
+
             else:
                 width, height = self.ParentControl.GetSize()
-                
+
                 # Get Before which Viewer the variable has to be moved or added
                 # according to the position of mouse in Viewer.
                 if y > height / 2:
                     target_idx += 1
-                
+
                 # Drag'n Drop is an internal is an internal move inside Debug
-                # Variable Panel 
+                # Variable Panel
                 if len(values) > 2 and values[2] == "move":
-                    self.ParentWindow.MoveValue(values[0], 
+                    self.ParentWindow.MoveValue(values[0],
                                                 target_idx)
-                
+
                 # Drag'n Drop was initiated by another control of Beremiz
                 else:
-                    self.ParentWindow.InsertValue(values[0], 
-                                                  target_idx, 
+                    self.ParentWindow.InsertValue(values[0],
+                                                  target_idx,
                                                   force=True)
-    
+
     def OnLeave(self):
         """
         Function called when mouse is leave Drop Target
@@ -220,15 +220,15 @@
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
         return wx.TextDropTarget.OnLeave(self)
-    
+
     def ShowMessage(self, message):
         """
         Show error message in Error Dialog
         @param message: Error message to display
         """
-        dialog = wx.MessageDialog(self.ParentWindow, 
-                                  message, 
-                                  _("Error"), 
+        dialog = wx.MessageDialog(self.ParentWindow,
+                                  message,
+                                  _("Error"),
                                   wx.OK|wx.ICON_ERROR)
         dialog.ShowModal()
         dialog.Destroy()
@@ -243,7 +243,7 @@
 """
 
 class DebugVariableGraphicViewer(DebugVariableViewer, FigureCanvas):
-    
+
     def __init__(self, parent, window, items, graph_type):
         """
         Constructor
@@ -253,36 +253,36 @@
         @param graph_type: Graph display type (Parallel or orthogonal)
         """
         DebugVariableViewer.__init__(self, window, items)
-        
+
         self.GraphType = graph_type        # Graph type display
         self.CursorTick = None             # Tick of the graph cursor
-        
+
         # Mouse position when start dragging
         self.MouseStartPos = None
         # Tick when moving tick start
         self.StartCursorTick = None
         # Canvas size when starting to resize canvas
-        self.CanvasStartSize = None        
-        
+        self.CanvasStartSize = None
+
         # List of current displayed contextual buttons
         self.ContextualButtons = []
         # Reference to item for which contextual buttons was displayed
         self.ContextualButtonsItem = None
-        
+
         # Flag indicating that zoom fit current displayed data range or whole
         # data range if False
         self.ZoomFit = False
-        
+
         # Create figure for drawing graphs
         self.Figure = matplotlib.figure.Figure(facecolor='w')
         # Defined border around figure in canvas
-        self.Figure.subplotpars.update(top=0.95, left=0.1, 
+        self.Figure.subplotpars.update(top=0.95, left=0.1,
                                        bottom=0.1, right=0.95)
-        
+
         FigureCanvas.__init__(self, parent, -1, self.Figure)
         self.SetWindowStyle(wx.WANTS_CHARS)
         self.SetBackgroundColour(wx.WHITE)
-        
+
         # Bind wx events
         self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
@@ -290,42 +290,42 @@
         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
         self.Bind(wx.EVT_SIZE, self.OnResize)
-        
+
         # Set canvas min size
         canvas_size = self.GetCanvasMinSize()
         self.SetMinSize(canvas_size)
-        
+
         # Define Viewer drop target
         self.SetDropTarget(DebugVariableGraphicDropTarget(self, window))
-        
+
         # Connect matplotlib events
         self.mpl_connect('button_press_event', self.OnCanvasButtonPressed)
         self.mpl_connect('motion_notify_event', self.OnCanvasMotion)
         self.mpl_connect('button_release_event', self.OnCanvasButtonReleased)
         self.mpl_connect('scroll_event', self.OnCanvasScroll)
-        
+
         # Add buttons for zooming on current displayed data range
         self.Buttons.append(
                 GraphButton(0, 0, "fit_graph", self.OnZoomFitButton))
-        
+
         # Add buttons for changing canvas size with predefined height
         for size, bitmap in zip(
                 [SIZE_MINI, SIZE_MIDDLE, SIZE_MAXI],
                 ["minimize_graph", "middle_graph", "maximize_graph"]):
             self.Buttons.append(
-                    GraphButton(0, 0, bitmap, 
+                    GraphButton(0, 0, bitmap,
                                 self.GetOnChangeSizeButton(size)))
-        
+
         # Add buttons for exporting graph values to clipboard and close graph
         for bitmap, callback in [
                 ("export_graph_mini", self.OnExportGraphButton),
                 ("delete_graph", self.OnCloseButton)]:
             self.Buttons.append(GraphButton(0, 0, bitmap, callback))
-        
+
         # Update graphs elements
         self.ResetGraphics()
         self.RefreshLabelsPosition(canvas_size.height)
-    
+
     def AddItem(self, item):
         """
         Add an item to the list of items displayed by Viewer
@@ -333,14 +333,14 @@
         """
         DebugVariableViewer.AddItem(self, item)
         self.ResetGraphics()
-        
+
     def RemoveItem(self, item):
         """
         Remove an item from the list of items displayed by Viewer
         @param item: Item to remove from the list
         """
         DebugVariableViewer.RemoveItem(self, item)
-        
+
         # If list of items is not empty
         if not self.ItemsIsEmpty():
             # Return to parallel graph if there is only one item
@@ -348,51 +348,51 @@
             if len(self.Items) == 1:
                 self.GraphType = GRAPH_PARALLEL
             self.ResetGraphics()
-    
+
     def SetCursorTick(self, cursor_tick):
         """
         Set cursor tick
         @param cursor_tick: Cursor tick
         """
         self.CursorTick = cursor_tick
-    
+
     def SetZoomFit(self, zoom_fit):
         """
         Set flag indicating that zoom fit current displayed data range
         @param zoom_fit: Flag for zoom fit (False: zoom fit whole data range)
         """
-        # Flag is different from the actual one 
+        # Flag is different from the actual one
         if zoom_fit != self.ZoomFit:
             # Save new flag value
             self.ZoomFit = zoom_fit
-            
+
             # Update button for zoom fit bitmap
             self.Buttons[0].SetBitmap("full_graph" if zoom_fit else "fit_graph")
-            
+
             # Refresh canvas
             self.RefreshViewer()
-        
+
     def SubscribeAllDataConsumers(self):
         """
         Function that unsubscribe and remove every item that store values of
         a variable that doesn't exist in PLC anymore
         """
         DebugVariableViewer.SubscribeAllDataConsumers(self)
-        
+
         # Graph still have data to display
         if not self.ItemsIsEmpty():
             # Reset flag indicating that zoom fit current displayed data range
             self.SetZoomFit(False)
-            
+
             self.ResetGraphics()
-    
+
     def Is3DCanvas(self):
         """
         Return if Viewer is a 3D canvas
         @return: True if Viewer is a 3D canvas
         """
         return self.GraphType == GRAPH_ORTHOGONAL and len(self.Items) == 3
-    
+
     def GetButtons(self):
         """
         Return list of buttons defined in Viewer
@@ -400,7 +400,7 @@
         """
         # Add contextual buttons to default buttons
         return self.Buttons + self.ContextualButtons
-    
+
     def PopupContextualButtons(self, item, rect, direction=wx.RIGHT):
         """
         Show contextual menu for item aside a label of this item defined
@@ -412,19 +412,19 @@
         # Return immediately if contextual menu for item is already shown
         if self.ContextualButtonsItem == item:
             return
-        
+
         # Close already shown contextual menu
         self.DismissContextualButtons()
-        
+
         # Save item for which contextual menu is shown
         self.ContextualButtonsItem = item
-        
+
         # If item variable is forced, add button for release variable to
         # contextual menu
         if self.ContextualButtonsItem.IsForced():
             self.ContextualButtons.append(
                 GraphButton(0, 0, "release", self.OnReleaseItemButton))
-        
+
         # Add other buttons to contextual menu
         for bitmap, callback in [
                 ("force", self.OnForceItemButton),
@@ -432,13 +432,13 @@
                 ("delete_graph", self.OnRemoveItemButton)]:
             self.ContextualButtons.append(
                     GraphButton(0, 0, bitmap, callback))
-        
+
         # If buttons are shown at left side or upper side of rect, positions
         # will be set in reverse order
         buttons = self.ContextualButtons[:]
         if direction in [wx.TOP, wx.LEFT]:
              buttons.reverse()
-             
+
         # Set contextual menu buttons position aside rect depending on
         # direction given
         offset = 0
@@ -458,10 +458,10 @@
                 offset += h
             button.SetPosition(x, y)
             button.Show()
-        
+
         # Refresh canvas
         self.ParentWindow.ForceRefresh()
-    
+
     def DismissContextualButtons(self):
         """
         Close current shown contextual menu
@@ -469,14 +469,14 @@
         # Return immediately if no contextual menu is shown
         if self.ContextualButtonsItem is None:
             return
-        
+
         # Reset variables corresponding to contextual menu
         self.ContextualButtonsItem = None
         self.ContextualButtons = []
-        
+
         # Refresh canvas
         self.ParentWindow.ForceRefresh()
-    
+
     def IsOverContextualButton(self, x, y):
         """
         Return if point is over one contextual button of Viewer
@@ -488,7 +488,7 @@
             if button.HitTest(x, y):
                 return button
         return None
-    
+
     def ExportGraph(self, item=None):
         """
         Export item(s) data to clipboard in CSV format
@@ -497,17 +497,17 @@
         """
         self.ParentWindow.CopyDataToClipboard(
             [(item, [entry for entry in item.GetData()])
-             for item in (self.Items 
-                          if item is None 
+             for item in (self.Items
+                          if item is None
                           else [item])])
-    
+
     def OnZoomFitButton(self):
         """
         Function called when Viewer Zoom Fit button is pressed
         """
         # Toggle zoom fit flag value
         self.SetZoomFit(not self.ZoomFit)
-        
+
     def GetOnChangeSizeButton(self, height):
         """
         Function that generate callback function for change Viewer height to
@@ -518,32 +518,32 @@
         def OnChangeSizeButton():
             self.SetCanvasHeight(height)
         return OnChangeSizeButton
-    
+
     def OnExportGraphButton(self):
         """
         Function called when Viewer Export button is pressed
         """
         # Export data of every item in Viewer
         self.ExportGraph()
-    
+
     def OnForceItemButton(self):
         """
         Function called when contextual menu Force button is pressed
         """
-        # Open dialog for forcing item variable value 
+        # Open dialog for forcing item variable value
         self.ForceValue(self.ContextualButtonsItem)
         # Close contextual menu
         self.DismissContextualButtons()
-        
+
     def OnReleaseItemButton(self):
         """
         Function called when contextual menu Release button is pressed
         """
-        # Release item variable value 
+        # Release item variable value
         self.ReleaseValue(self.ContextualButtonsItem)
         # Close contextual menu
         self.DismissContextualButtons()
-    
+
     def OnExportItemGraphButton(self):
         """
         Function called when contextual menu Export button is pressed
@@ -552,17 +552,17 @@
         self.ExportGraph(self.ContextualButtonsItem)
         # Close contextual menu
         self.DismissContextualButtons()
-        
-    def OnRemoveItemButton(self):            
+
+    def OnRemoveItemButton(self):
         """
         Function called when contextual menu Remove button is pressed
         """
         # Remove item from Viewer
-        wx.CallAfter(self.ParentWindow.DeleteValue, self, 
+        wx.CallAfter(self.ParentWindow.DeleteValue, self,
                      self.ContextualButtonsItem)
         # Close contextual menu
         self.DismissContextualButtons()
-    
+
     def HandleCursorMove(self, event):
         """
         Update Cursor position according to mouse position and graph type
@@ -571,7 +571,7 @@
         start_tick, end_tick = self.ParentWindow.GetRange()
         cursor_tick = None
         items = self.ItemsDict.values()
-        
+
         # Graph is orthogonal
         if self.GraphType == GRAPH_ORTHOGONAL:
             # Extract items data displayed in canvas figure
@@ -579,31 +579,31 @@
             end_tick = max(end_tick, start_tick)
             x_data = items[0].GetData(start_tick, end_tick)
             y_data = items[1].GetData(start_tick, end_tick)
-            
+
             # Search for the nearest point from mouse position
             if len(x_data) > 0 and len(y_data) > 0:
-                length = min(len(x_data), len(y_data)) 
+                length = min(len(x_data), len(y_data))
                 d = numpy.sqrt((x_data[:length,1]-event.xdata) ** 2 + \
                                (y_data[:length,1]-event.ydata) ** 2)
-                
+
                 # Set cursor tick to the tick of this point
                 cursor_tick = x_data[numpy.argmin(d), 0]
-        
+
         # Graph is parallel
         else:
             # Extract items tick
             data = items[0].GetData(start_tick, end_tick)
-            
+
             # Search for point that tick is the nearest from mouse X position
             # and set cursor tick to the tick of this point
             if len(data) > 0:
                 cursor_tick = data[numpy.argmin(
                         numpy.abs(data[:,0] - event.xdata)), 0]
-        
+
         # Update cursor tick
         if cursor_tick is not None:
             self.ParentWindow.SetCursorTick(cursor_tick)
-    
+
     def OnCanvasButtonPressed(self, event):
         """
         Function called when a button of mouse is pressed
@@ -613,18 +613,18 @@
         # comparing to wx
         width, height = self.GetSize()
         x, y = event.x, height - event.y
-        
+
         # Return immediately if mouse is over a button
         if self.IsOverButton(x, y):
-            return 
-        
+            return
+
         # Mouse was clicked inside graph figure
         if event.inaxes == self.Axes:
-            
+
             # Find if it was on an item label
             item_idx = None
             # Check every label paired with corresponding item
-            for i, t in ([pair for pair in enumerate(self.AxesLabels)] + 
+            for i, t in ([pair for pair in enumerate(self.AxesLabels)] +
                          [pair for pair in enumerate(self.Labels)]):
                 # Get label bounding box
                 (x0, y0), (x1, y1) = t.get_window_extent().get_points()
@@ -633,46 +633,46 @@
                 if rect.InsideXY(x, y):
                     item_idx = i
                     break
-            
+
             # If an item label have been clicked
             if item_idx is not None:
                 # Hide buttons and contextual buttons
                 self.ShowButtons(False)
                 self.DismissContextualButtons()
-                
+
                 # Start a drag'n drop from mouse position in wx coordinate of
                 # parent
                 xw, yw = self.GetPosition()
-                self.ParentWindow.StartDragNDrop(self, 
-                    self.ItemsDict.values()[item_idx], 
+                self.ParentWindow.StartDragNDrop(self,
+                    self.ItemsDict.values()[item_idx],
                     x + xw, y + yw, # Current mouse position
                     x + xw, y + yw) # Mouse position when button was clicked
-            
+
             # Don't handle mouse button if canvas is 3D and let matplotlib do
             # the default behavior (rotate 3D axes)
             elif not self.Is3DCanvas():
                 # Save mouse position when clicked
                 self.MouseStartPos = wx.Point(x, y)
-                
+
                 # Mouse button was left button, start moving cursor
                 if event.button == 1:
                     # Save current tick in case a drag'n drop is initiate to
                     # restore it
                     self.StartCursorTick = self.CursorTick
-                    
+
                     self.HandleCursorMove(event)
-                    
+
                 # Mouse button is middle button and graph is parallel, start
                 # moving graph along X coordinate (tick)
                 elif event.button == 2 and self.GraphType == GRAPH_PARALLEL:
                     self.StartCursorTick = self.ParentWindow.GetRange()[0]
-        
+
         # Mouse was clicked outside graph figure and over resize highlight with
         # left button, start resizing Viewer
         elif event.button == 1 and event.y <= 5:
             self.MouseStartPos = wx.Point(x, y)
             self.CanvasStartSize = height
-    
+
     def OnCanvasButtonReleased(self, event):
         """
         Function called when a button of mouse is released
@@ -686,37 +686,37 @@
             # Give mouse position in wx coordinate of parent
             self.ParentWindow.StopDragNDrop(item.GetVariable(),
                 xw + event.x, yw + height - event.y)
-        
+
         else:
             # Reset any move in progress
             self.MouseStartPos = None
             self.CanvasStartSize = None
-            
+
             # Handle button under mouse if it exist
             width, height = self.GetSize()
             self.HandleButton(event.x, height - event.y)
-    
+
     def OnCanvasMotion(self, event):
         """
         Function called when a button of mouse is moved over Viewer
         @param event: Mouse event
         """
         width, height = self.GetSize()
-        
+
         # If a drag'n drop is in progress, move canvas dragged
         if self.ParentWindow.IsDragging():
             xw, yw = self.GetPosition()
             # Give mouse position in wx coordinate of parent
             self.ParentWindow.MoveDragNDrop(
-                xw + event.x, 
+                xw + event.x,
                 yw + height - event.y)
-        
-        # If a Viewer resize is in progress, change Viewer size 
+
+        # If a Viewer resize is in progress, change Viewer size
         elif event.button == 1 and self.CanvasStartSize is not None:
             width, height = self.GetSize()
             self.SetCanvasHeight(
                 self.CanvasStartSize + height - event.y - self.MouseStartPos.y)
-        
+
         # If no button is pressed, show or hide contextual buttons or resize
         # highlight
         elif event.button is None:
@@ -729,13 +729,13 @@
                              wx.LEFT, wx.BOTTOM] # Directions for Labels
             else: # Graph is orthogonal in 3D
                 directions = [wx.LEFT] * len(self.Labels)
-            
+
             # Find if mouse is over an item label
             item_idx = None
             menu_direction = None
             for (i, t), dir in zip(
-                    [pair for pair in enumerate(self.AxesLabels)] + 
-                    [pair for pair in enumerate(self.Labels)], 
+                    [pair for pair in enumerate(self.AxesLabels)] +
+                    [pair for pair in enumerate(self.Labels)],
                     directions):
                 # Check every label paired with corresponding item
                 (x0, y0), (x1, y1) = t.get_window_extent().get_points()
@@ -745,19 +745,19 @@
                     item_idx = i
                     menu_direction = dir
                     break
-            
-            # If mouse is over an item label, 
+
+            # If mouse is over an item label,
             if item_idx is not None:
                 self.PopupContextualButtons(
-                    self.ItemsDict.values()[item_idx], 
+                    self.ItemsDict.values()[item_idx],
                     rect, menu_direction)
                 return
-            
+
             # If mouse isn't over a contextual menu, hide the current shown one
-            # if it exists 
+            # if it exists
             if self.IsOverContextualButton(event.x, height - event.y) is None:
                 self.DismissContextualButtons()
-            
+
             # Update resize highlight
             if event.y <= 5:
                 if self.SetHighlight(HIGHLIGHT_RESIZE):
@@ -767,46 +767,46 @@
                 if self.SetHighlight(HIGHLIGHT_NONE):
                     self.SetCursor(wx.NullCursor)
                     self.ParentWindow.ForceRefresh()
-        
-        # Handle buttons if canvas is not 3D 
+
+        # Handle buttons if canvas is not 3D
         elif not self.Is3DCanvas():
-            
+
             # If left button is pressed
             if event.button == 1:
-                
+
                 # Mouse is inside graph figure
                 if event.inaxes == self.Axes:
-                    
+
                     # If a cursor move is in progress, update cursor position
                     if self.MouseStartPos is not None:
                         self.HandleCursorMove(event)
-                
+
                 # Mouse is outside graph figure, cursor move is in progress and
                 # there is only one item in Viewer, start a drag'n drop
                 elif self.MouseStartPos is not None and len(self.Items) == 1:
                     xw, yw = self.GetPosition()
                     self.ParentWindow.SetCursorTick(self.StartCursorTick)
-                    self.ParentWindow.StartDragNDrop(self, 
+                    self.ParentWindow.StartDragNDrop(self,
                         self.ItemsDict.values()[0],
                         # Current mouse position
                         event.x + xw, height - event.y + yw,
                         # Mouse position when button was clicked
                         self.MouseStartPos.x + xw,
                         self.MouseStartPos.y + yw)
-            
+
             # If middle button is pressed and moving graph along X coordinate
             # is in progress
             elif event.button == 2 and self.GraphType == GRAPH_PARALLEL and \
                  self.MouseStartPos is not None:
                 start_tick, end_tick = self.ParentWindow.GetRange()
                 rect = self.GetAxesBoundingBox()
-                
+
                 # Move graph along X coordinate
                 self.ParentWindow.SetCanvasPosition(
-                    self.StartCursorTick + 
+                    self.StartCursorTick +
                     (self.MouseStartPos.x - event.x) *
                     (end_tick - start_tick) / rect.width)
-    
+
     def OnCanvasScroll(self, event):
         """
         Function called when a wheel mouse is use in Viewer
@@ -815,7 +815,7 @@
         # Change X range of graphs if mouse is in canvas figure and ctrl is
         # pressed
         if event.inaxes is not None and event.guiEvent.ControlDown():
-            
+
             # Calculate position of fixed tick point according to graph type
             # and mouse position
             if self.GraphType == GRAPH_ORTHOGONAL:
@@ -824,10 +824,10 @@
             else:
                 tick = event.xdata
             self.ParentWindow.ChangeRange(int(-event.step) / 3, tick)
-            
+
             # Vetoing event to prevent parent panel to be scrolled
             self.ParentWindow.VetoScrollEvent = True
-    
+
     def OnLeftDClick(self, event):
         """
         Function called when a left mouse button is double clicked
@@ -841,17 +841,17 @@
             self.ParentWindow.SetCursorTick(self.StartCursorTick)
             # Toggle to text Viewer(s)
             self.ParentWindow.ToggleViewerType(self)
-        
+
         else:
             event.Skip()
-    
+
     # Cursor tick move for each arrow key
     KEY_CURSOR_INCREMENT = {
         wx.WXK_LEFT: -1,
         wx.WXK_RIGHT: 1,
         wx.WXK_UP: 10,
         wx.WXK_DOWN: -10}
-    
+
     def OnKeyDown(self, event):
         """
         Function called when key is pressed
@@ -863,7 +863,7 @@
             if move is not None:
                 self.ParentWindow.MoveCursorTick(move)
         event.Skip()
-    
+
     def OnLeave(self, event):
         """
         Function called when mouse leave Viewer
@@ -876,7 +876,7 @@
             DebugVariableViewer.OnLeave(self, event)
         else:
             event.Skip()
-    
+
     def GetCanvasMinSize(self):
         """
         Return the minimum size of Viewer so that all items label can be
@@ -885,10 +885,10 @@
         """
         # The minimum height take in account the height of all items, padding
         # inside figure and border around figure
-        return wx.Size(200, 
-            CANVAS_BORDER[0] + CANVAS_BORDER[1] + 
+        return wx.Size(200,
+            CANVAS_BORDER[0] + CANVAS_BORDER[1] +
             2 * CANVAS_PADDING + VALUE_LABEL_HEIGHT * len(self.Items))
-    
+
     def SetCanvasHeight(self, height):
         """
         Set Viewer size checking that it respects Viewer minimum size
@@ -899,7 +899,7 @@
         self.SetMinSize(wx.Size(min_width, height))
         self.RefreshLabelsPosition(height)
         self.ParentWindow.RefreshGraphicsSizer()
-        
+
     def GetAxesBoundingBox(self, parent_coordinate=False):
         """
         Return figure bounding box in wx coordinate
@@ -911,15 +911,15 @@
         ax, ay, aw, ah = self.figure.gca().get_position().bounds
         bbox = wx.Rect(ax * width, height - (ay + ah) * height - 1,
                        aw * width + 2, ah * height + 1)
-        
+
         # If parent_coordinate, add Viewer position in parent
         if parent_coordinate:
             xw, yw = self.GetPosition()
             bbox.x += xw
             bbox.y += yw
-        
+
         return bbox
-    
+
     def RefreshHighlight(self, x, y):
         """
         Refresh Viewer highlight according to mouse position
@@ -927,7 +927,7 @@
         @param y: Y coordinate of mouse pointer
         """
         width, height = self.GetSize()
-        
+
         # Mouse is over Viewer figure and graph is not 3D
         bbox = self.GetAxesBoundingBox()
         if bbox.InsideXY(x, y) and not self.Is3DCanvas():
@@ -935,28 +935,28 @@
             # Mouse is over Viewer left part of figure
             if rect.InsideXY(x, y):
                 self.SetHighlight(HIGHLIGHT_LEFT)
-            
+
             # Mouse is over Viewer right part of figure
             else:
                 self.SetHighlight(HIGHLIGHT_RIGHT)
-        
+
         # Mouse is over upper part of Viewer
         elif y < height / 2:
             # Viewer is upper one in Debug Variable Panel, show highlight
             if self.ParentWindow.IsViewerFirst(self):
                 self.SetHighlight(HIGHLIGHT_BEFORE)
-            
+
             # Viewer is not the upper one, show highlight in previous one
             # It prevents highlight to move when mouse leave one Viewer to
             # another
             else:
                 self.SetHighlight(HIGHLIGHT_NONE)
                 self.ParentWindow.HighlightPreviousViewer(self)
-        
+
         # Mouse is over lower part of Viewer
         else:
             self.SetHighlight(HIGHLIGHT_AFTER)
-    
+
     def OnAxesMotion(self, event):
         """
         Function overriding default function called when mouse is dragged for
@@ -969,7 +969,7 @@
             if current_time - self.LastMotionTime > REFRESH_PERIOD:
                 self.LastMotionTime = current_time
                 Axes3D._on_move(self.Axes, event)
-    
+
     def GetAddTextFunction(self):
         """
         Return function for adding text in figure according to graph type
@@ -987,58 +987,58 @@
             self.Axes.set_prop_cycle(cycler('color',color))
         else:
             self.Axes.set_color_cycle(color)
-        
+
     def ResetGraphics(self):
         """
         Reset figure and graphical elements displayed in it
-        Called any time list of items or graph type change 
+        Called any time list of items or graph type change
         """
         # Clear figure from any axes defined
         self.Figure.clear()
-        
+
         # Add 3D projection if graph is in 3D
         if self.Is3DCanvas():
             self.Axes = self.Figure.gca(projection='3d')
             self.SetAxesColor(['b'])
-            
-            # Override function to prevent too much refresh when graph is 
+
+            # Override function to prevent too much refresh when graph is
             # rotated
             self.LastMotionTime = gettime()
             setattr(self.Axes, "_on_move", self.OnAxesMotion)
-            
+
             # Init graph mouse event so that graph can be rotated
             self.Axes.mouse_init()
-            
+
             # Set size of Z axis labels
             self.Axes.tick_params(axis='z', labelsize='small')
-        
+
         else:
             self.Axes = self.Figure.gca()
             self.SetAxesColor(COLOR_CYCLE)
-        
+
         # Set size of X and Y axis labels
         self.Axes.tick_params(axis='x', labelsize='small')
         self.Axes.tick_params(axis='y', labelsize='small')
-        
+
         # Init variables storing graphical elements added to figure
         self.Plots = []      # List of curves
         self.VLine = None    # Vertical line for cursor
         self.HLine = None    # Horizontal line for cursor (only orthogonal 2D)
         self.AxesLabels = [] # List of items variable path text label
         self.Labels = []     # List of items text label
-        
-        # Get function to add a text in figure according to graph type 
+
+        # Get function to add a text in figure according to graph type
         add_text_func = self.GetAddTextFunction()
-        
+
         # Graph type is parallel or orthogonal in 3D
         if self.GraphType == GRAPH_PARALLEL or self.Is3DCanvas():
             num_item = len(self.Items)
             for idx in xrange(num_item):
-                
+
                 # Get color from color cycle (black if only one item)
                 color = ('k' if num_item == 1
                              else COLOR_CYCLE[idx % len(COLOR_CYCLE)])
-                
+
                 # In 3D graph items variable label are not displayed as text
                 # in figure, but as axis title
                 if not self.Is3DCanvas():
@@ -1046,12 +1046,12 @@
                     self.AxesLabels.append(
                         add_text_func(size='small', color=color,
                                       verticalalignment='top'))
-                
+
                 # Items variable labels are in figure lower right corner
                 self.Labels.append(
-                    add_text_func(size='large', color=color, 
+                    add_text_func(size='large', color=color,
                                   horizontalalignment='right'))
-        
+
         # Graph type is orthogonal in 2D
         else:
             # X coordinate labels are in figure lower side
@@ -1059,7 +1059,7 @@
             self.Labels.append(
                 add_text_func(size='large',
                               horizontalalignment='right'))
-            
+
             # Y coordinate labels are vertical and in figure left side
             self.AxesLabels.append(
                 add_text_func(size='small', rotation='vertical',
@@ -1067,11 +1067,11 @@
             self.Labels.append(
                 add_text_func(size='large', rotation='vertical',
                               verticalalignment='top'))
-       
+
         # Refresh position of labels according to Viewer size
         width, height = self.GetSize()
         self.RefreshLabelsPosition(height)
-    
+
     def RefreshLabelsPosition(self, height):
         """
         Function called when mouse leave Viewer
@@ -1087,30 +1087,30 @@
         graph_ratio = 1. / (
             (1.0 - (CANVAS_BORDER[0] + CANVAS_BORDER[1]) * canvas_ratio)
              * height)             # Divide by figure height in pixel
-        
+
         # Update position of figure (keeping up and bottom border the same
         # size)
         self.Figure.subplotpars.update(
-            top= 1.0 - CANVAS_BORDER[1] * canvas_ratio, 
+            top= 1.0 - CANVAS_BORDER[1] * canvas_ratio,
             bottom= CANVAS_BORDER[0] * canvas_ratio)
-        
+
         # Update position of items labels
         if self.GraphType == GRAPH_PARALLEL or self.Is3DCanvas():
             num_item = len(self.Items)
             for idx in xrange(num_item):
-                
+
                 # In 3D graph items variable label are not displayed
                 if not self.Is3DCanvas():
                     # Items variable labels are in figure upper left corner
                     self.AxesLabels[idx].set_position(
-                        (0.05, 
-                         1.0 - (CANVAS_PADDING + 
+                        (0.05,
+                         1.0 - (CANVAS_PADDING +
                                 AXES_LABEL_HEIGHT * idx) * graph_ratio))
-                
+
                 # Items variable labels are in figure lower right corner
                 self.Labels[idx].set_position(
-                    (0.95, 
-                     CANVAS_PADDING * graph_ratio + 
+                    (0.95,
+                     CANVAS_PADDING * graph_ratio +
                      (num_item - idx - 1) * VALUE_LABEL_HEIGHT * graph_ratio))
         else:
             # X coordinate labels are in figure lower side
@@ -1118,16 +1118,16 @@
                     (0.1, CANVAS_PADDING * graph_ratio))
             self.Labels[0].set_position(
                     (0.95, CANVAS_PADDING * graph_ratio))
-            
+
             # Y coordinate labels are vertical and in figure left side
             self.AxesLabels[1].set_position(
                     (0.05, 2 * CANVAS_PADDING * graph_ratio))
             self.Labels[1].set_position(
                     (0.05, 1.0 - CANVAS_PADDING * graph_ratio))
-        
+
         # Update subplots
         self.Figure.subplots_adjust()
-    
+
     def RefreshViewer(self, refresh_graphics=True):
         """
         Function called to refresh displayed by matplotlib canvas
@@ -1138,55 +1138,55 @@
         if refresh_graphics:
             # Get tick range of values to display
             start_tick, end_tick = self.ParentWindow.GetRange()
-            
+
             # Graph is parallel
-            if self.GraphType == GRAPH_PARALLEL:    
+            if self.GraphType == GRAPH_PARALLEL:
                 # Init list of data range for each variable displayed
                 ranges = []
-                
+
                 # Get data and range for each variable displayed
                 for idx, item in enumerate(self.Items):
                     data, min_value, max_value = item.GetDataAndValueRange(
                                 start_tick, end_tick, not self.ZoomFit)
-                    
+
                     # Check that data is not empty
                     if data is not None:
                         # Add variable range to list of variable data range
                         ranges.append((min_value, max_value))
-                        
+
                         # Add plot to canvas if not yet created
                         if len(self.Plots) <= idx:
                             self.Plots.append(
                                 self.Axes.plot(data[:, 0], data[:, 1])[0])
-                        
+
                         # Set data to already created plot in canvas
                         else:
                             self.Plots[idx].set_data(data[:, 0], data[:, 1])
-                
+
                 # Get X and Y axis ranges
                 x_min, x_max = start_tick, end_tick
                 y_min, y_max = merge_ranges(ranges)
-                
+
                 # Display cursor in canvas if a cursor tick is defined and it is
                 # include in values tick range
-                if (self.CursorTick is not None and 
+                if (self.CursorTick is not None and
                     start_tick <= self.CursorTick <= end_tick):
-                    
+
                     # Define a vertical line to display cursor position if no
                     # line is already defined
                     if self.VLine is None:
-                        self.VLine = self.Axes.axvline(self.CursorTick, 
+                        self.VLine = self.Axes.axvline(self.CursorTick,
                                                        color=CURSOR_COLOR)
-                    
+
                     # Set value of vertical line if already defined
                     else:
                         self.VLine.set_xdata((self.CursorTick, self.CursorTick))
                     self.VLine.set_visible(True)
-                
+
                 # Hide vertical line if cursor tick is not defined or reset
                 elif self.VLine is not None:
                     self.VLine.set_visible(False)
-            
+
             # Graph is orthogonal
             else:
                 # Update tick range, removing ticks that don't have a value for
@@ -1194,76 +1194,76 @@
                 start_tick = max(start_tick, self.GetItemsMinCommonTick())
                 end_tick = max(end_tick, start_tick)
                 items = self.ItemsDict.values()
-                
+
                 # Get data and range for first variable (X coordinate)
                 x_data, x_min, x_max = items[0].GetDataAndValueRange(
                                         start_tick, end_tick, not self.ZoomFit)
                 # Get data and range for second variable (Y coordinate)
                 y_data, y_min, y_max = items[1].GetDataAndValueRange(
                                         start_tick, end_tick, not self.ZoomFit)
-                
+
                 # Normalize X and Y coordinates value range
                 x_min, x_max = merge_ranges([(x_min, x_max)])
                 y_min, y_max = merge_ranges([(y_min, y_max)])
-                
-                # Get X and Y coordinates for cursor if cursor tick is defined 
+
+                # Get X and Y coordinates for cursor if cursor tick is defined
                 if self.CursorTick is not None:
                     x_cursor, x_forced = items[0].GetValue(
                                             self.CursorTick, raw=True)
                     y_cursor, y_forced = items[1].GetValue(
                                             self.CursorTick, raw=True)
-                
+
                 # Get common data length so that each value has an x and y
                 # coordinate
                 length = (min(len(x_data), len(y_data))
                           if x_data is not None and y_data is not None
                           else 0)
-                
-                # Graph is orthogonal 2D 
+
+                # Graph is orthogonal 2D
                 if len(self.Items) < 3:
-                    
+
                     # Check that x and y data are not empty
                     if x_data is not None and y_data is not None:
-                        
+
                         # Add plot to canvas if not yet created
                         if len(self.Plots) == 0:
                             self.Plots.append(
-                                self.Axes.plot(x_data[:, 1][:length], 
+                                self.Axes.plot(x_data[:, 1][:length],
                                                y_data[:, 1][:length])[0])
-                        
+
                         # Set data to already created plot in canvas
                         else:
                             self.Plots[0].set_data(
-                                x_data[:, 1][:length], 
+                                x_data[:, 1][:length],
                                 y_data[:, 1][:length])
-                    
+
                     # Display cursor in canvas if a cursor tick is defined and it is
                     # include in values tick range
-                    if (self.CursorTick is not None and 
+                    if (self.CursorTick is not None and
                         start_tick <= self.CursorTick <= end_tick):
-                        
+
                         # Define a vertical line to display cursor x coordinate
                         # if no line is already defined
                         if self.VLine is None:
-                            self.VLine = self.Axes.axvline(x_cursor, 
+                            self.VLine = self.Axes.axvline(x_cursor,
                                                            color=CURSOR_COLOR)
                         # Set value of vertical line if already defined
                         else:
                             self.VLine.set_xdata((x_cursor, x_cursor))
-                        
-                        
+
+
                         # Define a horizontal line to display cursor y
                         # coordinate if no line is already defined
                         if self.HLine is None:
-                            self.HLine = self.Axes.axhline(y_cursor, 
+                            self.HLine = self.Axes.axhline(y_cursor,
                                                            color=CURSOR_COLOR)
                         # Set value of horizontal line if already defined
                         else:
                             self.HLine.set_ydata((y_cursor, y_cursor))
-                        
+
                         self.VLine.set_visible(True)
                         self.HLine.set_visible(True)
-                    
+
                     # Hide vertical and horizontal line if cursor tick is not
                     # defined or reset
                     else:
@@ -1271,42 +1271,42 @@
                             self.VLine.set_visible(False)
                         if self.HLine is not None:
                             self.HLine.set_visible(False)
-                
+
                 # Graph is orthogonal 3D
                 else:
                     # Remove all plots already defined in 3D canvas
                     while len(self.Axes.lines) > 0:
                         self.Axes.lines.pop()
-                    
+
                     # Get data and range for third variable (Z coordinate)
                     z_data, z_min, z_max = items[2].GetDataAndValueRange(
                                     start_tick, end_tick, not self.ZoomFit)
-                    
+
                     # Normalize Z coordinate value range
                     z_min, z_max = merge_ranges([(z_min, z_max)])
-                    
+
                     # Check that x, y and z data are not empty
-                    if (x_data is not None and y_data is not None and 
+                    if (x_data is not None and y_data is not None and
                         z_data is not None):
-                        
+
                         # Get common data length so that each value has an x, y
                         # and z coordinate
                         length = min(length, len(z_data))
-                        
+
                         # Add plot to canvas
                         self.Axes.plot(x_data[:, 1][:length],
                                        y_data[:, 1][:length],
                                        zs = z_data[:, 1][:length])
-                    
+
                     # Display cursor in canvas if a cursor tick is defined and
                     # it is include in values tick range
-                    if (self.CursorTick is not None and 
+                    if (self.CursorTick is not None and
                         start_tick <= self.CursorTick <= end_tick):
-                        
+
                         # Get Z coordinate for cursor
                         z_cursor, z_forced = items[2].GetValue(
                                                 self.CursorTick, raw=True)
-                        
+
                         # Add 3 lines parallel to x, y and z axis to display
                         # cursor position in 3D
                         for kwargs in [{"xs": numpy.array([x_min, x_max])},
@@ -1319,14 +1319,14 @@
                                 kwargs.setdefault(param, value)
                             kwargs["color"] = CURSOR_COLOR
                             self.Axes.plot(**kwargs)
-                    
+
                     # Set Z axis limits
                     self.Axes.set_zlim(z_min, z_max)
-            
+
             # Set X and Y axis limits
             self.Axes.set_xlim(x_min, x_max)
             self.Axes.set_ylim(y_min, y_max)
-        
+
         # Get value and forced flag for each variable displayed in graph
         # If cursor tick is not defined get value and flag of last received
         # or get value and flag of variable at cursor tick
@@ -1335,34 +1335,34 @@
                  if self.CursorTick is not None
                  else (item.GetValue(), item.IsForced()))
                 for item in self.Items])
-        
+
         # Get path of each variable displayed simplified using panel variable
         # name mask
-        labels = [item.GetVariable(self.ParentWindow.GetVariableNameMask()) 
+        labels = [item.GetVariable(self.ParentWindow.GetVariableNameMask())
                   for item in self.Items]
-        
-        # Get style for each variable according to 
+
+        # Get style for each variable according to
         styles = map(lambda x: {True: 'italic', False: 'normal'}[x], forced)
-        
+
         # Graph is orthogonal 3D, set variables path as 3D axis label
         if self.Is3DCanvas():
-            for idx, label_func in enumerate([self.Axes.set_xlabel, 
+            for idx, label_func in enumerate([self.Axes.set_xlabel,
                                               self.Axes.set_ylabel,
                                               self.Axes.set_zlabel]):
                 label_func(labels[idx], fontdict={'size': 'small',
                                                   'color': COLOR_CYCLE[idx]})
-        
+
         # Graph is not orthogonal 3D, set variables path in axes labels
         else:
             for label, text in zip(self.AxesLabels, labels):
                 label.set_text(text)
-        
+
         # Set value label text and style according to value and forced flag for
         # each variable displayed
         for label, value, style in zip(self.Labels, values, styles):
             label.set_text(value)
             label.set_style(style)
-        
+
         # Refresh figure
         self.draw()
 
@@ -1372,51 +1372,49 @@
         """
         # Render figure using agg
         FigureCanvasAgg.draw(self)
-        
+
         # Get bitmap of figure rendered
         self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
-        if wx.VERSION < (3, 0, 0):        
+        if wx.VERSION < (3, 0, 0):
             self.bitmap.UseAlpha()
-        
+
         # Create DC for rendering graphics in bitmap
         destDC = wx.MemoryDC()
         destDC.SelectObject(self.bitmap)
-        
+
         # Get Graphics Context for DC, for anti-aliased and transparent
         # rendering
         destGC = wx.GCDC(destDC)
-        
+
         destGC.BeginDrawing()
-        
+
         # Get canvas size and figure bounding box in canvas
         width, height = self.GetSize()
         bbox = self.GetAxesBoundingBox()
-        
+
         # If highlight to display is resize, draw thick grey line at bottom
-        # side of canvas 
+        # side of canvas
         if self.Highlight == HIGHLIGHT_RESIZE:
             destGC.SetPen(HIGHLIGHT_RESIZE_PEN)
             destGC.SetBrush(HIGHLIGHT_RESIZE_BRUSH)
             destGC.DrawRectangle(0, height - 5, width, 5)
-        
+
         # If highlight to display is merging graph, draw 50% transparent blue
         # rectangle on left or right part of figure depending on highlight type
         elif self.Highlight in [HIGHLIGHT_LEFT, HIGHLIGHT_RIGHT]:
             destGC.SetPen(HIGHLIGHT_DROP_PEN)
             destGC.SetBrush(HIGHLIGHT_DROP_BRUSH)
-            
-            x_offset = (bbox.width / 2 
+
+            x_offset = (bbox.width / 2
                         if self.Highlight == HIGHLIGHT_RIGHT
                         else 0)
-            destGC.DrawRectangle(bbox.x + x_offset, bbox.y, 
+            destGC.DrawRectangle(bbox.x + x_offset, bbox.y,
                                  bbox.width / 2, bbox.height)
-        
+
         # Draw other Viewer common elements
         self.DrawCommonElements(destGC, self.GetButtons())
-        
+
         destGC.EndDrawing()
-        
+
         self._isDrawn = True
         self.gui_repaint(drawDC=drawDC)
-    
-    
--- a/controls/DebugVariablePanel/DebugVariableItem.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/DebugVariableItem.py	Mon Aug 14 19:13:01 2017 +0300
@@ -44,7 +44,7 @@
 """
 
 class DebugVariableItem(DebugDataConsumer):
-    
+
     def __init__(self, parent, variable, store_data=False):
         """
         Constructor
@@ -52,24 +52,24 @@
         @param variable: Path of variable to debug
         """
         DebugDataConsumer.__init__(self)
-        
+
         self.Parent = parent
         self.Variable = variable
         self.StoreData = store_data
-        
+
         # Get Variable data type
         self.RefreshVariableType()
-        
+
     def __del__(self):
         """
         Destructor
         """
         # Reset reference to debug variable panel
         self.Parent = None
-    
+
     def SetVariable(self, variable):
         """
-        Set path of variable 
+        Set path of variable
         @param variable: Path of variable to debug
         """
         if self.Parent is not None and self.Variable != variable:
@@ -77,46 +77,46 @@
             self.Variable = variable
             # Get Variable data type
             self.RefreshVariableType()
-            
+
             # Refresh debug variable panel
             self.Parent.RefreshView()
-    
+
     def GetVariable(self, mask=None):
         """
-        Return path of variable 
+        Return path of variable
         @param mask: Mask to apply to variable path [var_name, '*',...]
         @return: String containing masked variable path
         """
         # Apply mask to variable name
         if mask is not None:
             # '#' correspond to parts that are different between all items
-            
+
             # Extract variable path parts
             parts = self.Variable.split('.')
             # Adjust mask size to size of variable path
             mask = mask + ['*'] * max(0, len(parts) - len(mask))
-            
+
             # Store previous mask
             last = None
             # Init masked variable path
             variable = ""
-            
+
             for m, p in zip(mask, parts):
                 # Part is not masked, add part prefixed with '.' is previous
                 # wasn't masked
                 if m == '*':
                     variable += ('.' if last == '*' else '') + p
-                
+
                 # Part is mask, add '..' if first or previous wasn't masked
                 elif last is None or last == '*':
                     variable += '..'
-                
+
                 last = m
-            
+
             return variable
-        
+
         return self.Variable
-    
+
     def RefreshVariableType(self):
         """
         Get and store variable data type
@@ -124,14 +124,14 @@
         self.VariableType = self.Parent.GetDataType(self.Variable)
         # Reset data stored
         self.ResetData()
-    
+
     def GetVariableType(self):
         """
         Return variable data type
         @return: Variable data type
         """
         return self.VariableType
-    
+
     def GetData(self, start_tick=None, end_tick=None):
         """
         Return data stored contained in given range
@@ -142,7 +142,7 @@
         # Return immediately if data empty or none
         if self.Data is None or len(self.Data) == 0:
             return self.Data
-        
+
         # Find nearest data outside given range indexes
         start_idx = (self.GetNearestData(start_tick, -1)
                      if start_tick is not None
@@ -150,10 +150,10 @@
         end_idx = (self.GetNearestData(end_tick, 1)
                    if end_tick is not None
                    else len(self.Data))
-        
+
         # Return data between indexes
         return self.Data[start_idx:end_idx]
-    
+
     def GetRawValue(self, index):
         """
         Return raw value at given index for string variables
@@ -164,14 +164,14 @@
             index < len(self.RawData)):
             return self.RawData[index][0]
         return ""
-    
+
     def GetValueRange(self):
         """
         Return variable value range
         @return: (minimum_value, maximum_value)
         """
         return self.MinValue, self.MaxValue
-    
+
     def GetDataAndValueRange(self, start_tick, end_tick, full_range=True):
         """
         Return variable data and value range for a given tick range
@@ -179,16 +179,16 @@
         @param end_tick: end tick of given range (default None, last data)
         @param full_range: Value range is calculated on whole data (False: only
         calculated on data in given range)
-        @return: (numpy.array([(tick, value, forced),...]), 
+        @return: (numpy.array([(tick, value, forced),...]),
                   min_value, max_value)
         """
         # Get data in given tick range
         data = self.GetData(start_tick, end_tick)
-        
+
         # Value range is calculated on whole data
         if full_range:
             return data, self.MinValue, self.MaxValue
-        
+
         # Check that data in given range is not empty
         values = data[:, 1]
         if len(values) > 0:
@@ -196,10 +196,10 @@
             return (data,
                     data[numpy.argmin(values), 1],
                     data[numpy.argmax(values), 1])
-        
+
         # Return default values
         return data, None, None
-    
+
     def ResetData(self):
         """
         Reset data stored when store data option enabled
@@ -207,31 +207,31 @@
         if self.StoreData and self.IsNumVariable():
             # Init table storing data
             self.Data = numpy.array([]).reshape(0, 3)
-            
+
             # Init table storing raw data if variable is strin
             self.RawData = ([]
                             if self.VariableType in ["STRING", "WSTRING"]
                             else None)
-                
+
             # Init Value range variables
             self.MinValue = None
             self.MaxValue = None
-        
+
         else:
             self.Data = None
-        
+
         # Init variable value
         self.Value = ""
-    
+
     def IsNumVariable(self):
         """
         Return if variable data type is numeric. String variables are
         considered as numeric (string CRC)
         @return: True if data type is numeric
         """
-        return (self.Parent.IsNumType(self.VariableType) or 
+        return (self.Parent.IsNumType(self.VariableType) or
                 self.VariableType in ["STRING", "WSTRING"])
-    
+
     def NewValues(self, ticks, values):
         """
         Function called by debug thread when a new debug value is available
@@ -240,24 +240,24 @@
         @param forced: Forced flag, True if value is forced (default: False)
         """
         DebugDataConsumer.NewValues(self, ticks[-1], values[-1], raw=None)
-        
+
         if self.Data is not None:
-            
+
             if self.VariableType in ["STRING", "WSTRING"]:
                 last_raw_data = (self.RawData[-1]
                                  if len(self.RawData) > 0 else None)
                 last_raw_data_idx = len(self.RawData) - 1
-            
+
             data_values = []
             for tick, (value, forced) in zip(ticks, values):
                 # Translate forced flag to float for storing in Data table
                 forced_value = float(forced)
-                
+
                 # String data value is CRC
                 num_value = (binascii.crc32(value) & STRING_CRC_MASK
                              if self.VariableType in ["STRING", "WSTRING"]
                              else float(value))
-            
+
                 # Update variable range values
                 self.MinValue = (min(self.MinValue, num_value)
                                  if self.MinValue is not None
@@ -265,10 +265,10 @@
                 self.MaxValue = (max(self.MaxValue, num_value)
                                  if self.MaxValue is not None
                                  else num_value)
-            
+
                 # In the case of string variables, we store raw string value and
                 # forced flag in raw data table. Only changes in this two values
-                # are stored. Index to the corresponding raw value is stored in 
+                # are stored. Index to the corresponding raw value is stored in
                 # data third column
                 if self.VariableType in ["STRING", "WSTRING"]:
                     raw_data = (value, forced_value)
@@ -277,20 +277,20 @@
                         last_raw_data = raw_data
                         self.RawData.append(raw_data)
                     extra_value = last_raw_data_idx
-                
+
                 # In other case, data third column is forced flag
                 else:
                     extra_value = forced_value
-            
+
                 data_values.append(
                     [float(tick), num_value, extra_value])
-            
+
             # Add New data to stored data table
             self.Data = numpy.append(self.Data, data_values, axis=0)
-            
+
             # Signal to debug variable panel to refresh
             self.Parent.HasNewData = True
-        
+
     def SetForced(self, forced):
         """
         Update Forced flag
@@ -299,10 +299,10 @@
         # Store forced flag
         if self.Forced != forced:
             self.Forced = forced
-            
+
             # Signal to debug variable panel to refresh
             self.Parent.HasNewData = True
-    
+
     def SetValue(self, value):
         """
         Update value.
@@ -314,14 +314,14 @@
             self.VariableType == "WSTRING" and
             value.startswith('"') and value.endswith('"')):
             value = value[1:-1]
-        
+
         # Store variable value
         if self.Value != value:
             self.Value = value
-            
+
             # Signal to debug variable panel to refresh
             self.Parent.HasNewData = True
-    
+
     def GetValue(self, tick=None, raw=False):
         """
         Return current value or value and forced flag for tick given
@@ -329,26 +329,26 @@
         """
         # If tick given and stored data option enabled
         if tick is not None and self.Data is not None:
-            
+
             # Return current value and forced flag if data empty
             if len(self.Data) == 0:
                 return self.Value, self.IsForced()
-            
+
             # Get index of nearest data from tick given
             idx = self.GetNearestData(tick, 0)
-            
+
             # Get value and forced flag at given index
             value, forced = self.RawData[int(self.Data[idx, 2])] \
                             if self.VariableType in ["STRING", "WSTRING"] \
                             else self.Data[idx, 1:3]
-            
+
             # Get raw value if asked
             if not raw:
                 value = TYPE_TRANSLATOR.get(
                         self.VariableType, str)(value)
-            
+
             return value, forced
-            
+
         # Return raw value if asked
         if not raw and self.VariableType in ["STRING", "WSTRING"]:
             return TYPE_TRANSLATOR.get(
@@ -368,16 +368,16 @@
         # Return immediately if data is empty
         if self.Data is None:
             return None
-        
+
         # Extract data ticks
         ticks = self.Data[:, 0]
-        
+
         # Get nearest data from tick
         idx = numpy.argmin(abs(ticks - tick))
-        
+
         # Adjust data index according to constraint
         if (adjust < 0 and ticks[idx] > tick and idx > 0 or
             adjust > 0 and ticks[idx] < tick and idx < len(ticks)):
             idx += adjust
-        
+
         return idx
--- a/controls/DebugVariablePanel/DebugVariablePanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/DebugVariablePanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -67,11 +67,11 @@
     for item, data in variables:
         if len(data) == 0:
             continue
-        
+
         next_tick = (data[0][0]
                      if next_tick is None
                      else min(next_tick, data[0][0]))
-    
+
     return next_tick
 
 #-------------------------------------------------------------------------------
@@ -84,7 +84,7 @@
 """
 
 class DebugVariableDropTarget(wx.TextDropTarget):
-    
+
     def __init__(self, window):
         """
         Constructor
@@ -92,14 +92,14 @@
         """
         wx.TextDropTarget.__init__(self)
         self.ParentWindow = window
-    
+
     def __del__(self):
         """
         Destructor
         """
         # Remove reference to Debug Variable Panel
         self.ParentWindow = None
-    
+
     def OnDragOver(self, x, y, d):
         """
         Function called when mouse is dragged over Drop Target
@@ -110,7 +110,7 @@
        # Signal Debug Variable Panel to refresh highlight giving mouse position
         self.ParentWindow.RefreshHighlight(x, y)
         return wx.TextDropTarget.OnDragOver(self, x, y, d)
-        
+
     def OnDropText(self, x, y, data):
         """
         Function called when mouse is released in Drop Target
@@ -120,9 +120,9 @@
         """
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
-        
+
         message = None
-        
+
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
@@ -131,23 +131,23 @@
         except:
             message = _("Invalid value \"%s\" for debug variable")%data
             values = None
-            
+
         # Display message if data is invalid
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
-        
+
         # Data contain a reference to a variable to debug
         elif values[1] == "debug":
-            
+
             # Drag'n Drop is an internal is an internal move inside Debug
-            # Variable Panel 
+            # Variable Panel
             if len(values) > 2 and values[2] == "move":
                 self.ParentWindow.MoveValue(values[0])
-            
+
             # Drag'n Drop was initiated by another control of Beremiz
             else:
                 self.ParentWindow.InsertValue(values[0], force=True)
-    
+
     def OnLeave(self):
         """
         Function called when mouse is leave Drop Target
@@ -155,15 +155,15 @@
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
         return wx.TextDropTarget.OnLeave(self)
-    
+
     def ShowMessage(self, message):
         """
         Show error message in Error Dialog
         @param message: Error message to display
         """
-        dialog = wx.MessageDialog(self.ParentWindow, 
-                                  message, 
-                                  _("Error"), 
+        dialog = wx.MessageDialog(self.ParentWindow,
+                                  message,
+                                  _("Error"),
                                   wx.OK|wx.ICON_ERROR)
         dialog.ShowModal()
         dialog.Destroy()
@@ -178,7 +178,7 @@
 """
 
 class DebugVariablePanel(wx.Panel, DebugViewer):
-    
+
     def __init__(self, parent, producer, window):
         """
         Constructor
@@ -188,48 +188,48 @@
         @param window: Reference to Beremiz frame
         """
         wx.Panel.__init__(self, parent, style=wx.SP_3D|wx.TAB_TRAVERSAL)
-        
+
         # Save Reference to Beremiz frame
         self.ParentWindow = window
-        
+
         # Variable storing flag indicating that variable displayed in table
         # received new value and then table need to be refreshed
         self.HasNewData = False
-        
+
         # Variable storing flag indicating that refresh has been forced, and
         # that next time refresh is possible, it will be done even if no new
         # data is available
         self.Force = False
-        
+
         self.SetBackgroundColour(wx.WHITE)
-        
+
         main_sizer = wx.BoxSizer(wx.VERTICAL)
-        
+
         self.Ticks = numpy.array([]) # List of tick received
         self.StartTick = 0           # Tick starting range of data displayed
         self.Fixed = False           # Flag that range of data is fixed
         self.CursorTick = None       # Tick of cursor for displaying values
-        
+
         self.DraggingAxesPanel = None
         self.DraggingAxesBoundingBox = None
         self.DraggingAxesMousePos = None
         self.VetoScrollEvent = False
-        
+
         self.VariableNameMask = []
-        
+
         self.GraphicPanels = []
-        
+
         graphics_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
         main_sizer.AddSizer(graphics_button_sizer, border=5, flag=wx.GROW|wx.ALL)
-        
+
         range_label = wx.StaticText(self, label=_('Range:'))
         graphics_button_sizer.AddWindow(range_label, flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         self.CanvasRange = wx.ComboBox(self, style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnRangeChanged, self.CanvasRange)
-        graphics_button_sizer.AddWindow(self.CanvasRange, 1, 
+        graphics_button_sizer.AddWindow(self.CanvasRange, 1,
               border=5, flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
-        
+
         self.CanvasRange.Clear()
         default_range_idx = 0
         for idx, (text, value) in enumerate(RANGE_VALUES):
@@ -237,44 +237,44 @@
             if text == "1s":
                 default_range_idx = idx
         self.CanvasRange.SetSelection(default_range_idx)
-        
+
         for name, bitmap, help in [
             ("CurrentButton", "current", _("Go to current value")),
             ("ExportGraphButton", "export_graph", _("Export graph values to clipboard"))]:
-            button = wx.lib.buttons.GenBitmapButton(self, 
-                  bitmap=GetBitmap(bitmap), 
+            button = wx.lib.buttons.GenBitmapButton(self,
+                  bitmap=GetBitmap(bitmap),
                   size=wx.Size(28, 28), style=wx.NO_BORDER)
             button.SetToolTipString(help)
             setattr(self, name, button)
             self.Bind(wx.EVT_BUTTON, getattr(self, "On" + name), button)
             graphics_button_sizer.AddWindow(button, border=5, flag=wx.LEFT)
-        
-        self.CanvasPosition = wx.ScrollBar(self, 
+
+        self.CanvasPosition = wx.ScrollBar(self,
               size=wx.Size(0, 16), style=wx.SB_HORIZONTAL)
-        self.CanvasPosition.Bind(wx.EVT_SCROLL_THUMBTRACK, 
+        self.CanvasPosition.Bind(wx.EVT_SCROLL_THUMBTRACK,
               self.OnPositionChanging, self.CanvasPosition)
-        self.CanvasPosition.Bind(wx.EVT_SCROLL_LINEUP, 
+        self.CanvasPosition.Bind(wx.EVT_SCROLL_LINEUP,
               self.OnPositionChanging, self.CanvasPosition)
-        self.CanvasPosition.Bind(wx.EVT_SCROLL_LINEDOWN, 
+        self.CanvasPosition.Bind(wx.EVT_SCROLL_LINEDOWN,
               self.OnPositionChanging, self.CanvasPosition)
-        self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEUP, 
+        self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEUP,
               self.OnPositionChanging, self.CanvasPosition)
-        self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEDOWN, 
+        self.CanvasPosition.Bind(wx.EVT_SCROLL_PAGEDOWN,
               self.OnPositionChanging, self.CanvasPosition)
         main_sizer.AddWindow(self.CanvasPosition, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
-        
+
         self.TickSizer = wx.BoxSizer(wx.HORIZONTAL)
         main_sizer.AddSizer(self.TickSizer, border=5, flag=wx.ALL|wx.GROW)
-        
+
         self.TickLabel = wx.StaticText(self)
         self.TickSizer.AddWindow(self.TickLabel, border=5, flag=wx.RIGHT)
-        
+
         self.MaskLabel = wx.TextCtrl(self, style=wx.TE_READONLY|wx.TE_CENTER|wx.NO_BORDER)
         self.TickSizer.AddWindow(self.MaskLabel, 1, border=5, flag=wx.RIGHT|wx.GROW)
-        
+
         self.TickTimeLabel = wx.StaticText(self)
         self.TickSizer.AddWindow(self.TickTimeLabel)
-        
+
         self.GraphicsWindow = wx.ScrolledWindow(self, style=wx.HSCROLL|wx.VSCROLL)
         self.GraphicsWindow.SetBackgroundColour(wx.WHITE)
         self.GraphicsWindow.SetDropTarget(DebugVariableDropTarget(self))
@@ -282,17 +282,17 @@
         self.GraphicsWindow.Bind(wx.EVT_PAINT, self.OnGraphicsWindowPaint)
         self.GraphicsWindow.Bind(wx.EVT_SIZE, self.OnGraphicsWindowResize)
         self.GraphicsWindow.Bind(wx.EVT_MOUSEWHEEL, self.OnGraphicsWindowMouseWheel)
-        
+
         main_sizer.AddWindow(self.GraphicsWindow, 1, flag=wx.GROW)
-        
+
         self.GraphicsSizer = wx.BoxSizer(wx.VERTICAL)
         self.GraphicsWindow.SetSizer(self.GraphicsSizer)
-    
+
         DebugViewer.__init__(self, producer, True)
-        
+
         self.SetSizer(main_sizer)
         self.SetTickTime()
-    
+
     def SetTickTime(self, ticktime=0):
         """
         Set Ticktime for calculate data range according to time range selected
@@ -300,26 +300,26 @@
         """
         # Save ticktime
         self.Ticktime = ticktime
-        
+
         # Set ticktime to millisecond if undefined
         if self.Ticktime == 0:
             self.Ticktime = MILLISECOND
-        
+
         # Calculate range to apply to data
         self.CurrentRange = RANGE_VALUES[
             self.CanvasRange.GetSelection()][1] / self.Ticktime
-    
+
     def SetDataProducer(self, producer):
         """
         Set Data Producer
         @param producer: Data Producer
         """
         DebugViewer.SetDataProducer(self, producer)
-        
+
         # Set ticktime if data producer is available
         if self.DataProducer is not None:
             self.SetTickTime(self.DataProducer.GetTicktime())
-    
+
     def RefreshNewData(self):
         """
         Called to refresh Panel according to values received by variables
@@ -329,50 +329,50 @@
         if self.HasNewData or self.Force:
             self.HasNewData = False
             self.RefreshView()
-        
+
         DebugViewer.RefreshNewData(self)
-    
+
     def NewDataAvailable(self, ticks):
         """
         Called by DataProducer for each tick captured or by panel to refresh
         graphs
         @param tick: PLC tick captured
-        All other parameters are passed to refresh function 
+        All other parameters are passed to refresh function
         """
         # If tick given
         if ticks is not None:
             tick = ticks[-1]
-            
+
             # Save tick as start tick for range if data is still empty
             if len(self.Ticks) == 0:
                 self.StartTick = ticks[0]
-            
+
             # Add tick to list of ticks received
             self.Ticks = numpy.append(self.Ticks, ticks)
-            
+
             # Update start tick for range if range follow ticks received
             if not self.Fixed or tick < self.StartTick + self.CurrentRange:
                 self.StartTick = max(self.StartTick, tick - self.CurrentRange)
-            
+
             # Force refresh if graph is fixed because range of data received
             # is too small to fill data range selected
             if self.Fixed and \
                self.Ticks[-1] - self.Ticks[0] < self.CurrentRange:
                 self.Force = True
-            
+
             self.HasNewData = False
             self.RefreshView()
-            
+
         else:
             DebugViewer.NewDataAvailable(self, ticks)
-    
+
     def ForceRefresh(self):
         """
         Called to force refresh of graphs
         """
         self.Force = True
         wx.CallAfter(self.NewDataAvailable, None)
-    
+
     def SetCursorTick(self, cursor_tick):
         """
         Set Cursor for displaying values of items at a tick given
@@ -381,37 +381,37 @@
         # Save cursor tick
         self.CursorTick = cursor_tick
         self.Fixed = cursor_tick is not None
-        self.UpdateCursorTick() 
-    
+        self.UpdateCursorTick()
+
     def MoveCursorTick(self, move):
         if self.CursorTick is not None:
-            cursor_tick = max(self.Ticks[0], 
-                          min(self.CursorTick + move, 
+            cursor_tick = max(self.Ticks[0],
+                          min(self.CursorTick + move,
                               self.Ticks[-1]))
             cursor_tick_idx = numpy.argmin(numpy.abs(self.Ticks - cursor_tick))
             if self.Ticks[cursor_tick_idx] == self.CursorTick:
-                cursor_tick_idx = max(0, 
-                                  min(cursor_tick_idx + abs(move) / move, 
+                cursor_tick_idx = max(0,
+                                  min(cursor_tick_idx + abs(move) / move,
                                       len(self.Ticks) - 1))
             self.CursorTick = self.Ticks[cursor_tick_idx]
             self.StartTick = max(self.Ticks[
-                                numpy.argmin(numpy.abs(self.Ticks - 
+                                numpy.argmin(numpy.abs(self.Ticks -
                                         self.CursorTick + self.CurrentRange))],
                              min(self.StartTick, self.CursorTick))
             self.RefreshCanvasPosition()
-            self.UpdateCursorTick() 
-            
+            self.UpdateCursorTick()
+
     def ResetCursorTick(self):
         self.CursorTick = None
         self.Fixed = False
         self.UpdateCursorTick()
-    
+
     def UpdateCursorTick(self):
         for panel in self.GraphicPanels:
             if isinstance(panel, DebugVariableGraphicViewer):
                 panel.SetCursorTick(self.CursorTick)
         self.ForceRefresh()
-    
+
     def StartDragNDrop(self, panel, item, x_mouse, y_mouse, x_mouse_start, y_mouse_start):
         if len(panel.GetItems()) > 1:
             self.DraggingAxesPanel = DebugVariableGraphicViewer(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
@@ -424,21 +424,21 @@
             self.DraggingAxesPanel = panel
         self.DraggingAxesBoundingBox = panel.GetAxesBoundingBox(parent_coordinate=True)
         self.DraggingAxesMousePos = wx.Point(
-            x_mouse_start - self.DraggingAxesBoundingBox.x, 
+            x_mouse_start - self.DraggingAxesBoundingBox.x,
             y_mouse_start - self.DraggingAxesBoundingBox.y)
         self.MoveDragNDrop(x_mouse, y_mouse)
-        
+
     def MoveDragNDrop(self, x_mouse, y_mouse):
         self.DraggingAxesBoundingBox.x = x_mouse - self.DraggingAxesMousePos.x
         self.DraggingAxesBoundingBox.y = y_mouse - self.DraggingAxesMousePos.y
         self.RefreshHighlight(x_mouse, y_mouse)
-    
+
     def RefreshHighlight(self, x_mouse, y_mouse):
         for idx, panel in enumerate(self.GraphicPanels):
             x, y = panel.GetPosition()
             width, height = panel.GetSize()
             rect = wx.Rect(x, y, width, height)
-            if (rect.InsideXY(x_mouse, y_mouse) or 
+            if (rect.InsideXY(x_mouse, y_mouse) or
                 idx == 0 and y_mouse < 0 or
                 idx == len(self.GraphicPanels) - 1 and y_mouse > panel.GetPosition()[1]):
                 panel.RefreshHighlight(x_mouse - x, y_mouse - y)
@@ -448,7 +448,7 @@
             self.RefreshView()
         else:
             self.ForceRefresh()
-    
+
     def ResetHighlight(self):
         for panel in self.GraphicPanels:
             panel.SetHighlight(HIGHLIGHT_NONE)
@@ -456,10 +456,10 @@
             self.RefreshView()
         else:
             self.ForceRefresh()
-    
+
     def IsDragging(self):
         return self.DraggingAxesPanel is not None
-    
+
     def GetDraggingAxesClippingRegion(self, panel):
         x, y = panel.GetPosition()
         width, height = panel.GetSize()
@@ -468,12 +468,12 @@
         bbox.x -= x
         bbox.y -= y
         return bbox
-    
+
     def GetDraggingAxesPosition(self, panel):
         x, y = panel.GetPosition()
         return wx.Point(self.DraggingAxesBoundingBox.x - x,
                         self.DraggingAxesBoundingBox.y - y)
-    
+
     def StopDragNDrop(self, variable, x_mouse, y_mouse):
         if self.DraggingAxesPanel not in self.GraphicPanels:
             self.DraggingAxesPanel.Destroy()
@@ -504,25 +504,25 @@
                             idx += 1
                         wx.CallAfter(self.MoveValue, variable, idx, True)
                 self.ForceRefresh()
-                return 
+                return
         width, height = self.GraphicsWindow.GetVirtualSize()
         rect = wx.Rect(0, 0, width, height)
         if rect.InsideXY(x_mouse, y_mouse):
             wx.CallAfter(self.MoveValue, variable, len(self.GraphicPanels), True)
         self.ForceRefresh()
-    
+
     def RefreshGraphicsSizer(self):
         self.GraphicsSizer.Clear()
-        
+
         for panel in self.GraphicPanels:
             self.GraphicsSizer.AddWindow(panel, flag=wx.GROW)
-            
+
         self.GraphicsSizer.Layout()
         self.RefreshGraphicsWindowScrollbars()
-    
+
     def RefreshView(self):
         self.RefreshCanvasPosition()
-        
+
         width, height = self.GraphicsWindow.GetVirtualSize()
         bitmap = wx.EmptyBitmap(width, height)
         dc = wx.BufferedDC(wx.ClientDC(self.GraphicsWindow), bitmap)
@@ -531,22 +531,22 @@
         if self.DraggingAxesPanel is not None:
             destBBox = self.DraggingAxesBoundingBox
             srcBBox = self.DraggingAxesPanel.GetAxesBoundingBox()
-            
+
             srcBmp = _convert_agg_to_wx_bitmap(self.DraggingAxesPanel.get_renderer(), None)
             srcDC = wx.MemoryDC()
             srcDC.SelectObject(srcBmp)
-                
-            dc.Blit(destBBox.x, destBBox.y, 
-                    int(destBBox.width), int(destBBox.height), 
+
+            dc.Blit(destBBox.x, destBBox.y,
+                    int(destBBox.width), int(destBBox.height),
                     srcDC, srcBBox.x, srcBBox.y)
         dc.EndDrawing()
-        
+
         if not self.Fixed or self.Force:
             self.Force = False
             refresh_graphics = True
         else:
             refresh_graphics = False
-        
+
         if self.DraggingAxesPanel is not None and self.DraggingAxesPanel not in self.GraphicPanels:
             self.DraggingAxesPanel.RefreshViewer(refresh_graphics)
         for panel in self.GraphicPanels:
@@ -554,7 +554,7 @@
                 panel.RefreshViewer(refresh_graphics)
             else:
                 panel.RefreshViewer()
-        
+
         if self.CursorTick is not None:
             tick = self.CursorTick
         elif len(self.Ticks) > 0:
@@ -570,27 +570,27 @@
                                   ((tick_duration % DAY) / HOUR, _("%dh")),
                                   ((tick_duration % HOUR) / MINUTE, _("%dm")),
                                   ((tick_duration % MINUTE) / SECOND, _("%ds"))]:
-                
+
                 if value > 0 or not_null:
                     duration += format % value
                     not_null = True
-            
-            duration += _("%03gms") % (float(tick_duration % SECOND) / MILLISECOND) 
+
+            duration += _("%03gms") % (float(tick_duration % SECOND) / MILLISECOND)
             self.TickTimeLabel.SetLabel("t: %s" % duration)
         else:
             self.TickLabel.SetLabel("")
             self.TickTimeLabel.SetLabel("")
         self.TickSizer.Layout()
-    
+
     def SubscribeAllDataConsumers(self):
         DebugViewer.SubscribeAllDataConsumers(self)
-        
+
         if self.DataProducer is not None:
             if self.DataProducer is not None:
                 self.SetTickTime(self.DataProducer.GetTicktime())
-        
+
         self.ResetCursorTick()
-        
+
         for panel in self.GraphicPanels[:]:
             panel.SubscribeAllDataConsumers()
             if panel.ItemsIsEmpty():
@@ -598,28 +598,28 @@
                     panel.ReleaseMouse()
                 self.GraphicPanels.remove(panel)
                 panel.Destroy()
-        
+
         self.ResetVariableNameMask()
         self.RefreshGraphicsSizer()
         self.ForceRefresh()
-    
+
     def ResetView(self):
         self.UnsubscribeAllDataConsumers()
-        
+
         self.Fixed = False
         for panel in self.GraphicPanels:
             panel.Destroy()
         self.GraphicPanels = []
         self.ResetVariableNameMask()
         self.RefreshGraphicsSizer()
-    
+
     def SetCanvasPosition(self, tick):
         tick = max(self.Ticks[0], min(tick, self.Ticks[-1] - self.CurrentRange))
         self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - tick))]
         self.Fixed = True
         self.RefreshCanvasPosition()
         self.ForceRefresh()
-    
+
     def RefreshCanvasPosition(self):
         if len(self.Ticks) > 0:
             pos = int(self.StartTick - self.Ticks[0])
@@ -628,7 +628,7 @@
             pos = 0
             range = 0
         self.CanvasPosition.SetScrollbar(pos, self.CurrentRange, range, self.CurrentRange)
-    
+
     def ChangeRange(self, dir, tick=None):
         current_range = self.CurrentRange
         current_range_idx = self.CanvasRange.GetSelection()
@@ -644,7 +644,7 @@
                 self.StartTick = self.Ticks[numpy.argmin(numpy.abs(self.Ticks - new_start_tick))]
                 self.Fixed = new_start_tick < self.Ticks[-1] - self.CurrentRange
             self.ForceRefresh()
-    
+
     def RefreshRange(self):
         if len(self.Ticks) > 0:
             if self.Fixed and self.Ticks[-1] - self.Ticks[0] < self.CurrentRange:
@@ -654,7 +654,7 @@
             else:
                 self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange)
         self.ForceRefresh()
-    
+
     def OnRangeChanged(self, event):
         try:
             self.CurrentRange = RANGE_VALUES[self.CanvasRange.GetSelection()][1] / self.Ticktime
@@ -662,13 +662,13 @@
             self.CanvasRange.SetValue(str(self.CurrentRange))
         wx.CallAfter(self.RefreshRange)
         event.Skip()
-    
+
     def OnCurrentButton(self, event):
         if len(self.Ticks) > 0:
             self.StartTick = max(self.Ticks[0], self.Ticks[-1] - self.CurrentRange)
             self.ResetCursorTick()
         event.Skip()
-    
+
     def CopyDataToClipboard(self, variables):
         text = "tick;%s;\n" % ";".join([item.GetVariable() for item, data in variables])
         next_tick = NextTick(variables)
@@ -693,7 +693,7 @@
             text += "%d;%s;\n" % (next_tick, ";".join(values))
             next_tick = NextTick(variables)
         self.ParentWindow.SetCopyBuffer(text)
-    
+
     def OnExportGraphButton(self, event):
         items = reduce(lambda x, y: x + y,
                        [panel.GetItems() for panel in self.GraphicPanels],
@@ -703,25 +703,25 @@
                      if item.IsNumVariable()]
         wx.CallAfter(self.CopyDataToClipboard, variables)
         event.Skip()
-    
+
     def OnPositionChanging(self, event):
         if len(self.Ticks) > 0:
             self.StartTick = self.Ticks[0] + event.GetPosition()
             self.Fixed = True
             self.ForceRefresh()
         event.Skip()
-    
+
     def GetRange(self):
         return self.StartTick, self.StartTick + self.CurrentRange
-    
+
     def GetViewerIndex(self, viewer):
         if viewer in self.GraphicPanels:
             return self.GraphicPanels.index(viewer)
         return None
-    
+
     def IsViewerFirst(self, viewer):
         return viewer == self.GraphicPanels[0]
-    
+
     def HighlightPreviousViewer(self, viewer):
         if self.IsViewerFirst(viewer):
             return
@@ -729,7 +729,7 @@
         if idx is None:
             return
         self.GraphicPanels[idx-1].SetHighlight(HIGHLIGHT_AFTER)
-    
+
     def ResetVariableNameMask(self):
         items = []
         for panel in self.GraphicPanels:
@@ -743,10 +743,10 @@
             self.VariableNameMask = []
         self.MaskLabel.ChangeValue(".".join(self.VariableNameMask))
         self.MaskLabel.SetInsertionPoint(self.MaskLabel.GetLastPosition())
-            
+
     def GetVariableNameMask(self):
         return self.VariableNameMask
-    
+
     def InsertValue(self, iec_path, idx = None, force=False, graph=False):
         for panel in self.GraphicPanels:
             if panel.GetItem(iec_path) is not None:
@@ -758,7 +758,7 @@
         item = DebugVariableItem(self, iec_path, True)
         result = self.AddDataConsumer(iec_path.upper(), item, True)
         if result is not None or force:
-            
+
             self.Freeze()
             if item.IsNumVariable() and graph:
                 panel = DebugVariableGraphicViewer(self.GraphicsWindow, self, [item], GRAPH_PARALLEL)
@@ -774,7 +774,7 @@
             self.RefreshGraphicsSizer()
             self.Thaw()
             self.ForceRefresh()
-    
+
     def MoveValue(self, iec_path, idx = None, graph=False):
         if idx is None:
             idx = len(self.GraphicPanels)
@@ -787,9 +787,9 @@
                 break
         if source_panel is not None:
             source_panel_idx = self.GraphicPanels.index(source_panel)
-            
+
             if (len(source_panel.GetItems()) == 1):
-                
+
                 if source_panel_idx < idx:
                     self.GraphicPanels.insert(idx, source_panel)
                     self.GraphicPanels.pop(source_panel_idx)
@@ -798,7 +798,7 @@
                     self.GraphicPanels.insert(idx, source_panel)
                 else:
                     return
-                
+
             else:
                 source_panel.RemoveItem(item)
                 source_size = source_panel.GetSize()
@@ -807,22 +807,22 @@
                     panel.SetCanvasHeight(source_size.height)
                     if self.CursorTick is not None:
                         panel.SetCursorTick(self.CursorTick)
-                
+
                 else:
                     panel = DebugVariableTextViewer(self.GraphicsWindow, self, [item])
-                
+
                 self.GraphicPanels.insert(idx, panel)
-                
+
                 if source_panel.ItemsIsEmpty():
                     if source_panel.HasCapture():
                         source_panel.ReleaseMouse()
                     source_panel.Destroy()
                     self.GraphicPanels.remove(source_panel)
-                
+
             self.ResetVariableNameMask()
             self.RefreshGraphicsSizer()
             self.ForceRefresh()
-    
+
     def MergeGraphs(self, source, target_idx, merge_type, force=False):
         source_item = None
         source_panel = None
@@ -846,11 +846,11 @@
             graph_type = target_panel.GraphType
             if target_panel != source_panel:
                 if (merge_type == GRAPH_PARALLEL and graph_type != merge_type or
-                    merge_type == GRAPH_ORTHOGONAL and 
+                    merge_type == GRAPH_ORTHOGONAL and
                     (graph_type == GRAPH_PARALLEL and len(target_panel.Items) > 1 or
                      graph_type == GRAPH_ORTHOGONAL and len(target_panel.Items) >= 3)):
                     return
-                
+
                 if source_panel is not None:
                     source_panel.RemoveItem(source_item)
                     if source_panel.ItemsIsEmpty():
@@ -862,7 +862,7 @@
                 target_panel.RemoveItem(source_item)
             else:
                 target_panel = None
-                
+
             if target_panel is not None:
                 target_panel.AddItem(source_item)
                 target_panel.GraphType = merge_type
@@ -874,15 +874,15 @@
                 else:
                     target_panel.SetCanvasHeight(size.height)
                 target_panel.ResetGraphics()
-                
+
                 self.ResetVariableNameMask()
                 self.RefreshGraphicsSizer()
                 self.ForceRefresh()
-    
+
     def DeleteValue(self, source_panel, item=None):
         source_idx = self.GetViewerIndex(source_panel)
         if source_idx is not None:
-            
+
             if item is None:
                 source_panel.ClearItems()
                 source_panel.Destroy()
@@ -900,7 +900,7 @@
                 self.Fixed = False
                 self.ResetCursorTick()
             self.ForceRefresh()
-    
+
     def ToggleViewerType(self, panel):
         panel_idx = self.GetViewerIndex(panel)
         if panel_idx is not None:
@@ -916,7 +916,7 @@
             panel.Destroy()
         self.RefreshGraphicsSizer()
         self.ForceRefresh()
-    
+
     def ResetGraphicsValues(self):
         self.Ticks = numpy.array([])
         self.StartTick = 0
@@ -931,22 +931,22 @@
         posx = max(0, min(xstart, (vwidth - window_size[0]) / SCROLLBAR_UNIT))
         posy = max(0, min(ystart, (vheight - window_size[1]) / SCROLLBAR_UNIT))
         self.GraphicsWindow.Scroll(posx, posy)
-        self.GraphicsWindow.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.GraphicsWindow.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
                 vwidth / SCROLLBAR_UNIT, vheight / SCROLLBAR_UNIT, posx, posy)
-    
+
     def OnGraphicsWindowEraseBackground(self, event):
         pass
-    
+
     def OnGraphicsWindowPaint(self, event):
         self.RefreshView()
         event.Skip()
-    
+
     def OnGraphicsWindowResize(self, event):
         size = self.GetSize()
         for panel in self.GraphicPanels:
             panel_size = panel.GetSize()
-            if (isinstance(panel, DebugVariableGraphicViewer) and 
-                panel.GraphType == GRAPH_ORTHOGONAL and 
+            if (isinstance(panel, DebugVariableGraphicViewer) and
+                panel.GraphType == GRAPH_ORTHOGONAL and
                 panel_size.width == panel_size.height):
                 panel.SetCanvasHeight(size.width)
         self.RefreshGraphicsWindowScrollbars()
--- a/controls/DebugVariablePanel/DebugVariableTextViewer.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py	Mon Aug 14 19:13:01 2017 +0300
@@ -39,7 +39,7 @@
 """
 
 class DebugVariableTextDropTarget(wx.TextDropTarget):
-    
+
     def __init__(self, parent, window):
         """
         Constructor
@@ -49,7 +49,7 @@
         wx.TextDropTarget.__init__(self)
         self.ParentControl = parent
         self.ParentWindow = window
-    
+
     def __del__(self):
         """
         Destructor
@@ -58,7 +58,7 @@
         # Panel
         self.ParentControl = None
         self.ParentWindow = None
-        
+
     def OnDragOver(self, x, y, d):
         """
         Function called when mouse is dragged over Drop Target
@@ -68,9 +68,9 @@
         """
         # Signal parent that mouse is dragged over
         self.ParentControl.OnMouseDragging(x, y)
-        
+
         return wx.TextDropTarget.OnDragOver(self, x, y, d)
-        
+
     def OnDropText(self, x, y, data):
         """
         Function called when mouse is released in Drop Target
@@ -80,9 +80,9 @@
         """
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
-        
+
         message = None
-        
+
         # Check that data is valid regarding DebugVariablePanel
         try:
             values = eval(data)
@@ -91,50 +91,50 @@
         except:
             message = _("Invalid value \"%s\" for debug variable") % data
             values = None
-        
+
         # Display message if data is invalid
         if message is not None:
             wx.CallAfter(self.ShowMessage, message)
-        
+
         # Data contain a reference to a variable to debug
         elif values[1] == "debug":
-            
+
             # Get Before which Viewer the variable has to be moved or added
             # according to the position of mouse in Viewer.
             width, height = self.ParentControl.GetSize()
             target_idx = self.ParentControl.GetIndex()
             if y > height / 2:
                 target_idx += 1
-            
+
             # Drag'n Drop is an internal is an internal move inside Debug
-            # Variable Panel 
+            # Variable Panel
             if len(values) > 2 and values[2] == "move":
-                self.ParentWindow.MoveValue(values[0], 
+                self.ParentWindow.MoveValue(values[0],
                                             target_idx)
-            
+
             # Drag'n Drop was initiated by another control of Beremiz
             else:
-                self.ParentWindow.InsertValue(values[0], 
-                                              target_idx, 
+                self.ParentWindow.InsertValue(values[0],
+                                              target_idx,
                                               force=True)
-    
+
     def OnLeave(self):
         """
         Function called when mouse is leave Drop Target
         """
         # Signal Debug Variable Panel to reset highlight
         self.ParentWindow.ResetHighlight()
-        
+
         return wx.TextDropTarget.OnLeave(self)
-    
+
     def ShowMessage(self, message):
         """
         Show error message in Error Dialog
         @param message: Error message to display
         """
-        dialog = wx.MessageDialog(self.ParentWindow, 
-                                  message, 
-                                  _("Error"), 
+        dialog = wx.MessageDialog(self.ParentWindow,
+                                  message,
+                                  _("Error"),
                                   wx.OK|wx.ICON_ERROR)
         dialog.ShowModal()
         dialog.Destroy()
@@ -149,7 +149,7 @@
 """
 
 class DebugVariableTextViewer(DebugVariableViewer, wx.Panel):
-    
+
     def __init__(self, parent, window, items=[]):
         """
         Constructor
@@ -158,13 +158,13 @@
         @param items: List of DebugVariableItem displayed by Viewer
         """
         DebugVariableViewer.__init__(self, window, items)
-        
+
         wx.Panel.__init__(self, parent)
         # Set panel background colour
         self.SetBackgroundColour(wx.WHITE)
         # Define panel drop target
         self.SetDropTarget(DebugVariableTextDropTarget(self, window))
-        
+
         # Bind events
         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
@@ -174,16 +174,16 @@
         self.Bind(wx.EVT_SIZE, self.OnResize)
         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
         self.Bind(wx.EVT_PAINT, self.OnPaint)
-        
+
         # Define panel min size for parent sizer layout
         self.SetMinSize(wx.Size(0, 25))
-        
+
         # Add buttons to Viewer
         for bitmap, callback in [("force", self.OnForceButton),
                                  ("release", self.OnReleaseButton),
                                  ("delete_graph", self.OnCloseButton)]:
             self.Buttons.append(GraphButton(0, 0, bitmap, callback))
-    
+
     def RefreshViewer(self):
         """
         Method that refresh the content displayed by Viewer
@@ -193,24 +193,24 @@
         bitmap = wx.EmptyBitmap(width, height)
         dc = wx.BufferedDC(wx.ClientDC(self), bitmap)
         dc.Clear()
-        
+
         # Get Graphics Context for DC, for anti-aliased and transparent
         # rendering
         gc = wx.GCDC(dc)
-        
+
         gc.BeginDrawing()
-        
+
         # Get first item
         item = self.ItemsDict.values()[0]
-        
+
         # Get item variable path masked according Debug Variable Panel mask
         item_path = item.GetVariable(
                 self.ParentWindow.GetVariableNameMask())
-        
+
         # Draw item variable path at Viewer left side
         w, h = gc.GetTextExtent(item_path)
         gc.DrawText(item_path, 20, (height - h) / 2)
-        
+
         # Update 'Release' button state and text color according to item forced
         # flag value
         item_forced = item.IsForced()
@@ -218,17 +218,17 @@
         self.RefreshButtonsPosition()
         if item_forced:
             gc.SetTextForeground(wx.BLUE)
-        
+
         # Draw item current value at right side of Viewer
         item_value = item.GetValue()
         w, h = gc.GetTextExtent(item_value)
         gc.DrawText(item_value, width - 40 - w, (height - h) / 2)
-        
+
         # Draw other Viewer common elements
         self.DrawCommonElements(gc)
-        
+
         gc.EndDrawing()
-    
+
     def OnLeftDown(self, event):
         """
         Function called when mouse left button is pressed
@@ -236,15 +236,15 @@
         """
         # Get first item
         item = self.ItemsDict.values()[0]
-        
+
         # Calculate item path bounding box
         width, height = self.GetSize()
         item_path = item.GetVariable(
                 self.ParentWindow.GetVariableNameMask())
         w, h = self.GetTextExtent(item_path)
-        
+
         # Test if mouse has been pressed in this bounding box. In that case
-        # start a move drag'n drop of item variable 
+        # start a move drag'n drop of item variable
         x, y = event.GetPosition()
         item_path_bbox = wx.Rect(20, (height - h) / 2, w, h)
         if item_path_bbox.InsideXY(x, y):
@@ -253,11 +253,11 @@
             dragSource = wx.DropSource(self)
             dragSource.SetData(data)
             dragSource.DoDragDrop()
-        
+
         # In other case handle event normally
         else:
             event.Skip()
-    
+
     def OnLeftUp(self, event):
         """
         Function called when mouse left button is released
@@ -267,7 +267,7 @@
         x, y = event.GetPosition()
         wx.CallAfter(self.HandleButton, x, y)
         event.Skip()
-    
+
     def OnLeftDClick(self, event):
         """
         Function called when mouse left button is double clicked
@@ -276,7 +276,7 @@
         # Only numeric variables can be toggled to graph canvas
         if self.ItemsDict.values()[0].IsNumVariable():
             self.ParentWindow.ToggleViewerType(self)
-    
+
     def OnPaint(self, event):
         """
         Function called when redrawing Viewer content is needed
--- a/controls/DebugVariablePanel/DebugVariableViewer.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/DebugVariableViewer.py	Mon Aug 14 19:13:01 2017 +0300
@@ -56,7 +56,7 @@
 """
 
 class DebugVariableViewer:
-    
+
     def __init__(self, window, items=[]):
         """
         Constructor
@@ -67,26 +67,26 @@
         self.ItemsDict = OrderedDict([(item.GetVariable(), item)
                                       for item in items])
         self.Items = self.ItemsDict.viewvalues()
-        
+
         # Variable storing current highlight displayed in Viewer
         self.Highlight = HIGHLIGHT_NONE
         # List of buttons
         self.Buttons = []
-    
+
     def __del__(self):
         """
         Destructor
         """
         # Remove reference to Debug Variable Panel
         self.ParentWindow = None
-    
+
     def GetIndex(self):
         """
         Return position of Viewer in Debug Variable Panel
         @return: Position of Viewer
         """
         return self.ParentWindow.GetViewerIndex(self)
-    
+
     def GetItem(self, variable):
         """
         Return item storing values of a variable
@@ -94,28 +94,28 @@
         @return: Item storing values of this variable
         """
         return self.ItemsDict.get(variable, None)
-    
+
     def GetItems(self):
         """
         Return items displayed by Viewer
         @return: List of items displayed in Viewer
         """
         return self.ItemsDict.values()
-    
+
     def AddItem(self, item):
         """
         Add an item to the list of items displayed by Viewer
         @param item: Item to add to the list
         """
         self.ItemsDict[item.GetVariable()] = item
-        
+
     def RemoveItem(self, item):
         """
         Remove an item from the list of items displayed by Viewer
         @param item: Item to remove from the list
         """
         self.ItemsDict.pop(item.GetVariable(), None)
-    
+
     def ClearItems(self):
         """
         Clear list of items displayed by Viewer
@@ -123,17 +123,17 @@
         # Unsubscribe every items of the list
         for item in self.Items:
             self.ParentWindow.RemoveDataConsumer(item)
-        
+
         # Clear list
         self.ItemsDict.clear()
-        
+
     def ItemsIsEmpty(self):
         """
         Return if list of items displayed by Viewer is empty
         @return: True if list is empty
         """
         return len(self.Items) == 0
-    
+
     def SubscribeAllDataConsumers(self):
         """
         Function that unsubscribe and remove every item that store values of
@@ -141,7 +141,7 @@
         """
         for item in self.ItemsDict.values()[:]:
             iec_path = item.GetVariable()
-            
+
             # Check that variablepath exist in PLC
             if self.ParentWindow.GetDataType(iec_path) is None:
                 # If not, unsubscribe and remove it
@@ -151,30 +151,30 @@
                 # If it exist, resubscribe and refresh data type
                 self.ParentWindow.AddDataConsumer(iec_path.upper(), item, True)
                 item.RefreshVariableType()
-    
+
     def ResetItemsData(self):
         """
         Reset data stored in every items displayed in Viewer
         """
         for item in self.Items:
             item.ResetData()
-    
+
     def GetItemsMinCommonTick(self):
         """
         Return the minimum tick common to all iems displayed in Viewer
         @return: Minimum common tick between items
         """
-        return reduce(max, [item.GetData()[0, 0] 
+        return reduce(max, [item.GetData()[0, 0]
                             for item in self.Items
                             if len(item.GetData()) > 0], 0)
-    
+
     def RefreshViewer(self):
         """
         Method that refresh the content displayed by Viewer
         Need to be overridden by inherited classes
         """
         pass
-    
+
     def SetHighlight(self, highlight):
         """
         Set Highlight type displayed in Viewer
@@ -183,17 +183,17 @@
         # Return immediately if highlight don't change
         if self.Highlight == highlight:
             return False
-        
+
         self.Highlight = highlight
         return True
-    
+
     def GetButtons(self):
         """
         Return list of buttons defined in Viewer
         @return: List of buttons
         """
         return self.Buttons
-    
+
     def IsOverButton(self, x, y):
         """
         Return if point is over one button of Viewer
@@ -205,7 +205,7 @@
             if button.HitTest(x, y):
                 return button
         return None
-    
+
     def HandleButton(self, x, y):
         """
         Search for the button under point and if found execute associated
@@ -217,10 +217,10 @@
         button = self.IsOverButton(x, y)
         if button is None:
             return False
-        
+
         button.ProcessCallback()
         return True
-    
+
     def ShowButtons(self, show):
         """
         Set display state of buttons in Viewer
@@ -229,27 +229,27 @@
         # Change display of every buttons
         for button in self.Buttons:
             button.Show(show)
-        
+
         # Refresh button positions
         self.RefreshButtonsPosition()
         self.RefreshViewer()
-    
+
     def RefreshButtonsPosition(self):
         """
         Function that refresh buttons position in Viewer
         """
         # Get Viewer size
         width, height = self.GetSize()
-        
+
         # Buttons are align right so we calculate buttons positions in
         # reverse order
         buttons = self.Buttons[:]
         buttons.reverse()
-        
+
         # Position offset on x coordinate
         x_offset = 0
         for button in buttons:
-            # Buttons are stacked right, removing those that are not active 
+            # Buttons are stacked right, removing those that are not active
             if button.IsEnabled():
                 # Update button position according to button width and offset
                 # on x coordinate
@@ -257,7 +257,7 @@
                 button.SetPosition(width - 5 - w - x_offset, 5)
                 # Update offset on x coordinate
                 x_offset += w + 2
-    
+
     def DrawCommonElements(self, dc, buttons=None):
         """
         Function that draw common graphics for every Viewers
@@ -268,26 +268,26 @@
         """
         # Get Viewer size
         width, height = self.GetSize()
-        
+
         # Set dc styling for drop before or drop after highlight
         dc.SetPen(HIGHLIGHT_DROP_PEN)
         dc.SetBrush(HIGHLIGHT_DROP_BRUSH)
-        
+
         # Draw line at upper side of Viewer if highlight is drop before
         if self.Highlight == HIGHLIGHT_BEFORE:
             dc.DrawLine(0, 1, width - 1, 1)
-        
+
         # Draw line at lower side of Viewer if highlight is drop before
         elif self.Highlight == HIGHLIGHT_AFTER:
             dc.DrawLine(0, height - 1, width - 1, height - 1)
-        
+
         # If no specific buttons are defined, get default buttons
         if buttons is None:
             buttons = self.Buttons
         # Draw buttons
         for button in buttons:
             button.Draw(dc)
-        
+
         # If graph dragging is processing
         if self.ParentWindow.IsDragging():
             destBBox = self.ParentWindow.GetDraggingAxesClippingRegion(self)
@@ -295,55 +295,55 @@
             if destBBox.width > 0 and destBBox.height > 0:
                 srcPanel = self.ParentWindow.DraggingAxesPanel
                 srcBBox = srcPanel.GetAxesBoundingBox()
-                
+
                 srcX = srcBBox.x - (srcPos.x if destBBox.x == 0 else 0)
                 srcY = srcBBox.y - (srcPos.y if destBBox.y == 0 else 0)
-                
+
                 srcBmp = _convert_agg_to_wx_bitmap(
                             srcPanel.get_renderer(), None)
                 srcDC = wx.MemoryDC()
                 srcDC.SelectObject(srcBmp)
-                
-                dc.Blit(destBBox.x, destBBox.y, 
-                        int(destBBox.width), int(destBBox.height), 
+
+                dc.Blit(destBBox.x, destBBox.y,
+                        int(destBBox.width), int(destBBox.height),
                         srcDC, srcX, srcY)
-    
+
     def OnEnter(self, event):
         """
         Function called when entering Viewer
-        @param event: wx.MouseEvent 
+        @param event: wx.MouseEvent
         """
         # Display buttons
         self.ShowButtons(True)
         event.Skip()
-        
+
     def OnLeave(self, event):
         """
         Function called when leaving Viewer
-        @param event: wx.MouseEvent 
+        @param event: wx.MouseEvent
         """
         # Hide buttons
         self.ShowButtons(False)
         event.Skip()
-    
+
     def OnCloseButton(self):
         """
         Function called when Close button is pressed
         """
         wx.CallAfter(self.ParentWindow.DeleteValue, self)
-    
+
     def OnForceButton(self):
         """
         Function called when Force button is pressed
         """
         self.ForceValue(self.ItemsDict.values()[0])
-        
+
     def OnReleaseButton(self):
         """
         Function called when Release button is pressed
         """
         self.ReleaseValue(self.ItemsDict.values()[0])
-    
+
     def OnMouseDragging(self, x, y):
         """
         Function called when mouse is dragged over Viewer
@@ -354,7 +354,7 @@
         # Refresh highlight in Debug Variable Panel (highlight can be displayed
         # in another Viewer
         self.ParentWindow.RefreshHighlight(x + xw, y + yw)
-    
+
     def RefreshHighlight(self, x, y):
         """
         Function called by Debug Variable Panel asking Viewer to refresh
@@ -364,22 +364,22 @@
         """
         # Get Viewer size
         width, height = self.GetSize()
-        
+
         # Mouse is in the first half of Viewer
         if y < height / 2:
             # If Viewer is the upper one, draw drop before highlight
             if self.ParentWindow.IsViewerFirst(self):
                 self.SetHighlight(HIGHLIGHT_BEFORE)
-            
+
             # Else draw drop after highlight in previous Viewer
             else:
                 self.SetHighlight(HIGHLIGHT_NONE)
                 self.ParentWindow.HighlightPreviousViewer(self)
-        
-        # Mouse is in the second half of Viewer, draw drop after highlight 
+
+        # Mouse is in the second half of Viewer, draw drop after highlight
         else:
             self.SetHighlight(HIGHLIGHT_AFTER)
-    
+
     def OnEraseBackground(self, event):
         """
         Function called when Viewer background is going to be erase
@@ -387,7 +387,7 @@
         """
         # Prevent flicker on Windows
         pass
-    
+
     def OnResize(self, event):
         """
         Function called when Viewer size changed
@@ -397,7 +397,7 @@
         self.RefreshButtonsPosition()
         self.ParentWindow.ForceRefresh()
         event.Skip()
-    
+
     def ForceValue(self, item):
         """
         Force value of item given
@@ -409,13 +409,13 @@
         # Return immediately if not found
         if iec_type is None:
             return
-        
+
         # Open a dialog to enter varaible forced value
         dialog = ForceVariableDialog(self, iec_type, str(item.GetValue()))
         if dialog.ShowModal() == wx.ID_OK:
             self.ParentWindow.ForceDataValue(iec_path.upper(),
                                              dialog.GetValue())
-    
+
     def ReleaseValue(self, item):
         """
         Release value of item given
--- a/controls/DebugVariablePanel/GraphButton.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DebugVariablePanel/GraphButton.py	Mon Aug 14 19:13:01 2017 +0300
@@ -35,7 +35,7 @@
 """
 
 class GraphButton():
-    
+
     def __init__(self, x, y, bitmap, callback):
         """
         Constructor
@@ -48,21 +48,21 @@
         self.SetPosition(x, y)
         # Set button bitmap
         self.SetBitmap(bitmap)
-        
+
         # By default button is hide and enabled
         self.Shown = False
         self.Enabled = True
-        
+
         # Save reference to callback function
         self.Callback = callback
-    
+
     def __del__(self):
         """
         Destructor
         """
         # Remove reference to callback function
         self.callback = None
-    
+
     def SetBitmap(self, bitmap):
         """
         Set bitmap to use for button
@@ -70,7 +70,7 @@
         """
         # Get wx.Bitmap object corresponding to bitmap
         self.Bitmap = GetBitmap(bitmap)
-    
+
     def GetSize(self):
         """
         Return size of button
@@ -78,7 +78,7 @@
         """
         # Button size is size of bitmap
         return self.Bitmap.GetSize()
-    
+
     def SetPosition(self, x, y):
         """
         Set button position
@@ -86,7 +86,7 @@
         @param y: Y coordinate of Button in Graphic Viewer
         """
         self.Position = wx.Point(x, y)
-    
+
     def Show(self, show=True):
         """
         Mark if button to be displayed in Graphic Viewer
@@ -94,20 +94,20 @@
         (default True)
         """
         self.Shown = show
-        
+
     def Hide(self):
         """
         Hide button from Graphic Viewer
         """
         self.Show(False)
-    
+
     def IsShown(self):
         """
         Return if button is displayed in Graphic Viewer
         @return: True if button is displayed in Graphic Viewer
         """
         return self.Shown
-    
+
     def Enable(self, enable=True):
         """
         Mark if button is active in Graphic Viewer
@@ -115,44 +115,44 @@
         (default True)
         """
         self.Enabled = enable
-    
+
     def Disable(self):
         """
         Deactivate button in Graphic Viewer
         """
         self.Enabled = False
-    
+
     def IsEnabled(self):
         """
         Return if button is active in Graphic Viewer
         @return: True if button is active in Graphic Viewer
         """
         return self.Enabled
-    
+
     def HitTest(self, x, y):
         """
         Test if point is inside button
         @param x: X coordinate of point
         @param y: Y coordinate of point
         @return: True if button is active and displayed and point is inside
-        button 
+        button
         """
         # Return immediately if button is hidden or inactive
         if not (self.IsShown() and self.IsEnabled()):
             return False
-        
+
         # Test if point is inside button
         w, h = self.Bitmap.GetSize()
         rect = wx.Rect(self.Position.x, self.Position.y, w, h)
         return rect.InsideXY(x, y)
-    
+
     def ProcessCallback(self):
         """
         Call callback function if defined
         """
         if self.Callback is not None:
             self.Callback()
-    
+
     def Draw(self, dc):
         """
         Draw button in Graphic Viewer
--- a/controls/DurationCellEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/DurationCellEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -27,39 +27,39 @@
 from dialogs.DurationEditorDialog import DurationEditorDialog
 
 class DurationCellControl(wx.PyControl):
-    
+
     '''
     Custom cell editor control with a text box and a button that launches
     the DurationEditorDialog.
     '''
     def __init__(self, parent):
         wx.Control.__init__(self, parent)
-        
+
         main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         # create location text control
-        self.Duration = wx.TextCtrl(self, size=wx.Size(0, -1), 
+        self.Duration = wx.TextCtrl(self, size=wx.Size(0, -1),
               style=wx.TE_PROCESS_ENTER)
         self.Duration.Bind(wx.EVT_KEY_DOWN, self.OnDurationChar)
         main_sizer.AddWindow(self.Duration, flag=wx.GROW)
-        
+
         # create browse button
         self.EditButton = wx.Button(self, label='...', size=wx.Size(30, -1))
         self.Bind(wx.EVT_BUTTON, self.OnEditButtonClick, self.EditButton)
         main_sizer.AddWindow(self.EditButton, flag=wx.GROW)
-        
+
         self.Bind(wx.EVT_SIZE, self.OnSize)
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.Default = None
-        
+
     def SetValue(self, value):
         self.Default = value
         self.Duration.SetValue(value)
-    
+
     def GetValue(self):
         return self.Duration.GetValue()
 
@@ -90,7 +90,7 @@
 
     def SetInsertionPoint(self, i):
         self.Duration.SetInsertionPoint(i)
-    
+
     def SetFocus(self):
         self.Duration.SetFocus()
 
@@ -100,13 +100,13 @@
     '''
     def __init__(self, table, colname):
         wx.grid.PyGridCellEditor.__init__(self)
-        
+
         self.Table = table
         self.Colname = colname
-    
+
     def __del__(self):
         self.CellControl = None
-    
+
     def Create(self, parent, id, evt_handler):
         self.CellControl = DurationCellControl(parent)
         self.SetControl(self.CellControl)
@@ -131,8 +131,8 @@
             return self.EndEditInternal(row, col, grid, oldval)
     else:
         def EndEdit(self, row, col, grid):
-            oldval = self.Table.GetValueByName(row, self.Colname)            
-            return self.EndEditInternal(row, col, grid, oldval)    
+            oldval = self.Table.GetValueByName(row, self.Colname)
+            return self.EndEditInternal(row, col, grid, oldval)
 
     def SetSize(self, rect):
         self.CellControl.SetDimensions(rect.x + 1, rect.y,
--- a/controls/EnhancedStatusBar.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/EnhancedStatusBar.py	Mon Aug 14 19:13:01 2017 +0300
@@ -16,7 +16,7 @@
 #
 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
 # Write To Me At:
-# 
+#
 #
 # andrea.gavana@agip.it
 # andrea_gavan@tin.it
@@ -47,7 +47,7 @@
      And Can Be ESB_EXACT_FIT, ESB_ALIGN_CENTER_VERTICAL, ESB_ALIGN_BOTTOM And
      ESB_ALIGN_LEFT;
 
-EnhancedStatusBar Is Freeware And Distributed Under The wxPython License. 
+EnhancedStatusBar Is Freeware And Distributed Under The wxPython License.
 
 Latest Revision: 21 September 2005, 19.57.20 GMT+2
 Latest Revision before Latest Revision: 21 September 2005, 18.29.35 GMT+2
@@ -90,17 +90,17 @@
                                    style=wx.ST_SIZEGRIP,
                                    name="EnhancedStatusBar")
         """
-        
+
         wx.StatusBar.__init__(self, parent, id, style, name)
-        
+
         self._items = {}
         self._curPos = 0
         self._parent = parent
-        
-        wx.EVT_SIZE(self, self.OnSize) 
+
+        wx.EVT_SIZE(self, self.OnSize)
         wx.CallAfter(self.OnSize, None)
 
-            
+
     def OnSize(self, event):
         """Handles The wx.EVT_SIZE Events For The StatusBar.
 
@@ -109,15 +109,15 @@
 
         for pos, item in self._items.items():
             widget, horizontalalignment, verticalalignment = item.widget, item.horizontalalignment, item.verticalalignment
-           
+
             rect = self.GetFieldRect(pos)
             widgetpos = widget.GetPosition()
             widgetsize = widget.GetSize()
 
             rect = self.GetFieldRect(pos)
-            
+
             if horizontalalignment == ESB_EXACT_FIT:
-                
+
                 if verticalalignment == ESB_EXACT_FIT:
                     """ 1 September 2015 Fix fit align """
                     widget.SetSize((rect.width-4, rect.height-4))
@@ -138,7 +138,7 @@
                     widget.SetPosition((rect.x-1, rect.height-widgetsize[1]))
 
             elif horizontalalignment == ESB_ALIGN_LEFT:
-                
+
                 xpos = rect.x - 1
                 if verticalalignment == ESB_EXACT_FIT:
                     widget.SetSize((widgetsize[0], rect.height-2))
@@ -154,9 +154,9 @@
                     widget.SetPosition((xpos, rect.y))
                 elif verticalalignment == ESB_ALIGN_BOTTOM:
                     widget.SetPosition((xpos, rect.height-widgetsize[1]))
-                
+
             elif horizontalalignment == ESB_ALIGN_RIGHT:
-                
+
                 xpos = rect.x + rect.width - widgetsize[0] - 1
                 if verticalalignment == ESB_EXACT_FIT:
                     widget.SetSize((widgetsize[0], rect.height-2))
@@ -174,7 +174,7 @@
                     widget.SetPosition((xpos, rect.height-widgetsize[1]))
 
             elif horizontalalignment == ESB_ALIGN_CENTER_HORIZONTAL:
-                
+
                 xpos = rect.x + (rect.width - widgetsize[0])/2 - 1
                 if verticalalignment == ESB_EXACT_FIT:
                     widget.SetSize((widgetsize[0], rect.height))
@@ -191,11 +191,11 @@
                 elif verticalalignment == ESB_ALIGN_BOTTOM:
                     widget.SetPosition((xpos, rect.height-widgetsize[1]))
 
-                
+
         if event is not None:
             event.Skip()
-        
-        
+
+
     def AddWidget(self, widget, horizontalalignment=ESB_ALIGN_CENTER_HORIZONTAL,
                   verticalalignment=ESB_ALIGN_CENTER_VERTICAL, pos = -1):
         """Add A Widget To The EnhancedStatusBar.
@@ -221,7 +221,7 @@
         if pos == -1:
             pos = self._curPos
             self._curPos += 1
-        
+
         if self.GetFieldsCount() <= pos:
             raise "\nERROR: EnhancedStatusBar has a max of %d items, you tried to set item #%d" % (self.GetFieldsCount(), pos)
 
@@ -236,13 +236,13 @@
             raise '\nERROR: Parameter "verticalalignment" Should Be One Of '\
                   '"ESB_ALIGN_CENTER_VERTICAL", "ESB_ALIGN_TOP", "ESB_ALIGN_BOTTOM"' \
                   '"ESB_EXACT_FIT"'
-        
+
 
         try:
             self.RemoveChild(self._items[pos].widget)
             self._items[pos].widget.Destroy()
         except KeyError: pass
-        
+
         self._items[pos] = EnhancedStatusBarItem(widget, pos, horizontalalignment, verticalalignment)
-        
+
         wx.CallAfter(self.OnSize, None)
--- a/controls/FolderTree.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/FolderTree.py	Mon Aug 14 19:13:01 2017 +0300
@@ -47,13 +47,13 @@
     return splitpath(head) + [tail]
 
 class FolderTree(wx.Panel):
-    
+
     def __init__(self, parent, folder, filter=None, editable=True):
         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
-        
+
         main_sizer = wx.BoxSizer(wx.VERTICAL)
-        
-        self.Tree = wx.TreeCtrl(self, 
+
+        self.Tree = wx.TreeCtrl(self,
               style=wx.TR_HAS_BUTTONS|
                     wx.TR_SINGLE|
                     wx.SUNKEN_BORDER|
@@ -69,19 +69,19 @@
         self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTreeBeginLabelEdit, self.Tree)
         self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTreeEndLabelEdit, self.Tree)
         main_sizer.AddWindow(self.Tree, 1, flag=wx.GROW)
-        
+
         if filter is not None:
             self.Filter = wx.ComboBox(self, style=wx.CB_READONLY)
             self.Bind(wx.EVT_COMBOBOX, self.OnFilterChanged, self.Filter)
             main_sizer.AddWindow(self.Filter, flag=wx.GROW)
         else:
             self.Filter = None
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.Folder = folder
         self.Editable = editable
-        
+
         self.TreeImageList = wx.ImageList(16, 16)
         self.TreeImageDict = {}
         for item_type, bitmap in [(DRIVE, "tree_drive"),
@@ -89,7 +89,7 @@
                                   (FILE, "tree_file")]:
             self.TreeImageDict[item_type] = self.TreeImageList.Add(GetBitmap(bitmap))
         self.Tree.SetImageList(self.TreeImageList)
-        
+
         self.Filters = {}
         if self.Filter is not None:
             filter_parts = filter.split("|")
@@ -101,11 +101,11 @@
                 self.Filter.Append(filter_parts[idx])
                 if idx == 0:
                     self.Filter.SetStringSelection(filter_parts[idx])
-                
+
             self.CurrentFilter = self.Filters[self.Filter.GetStringSelection()]
         else:
             self.CurrentFilter = ""
-    
+
     def _GetFolderChildren(self, folderpath, recursive=True):
         items = []
         if wx.Platform == '__WXMSW__' and folderpath == "/":
@@ -127,25 +127,25 @@
                         else:
                             children = 0
                         items.append((filename, FOLDER, children))
-                    elif (self.CurrentFilter == "" or 
+                    elif (self.CurrentFilter == "" or
                           os.path.splitext(filename)[1] == self.CurrentFilter):
                         items.append((filename, FILE, None))
         if recursive:
             items.sort(sort_folder)
         return items
-    
+
     def SetFilter(self, filter):
         self.CurrentFilter = filter
-    
+
     def GetTreeCtrl(self):
         return self.Tree
-    
+
     def RefreshTree(self):
         root = self.Tree.GetRootItem()
         if not root.IsOk():
             root = self.Tree.AddRoot("")
         self.GenerateTreeBranch(root, self.Folder)
-        
+
     def GenerateTreeBranch(self, root, folderpath):
         item, item_cookie = self.Tree.GetFirstChild(root)
         for idx, (filename, item_type, children) in enumerate(self._GetFolderChildren(folderpath)):
@@ -172,18 +172,18 @@
     def ExpandItem(self, item):
         self.GenerateTreeBranch(item, self.GetPath(item))
         self.Tree.Expand(item)
-    
+
     def OnTreeItemActivated(self, event):
         self.ExpandItem(event.GetItem())
         event.Skip()
-    
+
     def OnTreeLeftDown(self, event):
         item, flags = self.Tree.HitTest(event.GetPosition())
         if flags & wx.TREE_HITTEST_ONITEMBUTTON and not self.Tree.IsExpanded(item):
             self.ExpandItem(item)
         else:
             event.Skip()
-    
+
     def OnTreeItemExpanded(self, event):
         item = event.GetItem()
         self.GenerateTreeBranch(item, self.GetPath(item))
@@ -201,7 +201,7 @@
             event.Skip()
         else:
             event.Veto()
-    
+
     def OnTreeEndLabelEdit(self, event):
         new_name = event.GetLabel()
         if new_name != "":
@@ -212,20 +212,20 @@
                     os.rename(old_filepath, new_filepath)
                     event.Skip()
                 else:
-                    message =  wx.MessageDialog(self, 
-                        _("File '%s' already exists!") % new_name, 
+                    message =  wx.MessageDialog(self,
+                        _("File '%s' already exists!") % new_name,
                         _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
                     event.Veto()
         else:
             event.Skip()
-    
+
     def OnFilterChanged(self, event):
         self.CurrentFilter = self.Filters[self.Filter.GetStringSelection()]
         self.RefreshTree()
         event.Skip()
-    
+
     def _SelectItem(self, root, parts):
         if len(parts) == 0:
             self.Tree.SelectItem(root)
@@ -233,7 +233,7 @@
             item, item_cookie = self.Tree.GetFirstChild(root)
             while item.IsOk():
                 if self.Tree.GetItemText(item) == parts[0]:
-                    if (self.Tree.ItemHasChildren(item) and 
+                    if (self.Tree.ItemHasChildren(item) and
                         not self.Tree.IsExpanded(item)):
                         self.Tree.Expand(item)
                         wx.CallAfter(self._SelectItem, item, parts[1:])
@@ -241,14 +241,14 @@
                         self._SelectItem(item, parts[1:])
                     return
                 item, item_cookie = self.Tree.GetNextChild(root, item_cookie)
-    
+
     def SetPath(self, path):
         if path.startswith(self.Folder):
             root = self.Tree.GetRootItem()
             if root.IsOk():
                 relative_path = path.replace(os.path.join(self.Folder, ""), "")
                 self._SelectItem(root, splitpath(relative_path))
-    
+
     def GetPath(self, item=None):
         if item is None:
             item = self.Tree.GetSelection()
--- a/controls/LibraryPanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/LibraryPanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -42,7 +42,7 @@
 """
 
 class LibraryPanel(wx.Panel):
-    
+
     def __init__(self, parent, enable_drag=False):
         """
         Constructor
@@ -51,19 +51,19 @@
         be drag'n drop from LibraryPanel (default: False)
         """
         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
-        
+
         # Define LibraryPanel main sizer
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         # Add SearchCtrl to main sizer
         self.SearchCtrl = wx.SearchCtrl(self)
         # Add a button with a magnifying glass, essentially to show that this
         # control is for searching in tree
         self.SearchCtrl.ShowSearchButton(True)
         self.Bind(wx.EVT_TEXT, self.OnSearchCtrlChanged, self.SearchCtrl)
-        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, 
+        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN,
                   self.OnSearchButtonClick, self.SearchCtrl)
         # Bind keyboard event on SearchCtrl text control to catch UP and DOWN
         # for search previous and next occurrence
@@ -74,16 +74,16 @@
             search_textctrl.Bind(wx.EVT_CHAR, self.OnKeyDown)
 
         main_sizer.AddWindow(self.SearchCtrl, flag=wx.GROW)
-        
+
         # Add Splitter window for tree and block comment to main sizer
         splitter_window = wx.SplitterWindow(self)
         splitter_window.SetSashGravity(1.0)
         main_sizer.AddWindow(splitter_window, flag=wx.GROW)
-        
+
         # Add TreeCtrl for functions and function blocks library in splitter
         # window
         self.Tree = wx.TreeCtrl(splitter_window,
-              size=wx.Size(0, 0),  
+              size=wx.Size(0, 0),
               style=wx.TR_HAS_BUTTONS|
                     wx.TR_SINGLE|
                     wx.SUNKEN_BORDER|
@@ -95,35 +95,35 @@
         # tree to start a drag'n drop
         if enable_drag:
             self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnTreeBeginDrag, self.Tree)
-        
+
         # Add TextCtrl for function and function block informations
-        self.Comment = wx.TextCtrl(splitter_window, size=wx.Size(0, 80), 
+        self.Comment = wx.TextCtrl(splitter_window, size=wx.Size(0, 80),
               style=wx.TE_READONLY|wx.TE_MULTILINE)
-        
+
         splitter_window.SplitHorizontally(self.Tree, self.Comment, -80)
-        
+
         self.SetSizer(main_sizer)
-        
+
         # Reference to the project controller
         self.Controller = None
-        
+
         # Variable storing functions and function blocks library to display
         self.BlockList = None
-    
+
     def __del__(self):
         """
         Destructor
         """
         # Remove reference to project controller
         self.Controller = None
-    
+
     def SetController(self, controller):
         """
         Set reference to project controller
         @param controller: Reference to project controller
         """
         self.Controller = controller
-    
+
     def SetBlockList(self, blocklist):
         """
         Set function and function block library to display in TreeCtrl
@@ -133,15 +133,15 @@
         self.BlockList = blocklist
         # Refresh TreeCtrl values
         self.RefreshTree()
-    
+
     def SetFocus(self):
         """
         Called to give focus to LibraryPanel
-        Override wx.Window SetFocus method 
+        Override wx.Window SetFocus method
         """
         # Give focus to SearchCtrl
         self.SearchCtrl.SetFocus()
-    
+
     def ResetTree(self):
         """
         Reset LibraryPanel values displayed in controls
@@ -150,7 +150,7 @@
         self.SearchCtrl.SetValue("")
         self.Tree.DeleteAllItems()
         self.Comment.SetValue("")
-    
+
     def RefreshTree(self):
         """
         Refresh LibraryPanel values displayed in controls
@@ -160,13 +160,13 @@
         if blocktypes is None and self.Controller is not None:
             # Get library from project controller if not defined
             blocktypes = self.Controller.GetBlockTypes()
-        
+
         # Refresh TreeCtrl values if a library is defined
         if blocktypes is not None:
             # List that will contain tree items to be deleted when TreeCtrl
             # will be refreshed
             items_to_delete = []
-            
+
             # Get current selected item for selected it when values refreshed
             selected_item = self.Tree.GetSelection()
             selected_pydata = (self.Tree.GetPyData(selected_item)
@@ -179,16 +179,16 @@
                              if selected_pydata is not None and
                                 selected_pydata["type"] == BLOCK
                              else (None, None))
-            
+
             # Get TreeCtrl root item (hidden)
             root = self.Tree.GetRootItem()
             if not root.IsOk():
                 # Create root if not present
                 root = self.Tree.AddRoot("")
-            
+
             # Iterate over functions and function blocks library categories and
             # add a tree item to root item for each of them
-            
+
             # Get first child under root item
             category_item, root_cookie = self.Tree.GetFirstChild(root)
             for category in blocktypes:
@@ -196,11 +196,11 @@
                 # extracting translated strings for gettext to consider "name"
                 # to be translated
                 category_name = category["name"]
-                
+
                 # Tree item already exists, set item label
                 if category_item.IsOk():
                     self.Tree.SetItemText(category_item, _(category_name))
-                
+
                 # Tree item doesn't exist, add new one to root
                 else:
                     category_item = self.Tree.AppendItem(root, _(category_name))
@@ -209,24 +209,24 @@
                     if wx.Platform != '__WXMSW__':
                         category_item, root_cookie = \
                             self.Tree.GetNextChild(root, root_cookie)
-                
-                # Set data associated to tree item (only save that item is a 
+
+                # Set data associated to tree item (only save that item is a
                 # category)
                 self.Tree.SetPyData(category_item, {"type" : CATEGORY})
-                
+
                 # Iterate over functions and function blocks defined in library
-                # category add a tree item to category tree item for each of 
+                # category add a tree item to category tree item for each of
                 # them
-                
+
                 # Get first child under category tree item
                 blocktype_item, category_cookie = \
                     self.Tree.GetFirstChild(category_item)
                 for blocktype in category["list"]:
-                    
+
                     # Tree item already exists, set item label
                     if blocktype_item.IsOk():
                         self.Tree.SetItemText(blocktype_item, blocktype["name"])
-                    
+
                     # Tree item doesn't exist, add new one to category item
                     else:
                         blocktype_item = self.Tree.AppendItem(
@@ -234,58 +234,58 @@
                         # See comment when adding category
                         if wx.Platform != '__WXMSW__':
                             blocktype_item, category_cookie = \
-                                self.Tree.GetNextChild(category_item, 
+                                self.Tree.GetNextChild(category_item,
                                                        category_cookie)
-                    
+
                     # Define data to associate to block tree item
                     comment = blocktype["comment"]
-                    block_data = {"type" : BLOCK, 
-                                  "block_type" : blocktype["type"], 
-                                  "inputs" : tuple([type 
+                    block_data = {"type" : BLOCK,
+                                  "block_type" : blocktype["type"],
+                                  "inputs" : tuple([type
                                                     for name, type, modifier
-                                                    in blocktype["inputs"]]), 
+                                                    in blocktype["inputs"]]),
                                   "extension" : (len(blocktype["inputs"])
                                                  if blocktype["extensible"]
                                                  else None),
-                                  "comment": _(comment) + 
+                                  "comment": _(comment) +
                                              blocktype.get("usage", "")}
                     self.Tree.SetPyData(blocktype_item, block_data)
-                    
+
                     # Select block tree item in tree if it corresponds to
                     # previously selected one
-                    if selected_infos == (blocktype["name"], 
+                    if selected_infos == (blocktype["name"],
                                           blocktype["inputs"]):
                         self.Tree.SelectItem(blocktype_item)
-                        
+
                         # Update TextCtrl value
                         self.Comment.SetValue(block_data["comment"])
-                
+
                     # Get next block tree item under category tree item
                     blocktype_item, category_cookie = \
                         self.Tree.GetNextChild(category_item, category_cookie)
-                
+
                 # Add every remaining tree item under category tree item after
                 # updating all block items to the list of items to delete
                 while blocktype_item.IsOk():
                     items_to_delete.append(blocktype_item)
                     blocktype_item, category_cookie = \
                         self.Tree.GetNextChild(category_item, category_cookie)
-                
+
                 # Get next category tree item under root item
                 category_item, root_cookie = \
                     self.Tree.GetNextChild(root, root_cookie)
-            
-            # Add every remaining tree item under root item after updating all 
+
+            # Add every remaining tree item under root item after updating all
             # category items to the list of items to delete
             while category_item.IsOk():
                 items_to_delete.append(category_item)
                 category_item, root_cookie = \
                     self.Tree.GetNextChild(root, root_cookie)
-            
+
             # Remove all items in list of items to delete from TreeCtrl
             for item in items_to_delete:
                 self.Tree.Delete(item)
-    
+
     def GetSelectedBlock(self):
         """
         Get selected block informations
@@ -298,17 +298,17 @@
                            if selected_item.IsOk() and
                               selected_item != self.Tree.GetRootItem()
                            else None)
-        
+
         # Return value is None if selected tree item is root or a category
-        return ({"type": self.Tree.GetItemText(selected_item), 
+        return ({"type": self.Tree.GetItemText(selected_item),
                  "inputs": selected_pydata["inputs"]}
-                if selected_pydata is not None and 
+                if selected_pydata is not None and
                    selected_pydata["type"] == BLOCK
                 else None)
-    
+
     def SelectTreeItem(self, name, inputs):
         """
-        Select Tree item corresponding to block informations given 
+        Select Tree item corresponding to block informations given
         @param name: Block type name
         @param inputs: List of block inputs type [input_type,...]
         """
@@ -318,7 +318,7 @@
             # Select tree item found
             self.Tree.SelectItem(item)
             self.Tree.EnsureVisible(item)
-    
+
     def FindTreeItem(self, item, name, inputs = None):
         """
         Find Tree item corresponding to block informations given
@@ -330,12 +330,12 @@
         # Return immediately if item isn't valid
         if not item.IsOk():
             return None
-        
+
         # Get data associated to item to test
         item_pydata = self.Tree.GetPyData(item)
         if item_pydata is not None and item_pydata["type"] == BLOCK:
             # Only test item corresponding to block
-            
+
             # Test if block inputs type are the same than those given
             type_inputs = item_pydata.get("inputs", None)
             type_extension = item_pydata.get("extension", None)
@@ -351,11 +351,11 @@
                     True)
             else:
                 same_inputs = True
-            
+
             # Return item if  block data corresponds to informations given
             if self.Tree.GetItemText(item) == name and same_inputs:
                 return item
-        
+
         # Test item children if item doesn't correspond
         child, child_cookie = self.Tree.GetFirstChild(item)
         while child.IsOk():
@@ -363,9 +363,9 @@
             if result:
                 return result
             child, child_cookie = self.Tree.GetNextChild(item, child_cookie)
-        
+
         return None
-    
+
     def SearchInTree(self, value, mode="first"):
         """
         Search in Tree and select item that name contains string given
@@ -378,13 +378,13 @@
         root = self.Tree.GetRootItem()
         if not root.IsOk():
             return False
-        
+
         # Set function to navigate in Tree item sibling according to search
-        # mode defined 
+        # mode defined
         sibling_function = (self.Tree.GetPrevSibling
                             if mode == "previous"
                             else self.Tree.GetNextSibling)
-        
+
         # Get current selected item (for next and previous mode)
         item = self.Tree.GetSelection()
         if not item.IsOk() or mode == "first":
@@ -392,29 +392,29 @@
             selected = None
         else:
             selected = item
-        
+
         # Navigate through tree items until one matching found or reach tree
         # starting or ending
         while item.IsOk():
-            
+
             # Get item data to get item type
             item_pydata = self.Tree.GetPyData(item)
-            
+
             # Item is a block category
             if (item == root) or item_pydata["type"] == CATEGORY:
-                
-                # Get category first or last child according to search mode 
+
+                # Get category first or last child according to search mode
                 # defined
                 child = (self.Tree.GetLastChild(item)
                          if mode == "previous"
                          else self.Tree.GetFirstChild(item)[0])
-                
+
                 # If category has no child, go to sibling category
                 item = (child if child.IsOk() else sibling_function(item))
-            
+
             # Item is a block
             else:
-                
+
                 # Extract item block name
                 name = self.Tree.GetItemText(item)
                 # Test if block name contains string given
@@ -428,17 +428,17 @@
                     self.Tree.SelectItem(item)
                     self.Tree.EnsureVisible(item)
                     return True
-                
+
                 # Go to next item sibling if block not found
                 next = sibling_function(item)
-                
+
                 # If category has no other child, go to next category sibling
                 item = (next
                         if next.IsOk()
                         else sibling_function(self.Tree.GetItemParent(item)))
-        
+
         return False
-    
+
     def OnSearchCtrlChanged(self, event):
         """
         Called when SearchCtrl text control value changed
@@ -447,7 +447,7 @@
         # Search for block containing SearchCtrl value in 'first' mode
         self.SearchInTree(self.SearchCtrl.GetValue())
         event.Skip()
-    
+
     def OnSearchButtonClick(self, event):
         """
         Called when SearchCtrl search button was clicked
@@ -456,7 +456,7 @@
         # Search for block containing SearchCtrl value in 'next' mode
         self.SearchInTree(self.SearchCtrl.GetValue(), "next")
         event.Skip()
-    
+
     def OnTreeItemSelected(self, event):
         """
         Called when tree item is selected
@@ -468,13 +468,13 @@
             item_pydata["comment"]
             if item_pydata is not None and item_pydata["type"] == BLOCK
             else "")
-        
+
         # Call extra function defined when tree item is selected
         if getattr(self, "_OnTreeItemSelected", None) is not None:
             self._OnTreeItemSelected(event)
-        
+
         event.Skip()
-    
+
     def OnTreeBeginDrag(self, event):
         """
         Called when a drag is started in tree
@@ -482,19 +482,19 @@
         """
         selected_item = event.GetItem()
         item_pydata = self.Tree.GetPyData(selected_item)
-        
+
         # Item dragged is a block
         if item_pydata is not None and item_pydata["type"] == BLOCK:
             # Start a drag'n drop
             data = wx.TextDataObject(str(
-                (self.Tree.GetItemText(selected_item), 
-                 item_pydata["block_type"], 
-                 "", 
+                (self.Tree.GetItemText(selected_item),
+                 item_pydata["block_type"],
+                 "",
                  item_pydata["inputs"])))
             dragSource = wx.DropSource(self.Tree)
             dragSource.SetData(data)
             dragSource.DoDragDrop()
-    
+
     def OnKeyDown(self, event):
         """
         Called when key is pressed in SearchCtrl text control
@@ -503,17 +503,17 @@
         # Get event keycode and value in SearchCtrl
         keycode = event.GetKeyCode()
         search_value = self.SearchCtrl.GetValue()
-        
+
         # Up key was pressed and SearchCtrl isn't empty, search for block in
-        # 'previous' mode 
+        # 'previous' mode
         if keycode == wx.WXK_UP and search_value != "":
             self.SearchInTree(search_value, "previous")
-        
+
         # Down key was pressed and SearchCtrl isn't empty, search for block in
-        # 'next' mode 
+        # 'next' mode
         elif keycode == wx.WXK_DOWN and search_value != "":
             self.SearchInTree(search_value, "next")
-        
+
         # Handle key normally
         else:
             event.Skip()
--- a/controls/LocationCellEditor.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/LocationCellEditor.py	Mon Aug 14 19:13:01 2017 +0300
@@ -27,31 +27,31 @@
 from dialogs.BrowseLocationsDialog import BrowseLocationsDialog
 
 class LocationCellControl(wx.PyControl):
-    
+
     '''
     Custom cell editor control with a text box and a button that launches
     the BrowseLocationsDialog.
     '''
     def __init__(self, parent):
         wx.Control.__init__(self, parent)
-        
+
         main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         # create location text control
-        self.Location = wx.TextCtrl(self, size=wx.Size(0, -1), 
+        self.Location = wx.TextCtrl(self, size=wx.Size(0, -1),
               style=wx.TE_PROCESS_ENTER)
         self.Location.Bind(wx.EVT_KEY_DOWN, self.OnLocationChar)
         main_sizer.AddWindow(self.Location, flag=wx.GROW)
-        
+
         # create browse button
         self.BrowseButton = wx.Button(self, label='...', size=wx.Size(30, -1))
         self.BrowseButton.Bind(wx.EVT_BUTTON, self.OnBrowseButtonClick)
         main_sizer.AddWindow(self.BrowseButton, flag=wx.GROW)
-        
+
         self.Bind(wx.EVT_SIZE, self.OnSize)
-        
+
         self.SetSizer(main_sizer)
 
         self.Controller = None
@@ -73,7 +73,7 @@
     def SetValue(self, value):
         self.Default = value
         self.Location.SetValue(value)
-    
+
     def GetValue(self):
         return self.Location.GetValue()
 
@@ -88,14 +88,14 @@
         else:
             infos = None
         dialog.Destroy()
-        
+
         if infos is not None:
             location = infos["location"]
             # set the location
             if not infos["location"].startswith("%"):
-                dialog = wx.SingleChoiceDialog(self, 
-                      _("Select a variable class:"), _("Variable class"), 
-                      [_("Input"), _("Output"), _("Memory")], 
+                dialog = wx.SingleChoiceDialog(self,
+                      _("Select a variable class:"), _("Variable class"),
+                      [_("Input"), _("Output"), _("Memory")],
                       wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
                 if dialog.ShowModal() == wx.ID_OK:
                     selected = dialog.GetSelection()
@@ -111,7 +111,7 @@
                     location = "%Q" + location
                 else:
                     location = "%M" + location
-            
+
             self.Location.SetValue(location)
             self.VarType = infos["IEC_type"]
 
@@ -129,7 +129,7 @@
 
     def SetInsertionPoint(self, i):
         self.Location.SetInsertionPoint(i)
-    
+
     def SetFocus(self):
         self.Location.SetFocus()
 
@@ -139,14 +139,14 @@
     '''
     def __init__(self, table, controller):
         wx.grid.PyGridCellEditor.__init__(self)
-        
+
         self.Table = table
         self.Controller = controller
 
     def __del__(self):
         self.CellControl = None
         self.Controller = None
-    
+
     def Create(self, parent, id, evt_handler):
         self.CellControl = LocationCellControl(parent)
         self.SetControl(self.CellControl)
@@ -169,15 +169,15 @@
             self.Table.SetValueByName(row, 'Type', self.CellControl.GetVarType())
         self.CellControl.Disable()
         return changed
-        
+
     if wx.VERSION >= (3, 0, 0):
         def EndEdit(self, row, col, grid, oldval):
             return self.EndEditInternal(row, col, grid, oldval)
     else:
         def EndEdit(self, row, col, grid):
-            old_loc = self.Table.GetValueByName(row, 'Location')            
+            old_loc = self.Table.GetValueByName(row, 'Location')
             return self.EndEditInternal(row, col, grid, old_loc)
-    
+
     def SetSize(self, rect):
         self.CellControl.SetDimensions(rect.x + 1, rect.y,
                                         rect.width, rect.height,
@@ -185,4 +185,3 @@
 
     def Clone(self):
         return LocationCellEditor(self.Table, self.Controller)
-
--- a/controls/PouInstanceVariablesPanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/PouInstanceVariablesPanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -59,14 +59,14 @@
             w, h = self.GetClientSize()
             total_h = self.GetLineHeight(item)
             r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0])
-            
+
             bbox_width = (r_image_w + 4) * len(rightimages) + 4
             bbox_height = r_image_h + 8
             bbox_x = w - bbox_width
             bbox_y = item.GetY() + ((total_h > r_image_h) and [(total_h-r_image_h)/2] or [0])[0]
-            
+
             return wx.Rect(bbox_x, bbox_y, bbox_width, bbox_height)
-        
+
         return None
 
     def IsOverItemRightImage(self, item, point):
@@ -75,30 +75,30 @@
             point = self.CalcUnscrolledPosition(point)
             r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0])
             images_bbx = self.GetItemRightImagesBBox(item)
-            
+
             rect = wx.Rect(images_bbx.x + 4, images_bbx.y + 4,
                            r_image_w, r_image_h)
             for r_image in rightimages:
                 if rect.Inside(point):
                     return r_image
                 rect.x += r_image_w + 4
-            
+
             return None
-                
+
     def PaintItem(self, item, dc, level, align):
         CT.CustomTreeCtrl.PaintItem(self, item, dc, level, align)
-        
+
         rightimages = item.GetRightImages()
         if len(rightimages) > 0:
             images_bbx = self.GetItemRightImagesBBox(item)
             r_image_w, r_image_h = self._imageListRight.GetSize(rightimages[0])
-            
+
             dc.SetBrush(wx.TRANSPARENT_BRUSH)
             dc.SetPen(wx.TRANSPARENT_PEN)
-            
+
             bg_width = (r_image_w + 4) * len(rightimages) + 4
             bg_height = r_image_h + 8
-            dc.DrawRectangle(images_bbx.x, images_bbx.y, 
+            dc.DrawRectangle(images_bbx.x, images_bbx.y,
                              images_bbx.width, images_bbx.height)
             x_pos = images_bbx.x + 4
             for r_image in rightimages:
@@ -106,7 +106,7 @@
                     r_image, dc, x_pos, images_bbx.y + 4,
                     wx.IMAGELIST_DRAW_TRANSPARENT)
                 x_pos += r_image_w + 4
-    
+
 _ButtonCallbacks = namedtuple("ButtonCallbacks", ["leftdown", "dclick"])
 
 from PLCControler import ITEMS_VARIABLE, ITEM_CONFIGURATION, ITEM_RESOURCE, ITEM_POU, ITEM_TRANSITION, ITEM_ACTION
@@ -115,26 +115,26 @@
 class PouInstanceVariablesPanel(wx.Panel):
 
     def __init__(self, parent, window, controller, debug):
-        wx.Panel.__init__(self, name='PouInstanceTreePanel', 
-                parent=parent, pos=wx.Point(0, 0), 
+        wx.Panel.__init__(self, name='PouInstanceTreePanel',
+                parent=parent, pos=wx.Point(0, 0),
                 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
+
         self.ParentButton = wx.lib.buttons.GenBitmapButton(self,
               bitmap=GetBitmap("top"), size=wx.Size(28, 28), style=wx.NO_BORDER)
         self.ParentButton.SetToolTipString(_("Parent instance"))
-        self.Bind(wx.EVT_BUTTON, self.OnParentButtonClick, 
+        self.Bind(wx.EVT_BUTTON, self.OnParentButtonClick,
                 self.ParentButton)
-        
+
         self.InstanceChoice = wx.ComboBox(self, size=wx.Size(0, 0), style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnInstanceChoiceChanged,
                 self.InstanceChoice)
-        
-        self.DebugButton = wx.lib.buttons.GenBitmapButton(self, 
+
+        self.DebugButton = wx.lib.buttons.GenBitmapButton(self,
               bitmap=GetBitmap("debug_instance"), size=wx.Size(28, 28), style=wx.NO_BORDER)
         self.DebugButton.SetToolTipString(_("Debug instance"))
-        self.Bind(wx.EVT_BUTTON, self.OnDebugButtonClick, 
+        self.Bind(wx.EVT_BUTTON, self.OnDebugButtonClick,
                 self.DebugButton)
-        
+
         self.VariablesList = CustomTreeCtrlWithRightImage(self,
               style=wx.SUNKEN_BORDER,
               agwStyle=CT.TR_NO_BUTTONS|
@@ -150,54 +150,54 @@
                 self.OnVariablesListItemActivated)
         self.VariablesList.Bind(wx.EVT_LEFT_DOWN, self.OnVariablesListLeftDown)
         self.VariablesList.Bind(wx.EVT_KEY_DOWN, self.OnVariablesListKeyDown)
-        
+
         self.TreeRightImageList = wx.ImageList(24, 24)
         self.EditImage = self.TreeRightImageList.Add(GetBitmap("edit"))
         self.DebugInstanceImage = self.TreeRightImageList.Add(GetBitmap("debug_instance"))
         self.VariablesList.SetRightImageList(self.TreeRightImageList)
-        
+
         self.ButtonCallBacks = {
             self.EditImage: _ButtonCallbacks(
                 self.EditButtonCallback, None),
             self.DebugInstanceImage: _ButtonCallbacks(
                 self.DebugButtonCallback, self.DebugButtonDClickCallback)}
-        
+
         buttons_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0)
         buttons_sizer.AddWindow(self.ParentButton)
         buttons_sizer.AddWindow(self.InstanceChoice, flag=wx.GROW)
         buttons_sizer.AddWindow(self.DebugButton)
         buttons_sizer.AddGrowableCol(1)
         buttons_sizer.AddGrowableRow(0)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
         main_sizer.AddSizer(buttons_sizer, flag=wx.GROW)
         main_sizer.AddWindow(self.VariablesList, flag=wx.GROW)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.ParentWindow = window
         self.Controller = controller
         self.Debug = debug
         if not self.Debug:
             self.DebugButton.Hide()
-        
+
         self.PouTagName = None
         self.PouInfos = None
         self.PouInstance = None
-        
+
     def __del__(self):
         self.Controller = None
-    
+
     def SetTreeImageList(self, tree_image_list):
         self.VariablesList.SetImageList(tree_image_list)
-    
+
     def SetController(self, controller):
         self.Controller = controller
-    
+
         self.RefreshView()
-    
+
     def SetPouType(self, tagname, pou_instance=None):
         if self.Controller is not None:
             if tagname == "Project":
@@ -206,7 +206,7 @@
                     tagname = self.Controller.ComputeConfigurationName(config_name)
             if pou_instance is not None:
                 self.PouInstance = pou_instance
-            
+
             if self.PouTagName != tagname:
                 self.PouTagName = tagname
                 self.RefreshView()
@@ -214,20 +214,20 @@
                 self.RefreshInstanceChoice()
         else:
             self.RefreshView()
-    
+
     def ResetView(self):
         self.Controller = None
-        
+
         self.PouTagName = None
         self.PouInfos = None
         self.PouInstance = None
-        
+
         self.RefreshView()
-    
+
     def RefreshView(self):
         self.Freeze()
         self.VariablesList.DeleteAllItems()
-        
+
         if self.Controller is not None and self.PouTagName is not None:
             if self.PouTagName.split('::')[0] in ['A', 'T']:
                 self.PouInfos = self.Controller.GetPouVariables('P::%s' % self.PouTagName.split('::')[1], self.Debug)
@@ -244,24 +244,24 @@
                     text = "%s (%s)" % (var_infos.name, var_infos.type)
                 else:
                     text = var_infos.name
-                
+
                 right_images = []
                 if var_infos.edit:
                     right_images.append(self.EditImage)
-                
+
                 if var_infos.debug and self.Debug:
                     right_images.append(self.DebugInstanceImage)
-                
+
                 item = self.VariablesList.AppendItem(root, text)
                 item.SetRightImages(right_images)
                 self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos.var_class))
                 self.VariablesList.SetPyData(item, var_infos)
-            
+
         self.RefreshInstanceChoice()
         self.RefreshButtons()
-        
+
         self.Thaw()
-    
+
     def RefreshInstanceChoice(self):
         self.InstanceChoice.Clear()
         self.InstanceChoice.SetValue("")
@@ -279,12 +279,12 @@
             else:
                 self.PouInstance = None
                 self.InstanceChoice.SetValue(_("Select an instance"))
-    
+
     def RefreshButtons(self):
         enabled = self.InstanceChoice.GetSelection() != -1
         self.ParentButton.Enable(enabled and self.PouInfos.var_class != ITEM_CONFIGURATION)
         self.DebugButton.Enable(enabled and self.PouInfos.debug and self.Debug)
-        
+
         root = self.VariablesList.GetRootItem()
         if root is not None and root.IsOk():
             item, item_cookie = self.VariablesList.GetFirstChild(root)
@@ -295,12 +295,12 @@
                         if child.GetName() != "edit":
                             child.Enable(enabled)
                 item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie)
-    
+
     def EditButtonCallback(self, infos):
         var_class = infos.var_class
         if var_class == ITEM_RESOURCE:
             tagname = self.Controller.ComputeConfigurationResourceName(
-                self.InstanceChoice.GetStringSelection(), 
+                self.InstanceChoice.GetStringSelection(),
                 infos.name)
         elif var_class == ITEM_TRANSITION:
             tagname = self.Controller.ComputePouTransitionName(
@@ -314,7 +314,7 @@
             var_class = ITEM_POU
             tagname = self.Controller.ComputePouName(infos.type)
         self.ParentWindow.EditProjectElement(var_class, tagname)
-    
+
     def DebugButtonCallback(self, infos):
         if self.InstanceChoice.GetSelection() != -1:
             var_class = infos.var_class
@@ -344,16 +344,16 @@
                     var_class,
                     var_path,
                     self.Controller.ComputePouName(infos.type))
-    
+
     def DebugButtonDClickCallback(self, infos):
         if self.InstanceChoice.GetSelection() != -1:
             if infos.var_class in ITEMS_VARIABLE:
                 self.ParentWindow.AddDebugVariable(
-                    "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
-                               infos.name), 
+                    "%s.%s" % (self.InstanceChoice.GetStringSelection(),
+                               infos.name),
                     force=True,
                     graph=True)
-    
+
     def ShowInstanceChoicePopup(self):
         self.InstanceChoice.SetFocusFromKbd()
         size = self.InstanceChoice.GetSize()
@@ -364,7 +364,7 @@
         #event = wx.KeyEvent(wx.EVT_KEY_DOWN._getEvtType())
         #event.m_keyCode = wx.WXK_SPACE
         self.InstanceChoice.GetEventHandler().ProcessEvent(event)
-    
+
     def OnParentButtonClick(self, event):
         if self.InstanceChoice.GetSelection() != -1:
             parent_path = self.InstanceChoice.GetStringSelection().rsplit(".", 1)[0]
@@ -373,11 +373,11 @@
                 wx.CallAfter(self.SetPouType, tagname, parent_path)
                 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname)
         event.Skip()
-        
+
     def OnInstanceChoiceChanged(self, event):
         self.RefreshButtons()
         event.Skip()
-        
+
     def OnDebugButtonClick(self, event):
         if self.InstanceChoice.GetSelection() != -1:
             self.ParentWindow.OpenDebugViewer(
@@ -385,26 +385,26 @@
                 self.InstanceChoice.GetStringSelection(),
                 self.PouTagName)
         event.Skip()
-    
+
     def OnVariablesListItemActivated(self, event):
         selected_item = event.GetItem()
         if selected_item is not None and selected_item.IsOk():
             item_infos = self.VariablesList.GetPyData(selected_item)
             if item_infos is not None:
-                
+
                 item_button = self.VariablesList.IsOverItemRightImage(
                     selected_item, event.GetPoint())
                 if item_button is not None:
                     callback = self.ButtonCallBacks[item_button].dclick
                     if callback is not None:
                         callback(item_infos)
-                
+
                 elif item_infos.var_class not in ITEMS_VARIABLE:
                     instance_path = self.InstanceChoice.GetStringSelection()
                     if item_infos.var_class == ITEM_RESOURCE:
                         if instance_path != "":
                             tagname = self.Controller.ComputeConfigurationResourceName(
-                                           instance_path, 
+                                           instance_path,
                                            item_infos.name)
                         else:
                             tagname = None
@@ -424,7 +424,7 @@
                         self.SetPouType(tagname, item_path)
                         self.ParentWindow.SelectProjectTreeItem(tagname)
         event.Skip()
-    
+
     def OnVariablesListLeftDown(self, event):
         if self.InstanceChoice.GetSelection() == -1:
             wx.CallAfter(self.ShowInstanceChoicePopup)
@@ -434,15 +434,15 @@
             if item is not None:
                 item_infos = self.VariablesList.GetPyData(item)
                 if item_infos is not None:
-                    
+
                     item_button = self.VariablesList.IsOverItemRightImage(
                         item, event.GetPosition())
                     if item_button is not None:
                         callback = self.ButtonCallBacks[item_button].leftdown
                         if callback is not None:
                             callback(item_infos)
-                
-                    elif (flags & CT.TREE_HITTEST_ONITEMLABEL and 
+
+                    elif (flags & CT.TREE_HITTEST_ONITEMLABEL and
                           item_infos.var_class in ITEMS_VARIABLE):
                         self.ParentWindow.EnsureTabVisible(
                             self.ParentWindow.DebugVariablePanel)
@@ -457,4 +457,3 @@
         keycode = event.GetKeyCode()
         if keycode != wx.WXK_LEFT:
             event.Skip()
-
--- a/controls/ProjectPropertiesPanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/ProjectPropertiesPanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -31,7 +31,7 @@
 
 REQUIRED_PARAMS = ["projectName", "productName", "productVersion", "companyName"]
 
-[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
+[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
 ] = range(10)
 
@@ -40,7 +40,7 @@
 #-------------------------------------------------------------------------------
 
 class ProjectPropertiesPanel(wx.Notebook):
-    
+
     def AddSizerParams(self, parent, sizer, params):
         for idx, (name, label) in enumerate(params):
             border = 0
@@ -48,17 +48,17 @@
                 border |= wx.TOP
             elif idx == len(params) - 1:
                 border |= wx.BOTTOM
-            
+
             st = wx.StaticText(parent, label=label)
-            sizer.AddWindow(st, border=10, 
+            sizer.AddWindow(st, border=10,
                   flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
-            
+
             tc = wx.TextCtrl(parent, style=wx.TE_PROCESS_ENTER)
             setattr(self, name, tc)
             callback = self.GetTextCtrlChangedFunction(tc, name)
             self.Bind(wx.EVT_TEXT_ENTER, callback, tc)
             tc.Bind(wx.EVT_KILL_FOCUS, callback)
-            sizer.AddWindow(tc, border=10, 
+            sizer.AddWindow(tc, border=10,
                   flag=wx.GROW|border|wx.RIGHT)
 
     def __init__(self, parent, controller=None, window=None, enable_required=True):
@@ -67,36 +67,36 @@
         self.Controller = controller
         self.ParentWindow = window
         self.Values = None
-        
+
         # Project Panel elements
 
         self.ProjectPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
         projectpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15)
         projectpanel_sizer.AddGrowableCol(1)
         self.ProjectPanel.SetSizer(projectpanel_sizer)
-        
+
         self.AddSizerParams(self.ProjectPanel, projectpanel_sizer,
               [("projectName", _('Project Name (required):')),
                ("projectVersion", _('Project Version (optional):')),
                ("productName", _('Product Name (required):')),
                ("productVersion", _('Product Version (required):')),
                ("productRelease", _('Product Release (optional):'))])
-        
+
         self.AddPage(self.ProjectPanel, _("Project"))
-        
+
         # Author Panel elements
 
         self.AuthorPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
         authorpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15)
         authorpanel_sizer.AddGrowableCol(1)
         self.AuthorPanel.SetSizer(authorpanel_sizer)
-        
+
         self.AddSizerParams(self.AuthorPanel, authorpanel_sizer,
               [("companyName", _('Company Name (required):')),
                ("companyURL", _('Company URL (optional):')),
                ("authorName", _('Author Name (optional):')),
                ("organization", _('Organization (optional):'))])
-        
+
         self.AddPage(self.AuthorPanel, _("Author"))
 
         # Graphics Panel elements
@@ -106,47 +106,47 @@
         graphicpanel_sizer.AddGrowableCol(0)
         graphicpanel_sizer.AddGrowableRow(3)
         self.GraphicsPanel.SetSizer(graphicpanel_sizer)
-        
+
         pageSize_st = wx.StaticText(self.GraphicsPanel,
               label=_('Page Size (optional):'))
-        graphicpanel_sizer.AddWindow(pageSize_st, border=10, 
+        graphicpanel_sizer.AddWindow(pageSize_st, border=10,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         pageSize_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
         pageSize_sizer.AddGrowableCol(1)
-        graphicpanel_sizer.AddSizer(pageSize_sizer, border=10, 
+        graphicpanel_sizer.AddSizer(pageSize_sizer, border=10,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         for name, label in [('PageWidth', _('Width:')),
                             ('PageHeight', _('Height:'))]:
             st = wx.StaticText(self.GraphicsPanel, label=label)
-            pageSize_sizer.AddWindow(st, border=12, 
+            pageSize_sizer.AddWindow(st, border=12,
                   flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-            
-            sp = wx.SpinCtrl(self.GraphicsPanel, 
+
+            sp = wx.SpinCtrl(self.GraphicsPanel,
                   min=0, max=2**16, style=wx.TE_PROCESS_ENTER)
             setattr(self, name, sp)
             callback = self.GetPageSizeChangedFunction(sp, name)
             self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
             sp.Bind(wx.EVT_KILL_FOCUS, callback)
             pageSize_sizer.AddWindow(sp, flag=wx.GROW)
-        
+
         scaling_st = wx.StaticText(self.GraphicsPanel,
               label=_('Grid Resolution:'))
-        graphicpanel_sizer.AddWindow(scaling_st, border=10, 
+        graphicpanel_sizer.AddWindow(scaling_st, border=10,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         scaling_nb = wx.Notebook(self.GraphicsPanel)
-        graphicpanel_sizer.AddWindow(scaling_nb, border=10, 
+        graphicpanel_sizer.AddWindow(scaling_nb, border=10,
               flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         self.Scalings = {}
         for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]:
             scaling_panel = wx.Panel(scaling_nb, style=wx.TAB_TRAVERSAL)
             scalingpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
             scalingpanel_sizer.AddGrowableCol(1)
             scaling_panel.SetSizer(scalingpanel_sizer)
-            
+
             scaling_controls = []
             for idx, (name, label) in enumerate([('XScale', _('Horizontal:')),
                                                  ('YScale', _('Vertical:'))]):
@@ -154,67 +154,67 @@
                     border = wx.TOP
                 else:
                     border = wx.BOTTOM
-                
+
                 st = wx.StaticText(scaling_panel, label=label)
-                scalingpanel_sizer.AddWindow(st, border=10, 
+                scalingpanel_sizer.AddWindow(st, border=10,
                       flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
-                
-                sp = wx.SpinCtrl(scaling_panel, 
+
+                sp = wx.SpinCtrl(scaling_panel,
                       min=0, max=2**16, style=wx.TE_PROCESS_ENTER)
                 scaling_controls.append(sp)
                 callback = self.GetScalingChangedFunction(sp, language, name)
                 self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
                 sp.Bind(wx.EVT_KILL_FOCUS, callback)
-                scalingpanel_sizer.AddWindow(sp, border=10, 
+                scalingpanel_sizer.AddWindow(sp, border=10,
                       flag=wx.GROW|border|wx.RIGHT)
-        
+
             self.Scalings[language] = scaling_controls
             scaling_nb.AddPage(scaling_panel, translation)
-        
+
         self.AddPage(self.GraphicsPanel, _("Graphics"))
 
         # Miscellaneous Panel elements
 
-        self.MiscellaneousPanel = wx.Panel(id=-1, parent=self, 
+        self.MiscellaneousPanel = wx.Panel(id=-1, parent=self,
               name='MiscellaneousPanel', pos=wx.Point(0, 0),
               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
         miscellaneouspanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15)
         miscellaneouspanel_sizer.AddGrowableCol(1)
         miscellaneouspanel_sizer.AddGrowableRow(1)
         self.MiscellaneousPanel.SetSizer(miscellaneouspanel_sizer)
-        
+
         language_label = wx.StaticText(self.MiscellaneousPanel,
               label=_('Language (optional):'))
-        miscellaneouspanel_sizer.AddWindow(language_label, border=10, 
+        miscellaneouspanel_sizer.AddWindow(language_label, border=10,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
-        
-        self.Language = wx.ComboBox(self.MiscellaneousPanel, 
+
+        self.Language = wx.ComboBox(self.MiscellaneousPanel,
               style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnLanguageChanged, self.Language)
-        miscellaneouspanel_sizer.AddWindow(self.Language, border=10, 
+        miscellaneouspanel_sizer.AddWindow(self.Language, border=10,
               flag=wx.GROW|wx.TOP|wx.RIGHT)
-        
+
         description_label = wx.StaticText(self.MiscellaneousPanel,
               label=_('Content Description (optional):'))
-        miscellaneouspanel_sizer.AddWindow(description_label, border=10, 
+        miscellaneouspanel_sizer.AddWindow(description_label, border=10,
               flag=wx.BOTTOM|wx.LEFT)
-        
-        self.ContentDescription = wx.TextCtrl(self.MiscellaneousPanel, 
+
+        self.ContentDescription = wx.TextCtrl(self.MiscellaneousPanel,
               size=wx.Size(240,150), style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER)
-        self.Bind(wx.EVT_TEXT_ENTER, self.OnContentDescriptionChanged, 
+        self.Bind(wx.EVT_TEXT_ENTER, self.OnContentDescriptionChanged,
               self.ContentDescription)
-        self.ContentDescription.Bind(wx.EVT_KILL_FOCUS, 
+        self.ContentDescription.Bind(wx.EVT_KILL_FOCUS,
               self.OnContentDescriptionChanged)
-        miscellaneouspanel_sizer.AddWindow(self.ContentDescription, border=10, 
+        miscellaneouspanel_sizer.AddWindow(self.ContentDescription, border=10,
               flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
-        
+
         self.AddPage(self.MiscellaneousPanel, _("Miscellaneous"))
-        
+
         for param in REQUIRED_PARAMS:
             getattr(self, param).Enable(enable_required)
-           
+
         languages = ["", "en-US", "fr-FR", "zh-CN", "ru-RU"]
-        
+
         for language in languages:
             self.Language.Append(language)
 
@@ -241,13 +241,13 @@
                 tc = getattr(self, item, None)
                 if tc is not None:
                     tc.SetValue(value)
-        
+
     def GetValues(self):
         values = {}
         for param in ["projectName", "projectVersion",
                       "productName", "productVersion",
                       "productRelease", "companyName",
-                      "companyURL", "authorName", 
+                      "companyURL", "authorName",
                       "organization"]:
             value = getattr(self, param).GetValue()
             if param in REQUIRED_PARAMS or value != "":
@@ -270,7 +270,7 @@
             values["scaling"][language] = (self.Scalings[language][0].GetValue(),
                                            self.Scalings[language][1].GetValue())
         return values
-    
+
     def GetTextCtrlChangedFunction(self, textctrl, name):
         def TextCtrlChangedFunction(event):
             if self.Controller is not None and self.Values is not None:
@@ -304,7 +304,7 @@
                     wx.CallAfter(self.RefreshView)
             event.Skip()
         return PageSizeChangedFunction
-    
+
     def GetScalingChangedFunction(self, spinctrl, language, name):
         def ScalingChangedFunction(event):
             if self.Controller is not None:
@@ -324,7 +324,7 @@
                     wx.CallAfter(self.RefreshView)
             event.Skip()
         return ScalingChangedFunction
-    
+
     def OnLanguageChanged(self, event):
         if self.Controller is not None:
             if self.Values is not None:
@@ -339,7 +339,7 @@
                 self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
                 wx.CallAfter(self.RefreshView)
         event.Skip()
-        
+
     def OnContentDescriptionChanged(self, event):
         if self.Controller is not None:
             if self.Values is not None:
--- a/controls/SearchResultPanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/SearchResultPanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -45,7 +45,7 @@
 #-------------------------------------------------------------------------------
 
 [ID_SEARCHRESULTPANEL, ID_SEARCHRESULTPANELHEADERLABEL,
- ID_SEARCHRESULTPANELSEARCHRESULTSTREE, ID_SEARCHRESULTPANELRESETBUTTON, 
+ ID_SEARCHRESULTPANELSEARCHRESULTSTREE, ID_SEARCHRESULTPANELRESETBUTTON,
 ] = [wx.NewId() for _init_ctrls in range(4)]
 
 class SearchResultPanel(wx.Panel):
@@ -60,7 +60,7 @@
     def _init_coll_MainSizer_Items(self, parent):
         parent.AddSizer(self.HeaderSizer, 0, border=0, flag=wx.GROW)
         parent.AddWindow(self.SearchResultsTree, 1, border=0, flag=wx.GROW)
-    
+
     def _init_coll_MainSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
         parent.AddGrowableRow(1)
@@ -68,18 +68,18 @@
     def _init_coll_HeaderSizer_Items(self, parent):
         parent.AddWindow(self.HeaderLabel, 1, border=5, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
         parent.AddWindow(self.ResetButton, 0, border=0, flag=0)
-    
+
     def _init_coll_HeaderSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
-    
+
     def _init_sizers(self):
         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
         self.HeaderSizer = wx.BoxSizer(wx.HORIZONTAL)
-        
+
         self._init_coll_MainSizer_Items(self.MainSizer)
         self._init_coll_MainSizer_Growables(self.MainSizer)
         self._init_coll_HeaderSizer_Items(self.HeaderSizer)
-        
+
         self.SetSizer(self.MainSizer)
 
     def _init_ctrls(self, prnt):
@@ -90,7 +90,7 @@
         self.HeaderLabel = wx.StaticText(id=ID_SEARCHRESULTPANELHEADERLABEL,
               name='HeaderLabel', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
-        
+
         search_results_tree_style = CT.TR_HAS_BUTTONS|CT.TR_NO_LINES|CT.TR_HAS_VARIABLE_ROW_HEIGHT
         self.SearchResultsTree = CT.CustomTreeCtrl(id=ID_SEARCHRESULTPANELSEARCHRESULTSTREE,
               name="SearchResultsTree", parent=self,
@@ -99,23 +99,23 @@
             self.SearchResultsTree.SetAGWWindowStyleFlag(search_results_tree_style)
         self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnSearchResultsTreeItemActivated,
               id=ID_SEARCHRESULTPANELSEARCHRESULTSTREE)
-        
+
         self.ResetButton = wx.lib.buttons.GenBitmapButton(self,
               bitmap=GetBitmap("reset"), size=wx.Size(28, 28), style=wx.NO_BORDER)
         self.ResetButton.SetToolTipString(_("Reset search result"))
         self.Bind(wx.EVT_BUTTON, self.OnResetButton, self.ResetButton)
-        
+
         self._init_sizers()
 
     def __init__(self, parent, window):
         self.ParentWindow = window
-        
+
         self._init_ctrls(parent)
-        
+
         # Define Tree item icon list
         self.TreeImageList = wx.ImageList(16, 16)
         self.TreeImageDict = {}
-        
+
         # Icons for other items
         for imgname, itemtype in [
             #editables
@@ -129,40 +129,40 @@
             ("IL",             "IL"),
             ("ST",             "ST")]:
             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
-        
+
         for itemtype in ["function", "functionBlock", "program",
                          "comment", "block", "io_variable",
                          "connector", "contact", "coil",
-                         "step", "transition", "jump", 
-                         "var_local", "var_input", 
+                         "step", "transition", "jump",
+                         "var_local", "var_input",
                          "var_inout", "var_output"]:
             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(itemtype.upper()))
-        
+
         # Assign icon list to TreeCtrl
         self.SearchResultsTree.SetImageList(self.TreeImageList)
-        
+
         self.ResetSearchResults()
 
     def SetSearchResults(self, criteria, search_results):
         self.Criteria = criteria
         self.SearchResults = {}
         self.ElementsOrder = []
-        
+
         for infos, start, end, text in search_results:
             if infos[0] not in self.ElementsOrder:
                 self.ElementsOrder.append(infos[0])
-            
+
             results = self.SearchResults.setdefault(infos[0], [])
             results.append((infos, start, end, text))
-        
+
         self.RefreshView()
-    
+
     def ResetSearchResults(self):
         self.Criteria = None
         self.ElementsOrder = []
         self.SearchResults = {}
         self.RefreshView()
-    
+
     def RefreshView(self):
         self.SearchResultsTree.DeleteAllItems()
         if self.Criteria is None:
@@ -180,19 +180,19 @@
             for tagname in self.ElementsOrder:
                 results = self.SearchResults.get(tagname, [])
                 matches_number += len(results)
-                
+
                 words = tagname.split("::")
-                
+
                 element_type = self.ParentWindow.Controler.GetElementType(tagname)
                 if element_type == ITEM_POU:
                     element_type = self.ParentWindow.Controler.GetPouType(words[1])
-                
+
                 element_infos = {"name": words[-1],
                                  "type": element_type,
                                  "data": tagname,
                                  "text": None,
                                  "matches": len(results)}
-                
+
                 children = element_infos.setdefault("children", [])
                 for infos, start, end, text in results:
                     if infos[1] == "name" or element_type == ITEM_DATATYPE:
@@ -223,7 +223,7 @@
                                    "children": [],
                                   }
                     children.append(child_infos)
-                
+
                 if len(words) > 2:
                     for _element_infos in search_results_tree_children:
                         if _element_infos["name"] == words[1]:
@@ -234,41 +234,41 @@
                         search_results_tree_children.append(element_infos)
                 else:
                     search_results_tree_children.append(element_infos)
-            
+
             if matches_number < 2:
                 header_format = _("'{a1}' - {a2} match in project")
             else:
                 header_format = _("'{a1}' - {a2} matches in project")
-            
+
             self.HeaderLabel.SetLabel(header_format.format(a1 = self.Criteria["find_pattern"], a2 = matches_number))
             self.ResetButton.Enable(True)
-            
+
             if matches_number > 0:
                 root = self.SearchResultsTree.GetRootItem()
                 if root is None:
                     root = self.SearchResultsTree.AddRoot(search_results_tree_infos["name"])
                 self.GenerateSearchResultsTreeBranch(root, search_results_tree_infos)
                 self.SearchResultsTree.Expand(root)
-    
+
     def GetTextCtrlClickFunction(self, item):
         def OnTextCtrlClick(event):
             self.SearchResultsTree.SelectItem(item)
             event.Skip()
         return OnTextCtrlClick
-    
+
     def GetTextCtrlDClickFunction(self, item):
         def OnTextCtrlDClick(event):
             self.ShowSearchResults(item)
             event.Skip()
         return OnTextCtrlDClick
-    
+
     def GenerateSearchResultsTreeBranch(self, root, infos):
         to_delete = []
         if infos["name"] == "body":
             item_name = "%d:" % infos["data"][1][0]
         else:
             item_name = infos["name"]
-        
+
         self.SearchResultsTree.SetItemText(root, item_name)
         self.SearchResultsTree.SetPyData(root, infos["data"])
         self.SearchResultsTree.SetItemBackgroundColour(root, wx.WHITE)
@@ -278,7 +278,7 @@
                 self.SearchResultsTree.SetItemImage(root, self.TreeImageDict[self.ParentWindow.Controler.GetPouType(infos["name"])])
             else:
                 self.SearchResultsTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
-        
+
         text = None
         if infos["text"] is not None:
             text = infos["text"]
@@ -291,12 +291,12 @@
             text = _("(%d matches)") % infos["matches"]
             start_idx, end_idx = 0, len(text)
             style = wx.TextAttr(wx.Colour(0, 127, 174))
-        
+
         if text is not None:
             text_ctrl_style = wx.BORDER_NONE|wx.TE_READONLY|wx.TE_RICH2
             if wx.Platform != '__WXMSW__' or len(text.splitlines()) > 1:
                 text_ctrl_style |= wx.TE_MULTILINE
-            text_ctrl = wx.TextCtrl(id=-1, parent=self.SearchResultsTree, pos=wx.Point(0, 0), 
+            text_ctrl = wx.TextCtrl(id=-1, parent=self.SearchResultsTree, pos=wx.Point(0, 0),
                     value=text, style=text_ctrl_style)
             width, height = text_ctrl.GetTextExtent(text)
             text_ctrl.SetClientSize(wx.Size(width + 1, height))
@@ -306,7 +306,7 @@
             text_ctrl.SetInsertionPoint(0)
             text_ctrl.SetStyle(start_idx, end_idx, style)
             self.SearchResultsTree.SetItemWindow(root, text_ctrl)
-            
+
         if wx.VERSION >= (2, 6, 0):
             item, root_cookie = self.SearchResultsTree.GetFirstChild(root)
         else:
@@ -317,7 +317,7 @@
                 item, root_cookie = self.SearchResultsTree.GetNextChild(root, root_cookie)
             self.GenerateSearchResultsTreeBranch(item, child)
             item, root_cookie = self.SearchResultsTree.GetNextChild(root, root_cookie)
-    
+
     def ShowSearchResults(self, item):
         data = self.SearchResultsTree.GetPyData(item)
         if isinstance(data, TupleType):
@@ -327,11 +327,11 @@
         self.ParentWindow.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
         for infos, start, end, text in search_results:
             self.ParentWindow.ShowSearchResult(infos, start, end)
-    
+
     def OnSearchResultsTreeItemActivated(self, event):
         self.ShowSearchResults(event.GetItem())
         event.Skip()
-    
+
     def OnResetButton(self, event):
         self.ResetSearchResults()
         self.ParentWindow.ClearSearchResults()
--- a/controls/VariablePanel.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/controls/VariablePanel.py	Mon Aug 14 19:13:01 2017 +0300
@@ -533,7 +533,7 @@
             self.ColFixedSizeFlag=[True,False,  True,   False,  True,   True,    False]
 
         self.PanelWidthMin = sum(self.ColSizes)
-        
+
         self.ElementType = element_type
         self.BodyType = None
 
@@ -643,7 +643,7 @@
         panel_width = window.Parent.ScreenRect.Width - 35
         if panel_width > self.PanelWidthMin:
             stretch_cols_width = panel_width
-            stretch_cols_sum = 0            
+            stretch_cols_sum = 0
             for col in range(len(self.ColFixedSizeFlag)):
                 if self.ColFixedSizeFlag[col]:
                     stretch_cols_width -= self.ColSizes[col]
@@ -759,7 +759,7 @@
         dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
         dialog.ShowModal()
         dialog.Destroy()
-            
+
     def OnVariablesGridCellChange(self, event):
         row, col = event.GetRow(), event.GetCol()
         colname = self.Table.GetColLabelValue(col, False)
@@ -793,7 +793,7 @@
 
         if message is not None:
             wx.CallAfter(self.ShowErrorMessage, message)
-            event.Veto()            
+            event.Veto()
         else:
             event.Skip()
 
--- a/dialogs/ActionBlockDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/ActionBlockDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -47,7 +47,7 @@
 #-------------------------------------------------------------------------------
 
 class ActionTable(CustomTable):
-    
+
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             colname = self.GetColLabelValue(col, False)
@@ -55,7 +55,7 @@
             if colname == "Type":
                 return _(value)
             return value
-    
+
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
             colname = self.GetColLabelValue(col, False)
@@ -64,7 +64,7 @@
             elif colname == "Qualifier" and not self.Parent.DurationList[value]:
                 self.data[row].duration = ""
             setattr(self.data[row], colname.lower(), value)
-        
+
     def _updateColAttrs(self, grid):
         """
         wx.Grid -> update the column attributes to add the
@@ -72,7 +72,7 @@
 
         Otherwise default to the default renderer.
         """
-        
+
         for row in range(self.GetNumberRows()):
             for col in range(self.GetNumberCols()):
                 editor = None
@@ -103,11 +103,11 @@
                 elif colname == "Indicator":
                     editor = wx.grid.GridCellChoiceEditor()
                     editor.SetParameters(self.Parent.VariableList)
-                    
+
                 grid.SetCellEditor(row, col, editor)
                 grid.SetCellRenderer(row, col, renderer)
                 grid.SetReadOnly(row, col, readonly)
-                
+
                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
             self.ResizeRow(grid, row)
 
@@ -116,56 +116,56 @@
 #-------------------------------------------------------------------------------
 
 class ActionBlockDialog(wx.Dialog):
-    
+
     def __init__(self, parent):
         wx.Dialog.__init__(self, parent, title=_('Edit action block properties'))
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         top_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
         top_sizer.AddGrowableCol(0)
         top_sizer.AddGrowableRow(0)
         main_sizer.AddSizer(top_sizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         actions_label = wx.StaticText(self, label=_('Actions:'))
         top_sizer.AddWindow(actions_label, flag=wx.ALIGN_BOTTOM)
-        
+
         for name, bitmap, help in [
                 ("AddButton", "add_element", _("Add action")),
                 ("DeleteButton", "remove_element", _("Remove action")),
                 ("UpButton", "up", _("Move action up")),
                 ("DownButton", "down", _("Move action down"))]:
-            button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), 
+            button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
                   size=wx.Size(28, 28), style=wx.NO_BORDER)
             button.SetToolTipString(help)
             setattr(self, name, button)
             top_sizer.AddWindow(button)
-        
+
         self.ActionsGrid = CustomGrid(self, size=wx.Size(-1, 250), style=wx.VSCROLL)
         self.ActionsGrid.DisableDragGridSize()
         self.ActionsGrid.EnableScrolling(False, True)
-        self.ActionsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
+        self.ActionsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
                               self.OnActionsGridCellChange)
         main_sizer.AddSizer(self.ActionsGrid, border=20,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
-        main_sizer.AddSizer(button_sizer, border=20, 
+        main_sizer.AddSizer(button_sizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.Table = ActionTable(self, [], GetActionTableColnames())
-        typelist = GetTypeList()       
+        typelist = GetTypeList()
         self.TypeList = ",".join(map(_,typelist))
         self.TranslateType = dict([(_(value), value) for value in typelist])
         self.ColSizes = [60, 90, 130, 200, 50]
         self.ColAlignements = [wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
-        
+
         self.ActionsGrid.SetTable(self.Table)
         self.ActionsGrid.SetDefaultValue(_ActionInfos("N", "Action", "", "", ""))
         self.ActionsGrid.SetButtons({"Add": self.AddButton,
@@ -173,19 +173,19 @@
                                      "Up": self.UpButton,
                                      "Down": self.DownButton})
         self.ActionsGrid.SetRowLabelSize(0)
-        
+
         for col in range(self.Table.GetNumberCols()):
             attr = wx.grid.GridCellAttr()
             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
             self.ActionsGrid.SetColAttr(col, attr)
             self.ActionsGrid.SetColMinimalWidth(col, self.ColSizes[col])
             self.ActionsGrid.AutoSizeColumn(col, False)
-        
+
         self.Table.ResetView(self.ActionsGrid)
         self.ActionsGrid.SetFocus()
         self.ActionsGrid.RefreshButtons()
         self.Fit()
-    
+
     def OnOK(self, event):
         self.ActionsGrid.CloseEditControl()
         self.EndModal(wx.ID_OK)
@@ -193,14 +193,14 @@
     def OnActionsGridCellChange(self, event):
         wx.CallAfter(self.Table.ResetView, self.ActionsGrid)
         event.Skip()
-    
+
     def SetQualifierList(self, list):
         self.QualifierList = ",".join(list)
         self.DurationList = list
 
     def SetVariableList(self, list):
         self.VariableList = "," + ",".join([variable.Name for variable in list])
-        
+
     def SetActionList(self, list):
         self.ActionList = "," + ",".join(list)
 
@@ -218,7 +218,7 @@
         if len(actions) > 0:
             self.ActionsGrid.SetGridCursor(0, 0)
         self.ActionsGrid.RefreshButtons()
-    
+
     def GetValues(self):
         actions = self.Table.GetData()
         for action in actions:
--- a/dialogs/ArrayTypeDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/ArrayTypeDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -39,56 +39,56 @@
 #-------------------------------------------------------------------------------
 
 class ArrayTypeDialog(wx.Dialog):
-    
+
     def __init__(self, parent, datatypes, infos):
         wx.Dialog.__init__(self, parent, title=_('Edit array type properties'))
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         top_sizer = wx.BoxSizer(wx.HORIZONTAL)
-        main_sizer.AddSizer(top_sizer, border=20, 
+        main_sizer.AddSizer(top_sizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         basetype_label = wx.StaticText(self, label=_('Base Type:'))
         top_sizer.AddWindow(basetype_label, 1, flag=wx.ALIGN_BOTTOM)
-        
+
         self.BaseType = wx.ComboBox(self, style=wx.CB_READONLY)
         top_sizer.AddWindow(self.BaseType, 1, flag=wx.GROW)
-        
-        self.Dimensions = CustomEditableListBox(self, label=_("Dimensions:"), 
+
+        self.Dimensions = CustomEditableListBox(self, label=_("Dimensions:"),
               style=wx.gizmos.EL_ALLOW_NEW|
                     wx.gizmos.EL_ALLOW_EDIT|
                     wx.gizmos.EL_ALLOW_DELETE)
-        for func in ["_OnLabelEndEdit", 
-                     "_OnAddButton", 
-                     "_OnDelButton", 
-                     "_OnUpButton", 
+        for func in ["_OnLabelEndEdit",
+                     "_OnAddButton",
+                     "_OnDelButton",
+                     "_OnUpButton",
                      "_OnDownButton"]:
             setattr(self.Dimensions, func, self.OnDimensionsChanged)
-        main_sizer.AddSizer(self.Dimensions, border=20, 
+        main_sizer.AddSizer(self.Dimensions, border=20,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
-        main_sizer.AddSizer(button_sizer, border=20, 
+        main_sizer.AddSizer(button_sizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         self.SetSizer(main_sizer)
-        
+
         for datatype in datatypes:
             self.BaseType.Append(datatype)
-        
+
         if isinstance(infos, TupleType) and infos[0] == "array":
             self.BaseType.SetStringSelection(infos[1])
             self.Dimensions.SetStrings(map(lambda x : "..".join(x), infos[2]))
         elif infos in datatypes:
             self.BaseType.SetStringSelection(infos)
-        
+
         self.BaseType.SetFocus()
         self.Fit()
-        
+
     def GetDimensions(self):
         message = None
         dimensions_list = []
@@ -113,14 +113,14 @@
             dlg.Destroy()
             return None
         return dimensions_list
-    
+
     def OnDimensionsChanged(self, event):
         wx.CallAfter(self.GetDimensions)
         event.Skip()
-    
+
     def OnOK(self, event):
         if self.GetDimensions() is not None:
             self.EndModal(wx.ID_OK)
-            
+
     def GetValue(self):
         return "array", self.BaseType.GetStringSelection(), self.GetDimensions()
--- a/dialogs/BlockPreviewDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/BlockPreviewDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -38,7 +38,7 @@
 """
 
 class BlockPreviewDialog(wx.Dialog):
-    
+
     def __init__(self, parent, controller, tagname, title):
         """
         Constructor
@@ -48,50 +48,50 @@
         @param title: Title of dialog frame
         """
         wx.Dialog.__init__(self, parent, title=title)
-        
+
         # Save reference to
         self.Controller = controller
         self.TagName = tagname
-        
+
         # Label for preview
         self.PreviewLabel = wx.StaticText(self, label=_('Preview:'))
-        
+
         # Create Preview panel
         self.Preview = wx.Panel(self, style=wx.SIMPLE_BORDER)
         self.Preview.SetBackgroundColour(wx.WHITE)
-        
+
         # Add function to preview panel so that it answers to graphic elements
         # like Viewer
         setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE)
         setattr(self.Preview, "GetScaling", lambda:None)
         setattr(self.Preview, "GetBlockType", controller.GetBlockType)
         setattr(self.Preview, "IsOfType", controller.IsOfType)
-        
+
         # Bind paint event on Preview panel
         self.Preview.Bind(wx.EVT_PAINT, self.OnPaint)
-        
+
         # Add default dialog buttons sizer
         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
-        self.Bind(wx.EVT_BUTTON, self.OnOK, 
+        self.Bind(wx.EVT_BUTTON, self.OnOK,
                   self.ButtonSizer.GetAffirmativeButton())
-        
+
         self.Element = None            # Graphic element to display in preview
         self.MinElementSize = None     # Graphic element minimal size
-        
+
         # Variable containing the graphic element name when dialog is opened
         self.DefaultElementName = None
         self.Fit()
-        
+
         # List of variables defined in POU {var_name: (var_class, var_type),...}
         self.VariableList = {}
-        
+
     def __del__(self):
         """
         Destructor
         """
         # Remove reference to project controller
         self.Controller = None
-    
+
     def _init_sizers(self, main_rows, main_growable_row,
                             left_rows, left_growable_row,
                             right_rows, right_growable_row):
@@ -108,44 +108,44 @@
         None if no row is growable
         """
         # Create dialog main sizer
-        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, 
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0,
                                           rows=main_rows, vgap=10)
         self.MainSizer.AddGrowableCol(0)
         if main_growable_row is not None:
             self.MainSizer.AddGrowableRow(main_growable_row)
-        
+
         # Create a sizer for dividing parameters in two columns
         self.ColumnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        self.MainSizer.AddSizer(self.ColumnSizer, border=20, 
+        self.MainSizer.AddSizer(self.ColumnSizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         # Create a sizer for left column
-        self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=0, 
+        self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=0,
                                               rows=left_rows, vgap=5)
         self.LeftGridSizer.AddGrowableCol(0)
         if left_growable_row is not None:
             self.LeftGridSizer.AddGrowableRow(left_growable_row)
-        self.ColumnSizer.AddSizer(self.LeftGridSizer, 1, border=5, 
+        self.ColumnSizer.AddSizer(self.LeftGridSizer, 1, border=5,
               flag=wx.GROW|wx.RIGHT|wx.EXPAND)
-        
+
         # Create a sizer for right column
-        self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=0, 
+        self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=0,
                                                rows=right_rows, vgap=0)
         self.RightGridSizer.AddGrowableCol(0)
         if right_growable_row is not None:
             self.RightGridSizer.AddGrowableRow(right_growable_row)
-        self.ColumnSizer.AddSizer(self.RightGridSizer, 1, border=5, 
+        self.ColumnSizer.AddSizer(self.RightGridSizer, 1, border=5,
               flag=wx.GROW|wx.LEFT)
-        
+
         self.SetSizer(self.MainSizer)
-    
+
     def SetMinElementSize(self, size):
         """
         Define minimal graphic element size
         @param size: Tuple containing minimal size (width, height)
         """
         self.MinElementSize = size
-    
+
     def GetMinElementSize(self):
         """
         Get minimal graphic element size
@@ -155,16 +155,16 @@
         """
         if self.Element is None:
             return None
-        
+
         return self.Element.GetMinSize()
-    
+
     def SetPreviewFont(self, font):
         """
         Set font of Preview panel
         @param font: wx.Font object containing font style
         """
         self.Preview.SetFont(font)
-    
+
     def RefreshVariableList(self):
         """
         Extract list of variables defined in POU
@@ -175,20 +175,20 @@
             for var in self.Controller.GetEditedElementInterfaceVars(
                                                         self.TagName)
             if var.Edit}
-        
-        # Add POU name to variable list if POU is a function 
+
+        # Add POU name to variable list if POU is a function
         returntype = self.Controller.GetEditedElementInterfaceReturnType(
                                                             self.TagName)
         if returntype is not None:
             self.VariableList[
                 self.Controller.GetEditedElementName(self.TagName)] = \
                  ("Output", returntype)
-        
+
         # Add POU name if POU is a transition
         words = self.TagName.split("::")
         if words[0] == "T":
             self.VariableList[words[2]] = ("Output", "BOOL")
-    
+
     def TestElementName(self, element_name):
         """
         Test displayed graphic element name
@@ -198,47 +198,47 @@
         message_format = None
         # Get graphic element name in upper case
         uppercase_element_name = element_name.upper()
-        
+
         # Test if graphic element name is a valid identifier
         if not TestIdentifier(element_name):
             message_format = _("\"%s\" is not a valid identifier!")
-        
+
         # Test that graphic element name isn't a keyword
         elif uppercase_element_name in IEC_KEYWORDS:
             message_format = _("\"%s\" is a keyword. It can't be used!")
-        
+
         # Test that graphic element name isn't a POU name
         elif uppercase_element_name in self.Controller.GetProjectPouNames():
             message_format = _("\"%s\" pou already exists!")
-        
+
         # Test that graphic element name isn't already used in POU by a variable
         # or another graphic element
-        elif ((self.DefaultElementName is None or 
-               self.DefaultElementName.upper() != uppercase_element_name) and 
+        elif ((self.DefaultElementName is None or
+               self.DefaultElementName.upper() != uppercase_element_name) and
               uppercase_element_name in self.Controller.\
                     GetEditedElementVariables(self.TagName)):
             message_format = _("\"%s\" element for this pou already exists!")
-        
+
         # If an error have been identify, show error message dialog
         if message_format is not None:
             self.ShowErrorMessage(message_format % element_name)
             # Test failed
             return False
-        
+
         # Test succeed
         return True
-    
+
     def ShowErrorMessage(self, message):
         """
         Show an error message dialog over this dialog
         @param message: Error message to display
         """
-        dialog = wx.MessageDialog(self, message, 
-                                  _("Error"), 
+        dialog = wx.MessageDialog(self, message,
+                                  _("Error"),
                                   wx.OK|wx.ICON_ERROR)
         dialog.ShowModal()
         dialog.Destroy()
-    
+
     def OnOK(self, event):
         """
         Called when dialog OK button is pressed
@@ -248,7 +248,7 @@
         """
         # Close dialog
         self.EndModal(wx.ID_OK)
-    
+
     def RefreshPreview(self):
         """
         Refresh preview panel of graphic element
@@ -258,42 +258,42 @@
         dc = wx.ClientDC(self.Preview)
         dc.SetFont(self.Preview.GetFont())
         dc.Clear()
-        
+
         # Return immediately if no graphic element defined
         if self.Element is None:
             return
-        
+
         # Calculate block size according to graphic element min size due to its
         # parameters and graphic element min size defined
         min_width, min_height = self.GetMinElementSize()
         width = max(self.MinElementSize[0], min_width)
         height = max(self.MinElementSize[1], min_height)
         self.Element.SetSize(width, height)
-        
+
         # Get element position and bounding box to center in preview
         posx, posy = self.Element.GetPosition()
         bbox = self.Element.GetBoundingBox()
-        
+
         # Get Preview panel size
         client_size = self.Preview.GetClientSize()
-        
+
         # If graphic element is too big to be displayed in preview panel,
         # calculate preview panel scale so that graphic element fit inside
-        scale = (max(float(bbox.width) / client_size.width, 
+        scale = (max(float(bbox.width) / client_size.width,
                      float(bbox.height) / client_size.height) * 1.1
-                 if bbox.width * 1.1 > client_size.width or 
+                 if bbox.width * 1.1 > client_size.width or
                     bbox.height * 1.1 > client_size.height
                  else 1.0)
         dc.SetUserScale(1.0 / scale, 1.0 / scale)
-        
+
         # Center graphic element in preview panel
         x = int(client_size.width * scale - bbox.width) / 2 + posx - bbox.x
         y = int(client_size.height * scale - bbox.height) / 2 + posy - bbox.y
         self.Element.SetPosition(x, y)
-        
+
         # Draw graphic element
         self.Element.Draw(dc)
-    
+
     def OnPaint(self, event):
         """
         Called when Preview panel need to be redraw
@@ -301,4 +301,3 @@
         """
         self.RefreshPreview()
         event.Skip()
-        
--- a/dialogs/BrowseLocationsDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/BrowseLocationsDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -37,16 +37,16 @@
 
 def GetDirFilterChoiceOptions():
     _ = lambda x : x
-    return [(_("All"), [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]), 
-            (_("Input"), [LOCATION_VAR_INPUT]), 
-            (_("Output"), [LOCATION_VAR_OUTPUT]), 
+    return [(_("All"), [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]),
+            (_("Input"), [LOCATION_VAR_INPUT]),
+            (_("Output"), [LOCATION_VAR_OUTPUT]),
             (_("Memory"), [LOCATION_VAR_MEMORY])]
 DIRFILTERCHOICE_OPTIONS = dict([(_(option), filter) for option, filter in GetDirFilterChoiceOptions()])
 
 def GetTypeFilterChoiceOptions():
     _ = lambda x : x
-    return [_("All"), 
-            _("Type and derivated"), 
+    return [_("All"),
+            _("Type and derivated"),
             _("Type strict")]
 
 # turn LOCATIONDATATYPES inside-out
@@ -60,81 +60,81 @@
 #-------------------------------------------------------------------------------
 
 class BrowseLocationsDialog(wx.Dialog):
-    
+
     def __init__(self, parent, var_type, controller):
         wx.Dialog.__init__(self, parent, title=_('Browse Locations'),
               style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(1)
-        
+
         locations_label = wx.StaticText(self, label=_('Locations available:'))
-        main_sizer.AddWindow(locations_label, border=20, 
+        main_sizer.AddWindow(locations_label, border=20,
               flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
-        
-        self.LocationsTree = wx.TreeCtrl(self, 
+
+        self.LocationsTree = wx.TreeCtrl(self,
               style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_HIDE_ROOT|wx.TR_LINES_AT_ROOT)
         self.LocationsTree.SetInitialSize(wx.Size(-1, 300))
-        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnLocationsTreeItemActivated, 
+        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnLocationsTreeItemActivated,
                   self.LocationsTree)
-        main_sizer.AddWindow(self.LocationsTree, border=20, 
+        main_sizer.AddWindow(self.LocationsTree, border=20,
               flag=wx.LEFT|wx.RIGHT|wx.GROW)
-        
+
         button_gridsizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
         button_gridsizer.AddGrowableCol(1)
         button_gridsizer.AddGrowableCol(3)
         button_gridsizer.AddGrowableRow(0)
-        main_sizer.AddSizer(button_gridsizer, border=20, 
+        main_sizer.AddSizer(button_gridsizer, border=20,
               flag=wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.GROW)
-        
+
         direction_label = wx.StaticText(self, label=_('Direction:'))
         button_gridsizer.AddWindow(direction_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         self.DirFilterChoice = wx.ComboBox(self, style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnFilterChoice, self.DirFilterChoice)
         button_gridsizer.AddWindow(self.DirFilterChoice,
               flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL)
-        
+
         filter_label = wx.StaticText(self, label=_('Type:'))
         button_gridsizer.AddWindow(filter_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         self.TypeFilterChoice = wx.ComboBox(self, style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnFilterChoice, self.TypeFilterChoice)
         button_gridsizer.AddWindow(self.TypeFilterChoice,
               flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
         button_gridsizer.AddSizer(button_sizer, flag=wx.ALIGN_RIGHT)
-        
+
         self.SetSizer(main_sizer)
-        
+
         self.Controller = controller
         self.VarType = var_type
         self.BaseVarType = self.Controller.GetBaseType(self.VarType)
         self.VarTypeSize = LOCATION_SIZES[self.BaseVarType]
         self.Locations = self.Controller.GetVariableLocationTree()
-        
+
         # Define Tree item icon list
         self.TreeImageList = wx.ImageList(16, 16)
         self.TreeImageDict = {}
-        
+
         # Icons for items
         for imgname, itemtype in [
-            ("CONFIGURATION", LOCATION_CONFNODE), 
-            ("RESOURCE",      LOCATION_MODULE), 
-            ("PROGRAM",       LOCATION_GROUP), 
-            ("VAR_INPUT",     LOCATION_VAR_INPUT), 
-            ("VAR_OUTPUT",    LOCATION_VAR_OUTPUT), 
+            ("CONFIGURATION", LOCATION_CONFNODE),
+            ("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(GetBitmap(imgname))
-        
+
         # Assign icon list to TreeCtrls
         self.LocationsTree.SetImageList(self.TreeImageList)
-        
+
         # Set a options for the choice
         for option, filter in GetDirFilterChoiceOptions():
             self.DirFilterChoice.Append(_(option))
@@ -143,34 +143,34 @@
             self.TypeFilterChoice.Append(_(option))
         self.TypeFilterChoice.SetStringSelection(_("All"))
         self.RefreshFilters()
-        
+
         self.RefreshLocationsTree()
         self.Fit()
-    
+
     def RefreshFilters(self):
         self.DirFilter = DIRFILTERCHOICE_OPTIONS[self.DirFilterChoice.GetStringSelection()]
         self.TypeFilter = self.TypeFilterChoice.GetSelection()
-    
+
     def RefreshLocationsTree(self):
         root = self.LocationsTree.GetRootItem()
         if not root.IsOk():
             root = self.LocationsTree.AddRoot("")
         self.GenerateLocationsTreeBranch(root, self.Locations)
-    
+
     def FilterType(self, location_type, location_size):
         if self.TypeFilter == 0:
             return True
-        
+
         if location_size != self.VarTypeSize:
             return False
-        
+
         if self.TypeFilter == 1:
             return self.Controller.IsOfType(location_type, self.BaseVarType)
         elif self.TypeFilter == 2:
             return location_type == self.VarType
-        
+
         return True
-    
+
     def GenerateLocationsTreeBranch(self, root, locations):
         to_delete = []
         item, root_cookie = self.LocationsTree.GetFirstChild(root)
@@ -194,21 +194,21 @@
             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_CONFNODE, LOCATION_MODULE, LOCATION_GROUP]:
             wx.CallAfter(self.EndModal, wx.ID_OK)
         event.Skip()
-    
+
     def OnFilterChoice(self, event):
         self.RefreshFilters()
         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
--- a/dialogs/BrowseValuesLibraryDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/BrowseValuesLibraryDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -29,7 +29,7 @@
 class BrowseValuesLibraryDialog(wx.Dialog):
     """
     Modal dialog that helps in selecting predefined XML attributes sets out of hierarchically organized list
-    """    
+    """
 
     def __init__(self, parent, name, library, default=None):
         wx.Dialog.__init__(self,
@@ -40,27 +40,27 @@
         self.staticText1 = wx.StaticText(
               label=_('Choose a value for %s:') % name, name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
+
         self.ValuesLibrary = wx.TreeCtrl(
               name='ValuesLibrary', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(400, 200), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_HIDE_ROOT|wx.TR_LINES_AT_ROOT)
-        
+
         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
 
         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
-        
+
         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
-        
+
         self.flexGridSizer1.AddWindow(self.staticText1, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
         self.flexGridSizer1.AddWindow(self.ValuesLibrary, 0, border=20, flag=wx.GROW|wx.LEFT|wx.RIGHT)
         self.flexGridSizer1.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-    
+
         self.flexGridSizer1.AddGrowableCol(0)
         self.flexGridSizer1.AddGrowableRow(1)
-        
+
         self.SetSizer(self.flexGridSizer1)
         self.Fit()
-        
+
         root = self.ValuesLibrary.AddRoot("")
         self.GenerateValuesLibraryBranch(root, library, default)
 
@@ -85,4 +85,3 @@
             message.Destroy()
         else:
             self.EndModal(wx.ID_OK)
-
--- a/dialogs/ConnectionDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/ConnectionDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -39,7 +39,7 @@
 """
 
 class ConnectionDialog(BlockPreviewDialog):
-    
+
     def __init__(self, parent, controller, tagname, apply_button=False):
         """
         Constructor
@@ -49,49 +49,49 @@
         @param apply_button: Enable button for applying connector modification
         to all connector having the same name in POU (default: False)
         """
-        BlockPreviewDialog.__init__(self, parent, controller, tagname, 
+        BlockPreviewDialog.__init__(self, parent, controller, tagname,
               title=_('Connection Properties'))
-        
+
         # Init common sizers
         self._init_sizers(2, 0, 7, 1, 0, None)
-        
+
         # Create label for connection type
         type_label = wx.StaticText(self, label=_('Type:'))
         self.LeftGridSizer.AddWindow(type_label, flag=wx.GROW)
-        
+
         # Create radio buttons for selecting connection type
         self.TypeRadioButtons = {}
         first = True
         for type, label in [(CONNECTOR, _('Connector')),
                             (CONTINUATION, _('Continuation'))]:
-            radio_button = wx.RadioButton(self, label=label, 
+            radio_button = wx.RadioButton(self, label=label,
                   style=(wx.RB_GROUP if first else 0))
             radio_button.SetValue(first)
             self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, radio_button)
             self.LeftGridSizer.AddWindow(radio_button, flag=wx.GROW)
             self.TypeRadioButtons[type] = radio_button
             first = False
-        
+
         # Create label for connection name
         name_label = wx.StaticText(self, label=_('Name:'))
         self.LeftGridSizer.AddWindow(name_label, flag=wx.GROW)
-        
+
         # Create text control for defining connection name
         self.ConnectionName = wx.TextCtrl(self)
         self.ConnectionName.SetMinSize(wx.Size(200,-1))
         self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.ConnectionName)
         self.LeftGridSizer.AddWindow(self.ConnectionName, flag=wx.GROW)
-        
+
         # Add preview panel and associated label to sizers
         self.Preview.SetMinSize(wx.Size(-1,100))
         self.LeftGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW)
         self.LeftGridSizer.AddWindow(self.Preview, flag=wx.GROW)
-        
+
         # Add buttons sizer to sizers
-        self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
+        self.MainSizer.AddSizer(self.ButtonSizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
         self.ColumnSizer.RemoveSizer(self.RightGridSizer)
-        
+
         # Add button for applying connection name modification to all connection
         # of POU
         if apply_button:
@@ -105,10 +105,10 @@
                 controller.GenerateNewName(
                         tagname, None, "Connection%d", 0))
         self.Fit()
-        
+
         # Connector radio button is default control having keyboard focus
         self.TypeRadioButtons[CONNECTOR].SetFocus()
-    
+
     def GetConnectionType(self):
         """
         Return type selected for connection
@@ -117,7 +117,7 @@
         return (CONNECTOR
                 if self.TypeRadioButtons[CONNECTOR].GetValue()
                 else CONTINUATION)
-    
+
     def SetValues(self, values):
         """
         Set default connection parameters
@@ -125,18 +125,18 @@
         """
         # For each parameters defined, set corresponding control value
         for name, value in values.items():
-            
+
             # Parameter is connection type
             if name == "type":
                 self.TypeRadioButtons[value].SetValue(True)
-            
+
             # Parameter is connection name
             elif name == "name":
                 self.ConnectionName.SetValue(value)
-        
+
         # Refresh preview panel
         self.RefreshPreview()
-    
+
     def GetValues(self):
         """
         Return connection parameters defined in dialog
@@ -154,23 +154,23 @@
         @return: True if connection name is valid
         """
         message = None
-        
+
         # Get connection name typed by user
         connection_name = self.ConnectionName.GetValue()
-        
+
         # Test that a name have been defined
         if connection_name == "":
             message = _("Form isn't complete. Name must be filled!")
-        
+
         # If an error have been identify, show error message dialog
         if message is not None:
             self.ShowErrorMessage(message)
             # Test failed
             return False
-        
+
         # Return result of element name test
         return self.TestElementName(connection_name)
-        
+
     def OnOK(self, event):
         """
         Called when dialog OK button is pressed
@@ -206,17 +206,16 @@
         """
         self.RefreshPreview()
         event.Skip()
-        
+
     def RefreshPreview(self):
         """
         Refresh preview panel of graphic element
         Override BlockPreviewDialog function
         """
         # Set graphic element displayed, creating a FBD connection element
-        self.Element = FBD_Connector(self.Preview, 
+        self.Element = FBD_Connector(self.Preview,
                 self.GetConnectionType(),
                 self.ConnectionName.GetValue())
-        
+
         # Call BlockPreviewDialog function
         BlockPreviewDialog.RefreshPreview(self)
-        
--- a/dialogs/DiscoveryDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/DiscoveryDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -38,56 +38,56 @@
         wx.ListCtrl.__init__(self, parent, id, pos, size, style, name=name)
         listmix.ListCtrlAutoWidthMixin.__init__(self)
 
-[ID_DISCOVERYDIALOG, ID_DISCOVERYDIALOGSTATICTEXT1, 
- ID_DISCOVERYDIALOGSERVICESLIST, ID_DISCOVERYDIALOGREFRESHBUTTON, 
- ID_DISCOVERYDIALOGLOCALBUTTON, ID_DISCOVERYDIALOGIPBUTTON, 
+[ID_DISCOVERYDIALOG, ID_DISCOVERYDIALOGSTATICTEXT1,
+ ID_DISCOVERYDIALOGSERVICESLIST, ID_DISCOVERYDIALOGREFRESHBUTTON,
+ ID_DISCOVERYDIALOGLOCALBUTTON, ID_DISCOVERYDIALOGIPBUTTON,
 ] = [wx.NewId() for _init_ctrls in range(6)]
 
 class DiscoveryDialog(wx.Dialog, listmix.ColumnSorterMixin):
-    
+
     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.ServicesList, 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.RefreshButton, 0, border=0, flag=0)
         parent.AddWindow(self.LocalButton, 0, border=0, flag=0)
         parent.AddWindow(self.IpButton, 0, border=0, flag=0)
         parent.AddSizer(self.ButtonSizer, 0, border=0, flag=0)
-        
+
     def _init_coll_ButtonGridSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
         parent.AddGrowableCol(1)
         parent.AddGrowableRow(0)
-    
+
     def _init_sizers(self):
         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
         self.ButtonGridSizer = wx.FlexGridSizer(cols=4, 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_DISCOVERYDIALOG, 
+        wx.Dialog.__init__(self, id=ID_DISCOVERYDIALOG,
               name='DiscoveryDialog', parent=prnt, style=wx.DEFAULT_DIALOG_STYLE,
               title=_('Service Discovery'))
-        
+
         self.staticText1 = wx.StaticText(id=ID_DISCOVERYDIALOGSTATICTEXT1,
               label=_('Services available:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
+
         # Set up list control
         self.ServicesList = AutoWidthListCtrl(id=ID_DISCOVERYDIALOGSERVICESLIST,
-              name='ServicesList', parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 0), 
+              name='ServicesList', parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 0),
               style=wx.LC_REPORT|wx.LC_EDIT_LABELS|wx.LC_SORT_ASCENDING|wx.LC_SINGLE_SEL)
         self.ServicesList.InsertColumn(0, _('NAME'))
         self.ServicesList.InsertColumn(1, _('TYPE'))
@@ -100,14 +100,14 @@
         self.ServicesList.SetInitialSize(wx.Size(-1, 300))
         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, id=ID_DISCOVERYDIALOGSERVICESLIST)
         self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, id=ID_DISCOVERYDIALOGSERVICESLIST)
-        
+
         listmix.ColumnSorterMixin.__init__(self, 4)
-        
+
         self.RefreshButton = wx.Button(id=ID_DISCOVERYDIALOGREFRESHBUTTON,
               label=_('Refresh'), name='RefreshButton', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, id=ID_DISCOVERYDIALOGREFRESHBUTTON)
-        
+
         self.LocalButton = wx.Button(id=ID_DISCOVERYDIALOGLOCALBUTTON,
               label=_('Local'), name='LocalButton', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
@@ -117,29 +117,29 @@
               label=_('Add IP'), name='IpButton', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         self.Bind(wx.EVT_BUTTON, self.OnIpButton, id=ID_DISCOVERYDIALOGIPBUTTON)
-        
+
         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTER)
-        
+
         self._init_sizers()
         self.Fit()
-        
+
     def __init__(self, parent):
         self._init_ctrls(parent)
-        
+
         self.itemDataMap = {}
         self.nextItemId = 0
-        
+
         self.URI = None
         self.Browser = None
-        
+
         self.ZeroConfInstance = Zeroconf()
         self.RefreshList()
         self.LatestSelection=None
-        
+
     def __del__(self):
         if self.Browser is not None : self.Browser.cancel()
         self.ZeroConfInstance.close()
-        
+
     def RefreshList(self):
         if self.Browser is not None : self.Browser.cancel()
         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
@@ -181,18 +181,18 @@
 #        connect_type = self.getColumnText(idx, 1)
 #        connect_address = self.getColumnText(idx, 2)
 #        connect_port = self.getColumnText(idx, 3)
-#        
+#
 #        self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
 
     def SetURI(self, idx):
         self.LatestSelection = idx
-        svcname = self.getColumnText(idx, 0) 
+        svcname = self.getColumnText(idx, 0)
         connect_type = self.getColumnText(idx, 1)
         self.URI = "%s://%s"%(connect_type, svcname + '.' + service_type)
-        
+
     def GetURI(self):
         return self.URI
-        
+
     def removeService(self, zeroconf, _type, name):
         wx.CallAfter(self._removeService, name)
 
@@ -201,7 +201,7 @@
         '''
         called when a service with the desired type goes offline.
         '''
-        
+
         # loop through the list items looking for the service that went offline
         for idx in xrange(self.ServicesList.GetItemCount()):
             # this is the unique identifier assigned to the item
@@ -213,7 +213,7 @@
             if item_name == name:
                 self.ServicesList.DeleteItem(idx)
                 break
-        
+
     def addService(self, zeroconf, _type, name):
         wx.CallAfter(self._addService, _type, name)
 
@@ -240,7 +240,7 @@
         # we assign every list item a unique id (that won't change when items
         # are added or removed)
         self.ServicesList.SetItemData(new_item, self.nextItemId)
- 
+
         # the value of each column has to be stored in the itemDataMap
         # so that ColumnSorterMixin knows how to sort the column.
 
@@ -249,4 +249,3 @@
         self.itemDataMap[self.nextItemId] = [ svcname, typename, ip, port, name ]
 
         self.nextItemId += 1
-        
--- a/dialogs/DurationEditorDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/DurationEditorDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -57,43 +57,43 @@
 
     def __init__(self, parent):
         wx.Dialog.__init__(self, parent, title=_('Edit Duration'))
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         controls_sizer = wx.FlexGridSizer(cols=len(CONTROLS), hgap=10, rows=2, vgap=10)
-        main_sizer.AddSizer(controls_sizer, border=20, 
+        main_sizer.AddSizer(controls_sizer, border=20,
               flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.GROW)
-        
+
         controls = []
         for i, (name, label) in enumerate(CONTROLS):
             controls_sizer.AddGrowableCol(i)
-            
+
             st = wx.StaticText(self, label=label)
             txtctrl = wx.TextCtrl(self, value='0', style=wx.TE_PROCESS_ENTER)
-            self.Bind(wx.EVT_TEXT_ENTER, 
-                      self.GetControlValueTestFunction(txtctrl), 
+            self.Bind(wx.EVT_TEXT_ENTER,
+                      self.GetControlValueTestFunction(txtctrl),
                       txtctrl)
             setattr(self, name, txtctrl)
-        
+
             controls.append((st, txtctrl))
-            
+
         for st, txtctrl in controls:
             controls_sizer.AddWindow(st, flag=wx.GROW)
-            
+
         for st, txtctrl in controls:
             controls_sizer.AddWindow(txtctrl, flag=wx.GROW)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
-        main_sizer.AddSizer(button_sizer, border=20, 
+        main_sizer.AddSizer(button_sizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         self.SetSizer(main_sizer)
         self.Fit()
         self.Days.SetFocus()
-        
+
     def SetDuration(self, value):
         result = IEC_TIME_MODEL.match(value.upper())
         if result is not None:
@@ -112,7 +112,7 @@
             else:
                 self.Milliseconds.SetValue("0")
                 self.Microseconds.SetValue("0")
-        
+
     def GetControlValueTestFunction(self, control):
         def OnValueChanged(event):
             try:
@@ -130,29 +130,29 @@
         for control, factor in [(self.Days, DAY), (self.Hours, HOUR),
                                 (self.Minutes, MINUTE), (self.Seconds, SECOND),
                                 (self.Milliseconds, MILLISECONDS), (self.Microseconds, MICROSECONDS)]:
-            
+
             milliseconds += float(control.GetValue()) * factor
-        
+
         not_null = False
         duration = "T#"
         for value, format in [(int(milliseconds) / DAY, "%dd"),
                             ((int(milliseconds) % DAY) / HOUR, "%dh"),
                             ((int(milliseconds) % HOUR) / MINUTE, "%dm"),
                             ((int(milliseconds) % MINUTE) / SECOND, "%ds")]:
-            
+
             if value > 0 or not_null:
                 duration += format % value
                 not_null = True
-        
+
         duration += "%gms" % (milliseconds % SECOND)
         return duration
-    
+
     def OnOK(self, event):
         self.OnCloseDialog()
 
     def OnCloseDialog(self):
         errors = []
-        for control, name in [(self.Days, _("days")), (self.Hours, _("hours")), 
+        for control, name in [(self.Days, _("days")), (self.Hours, _("hours")),
                               (self.Minutes, _("minutes")), (self.Seconds, _("seconds")),
                               (self.Milliseconds, _("milliseconds"))]:
             try:
--- a/dialogs/FBDBlockDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/FBDBlockDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -48,7 +48,7 @@
 """
 
 class FBDBlockDialog(BlockPreviewDialog):
-    
+
     def __init__(self, parent, controller, tagname):
         """
         Constructor
@@ -58,83 +58,83 @@
         """
         BlockPreviewDialog.__init__(self, parent, controller, tagname,
               title=_('Block Properties'))
-        
+
         # Init common sizers
         self._init_sizers(2, 0, 1, 0, 3, 2)
-        
+
         # Create static box around library panel
         type_staticbox = wx.StaticBox(self, label=_('Type:'))
         left_staticboxsizer = wx.StaticBoxSizer(type_staticbox, wx.VERTICAL)
         self.LeftGridSizer.AddSizer(left_staticboxsizer, border=5, flag=wx.GROW)
-        
+
         # Create Library panel and add it to static box
         self.LibraryPanel = LibraryPanel(self)
         self.LibraryPanel.SetInitialSize(wx.Size(-1, 400))
-        
+
         # Set function to call when selection in Library panel changed
-        setattr(self.LibraryPanel, "_OnTreeItemSelected", 
+        setattr(self.LibraryPanel, "_OnTreeItemSelected",
               self.OnLibraryTreeItemSelected)
-        left_staticboxsizer.AddWindow(self.LibraryPanel, 1, border=5, 
+        left_staticboxsizer.AddWindow(self.LibraryPanel, 1, border=5,
               flag=wx.GROW|wx.TOP)
-        
+
         # Create sizer for other block parameters
         top_right_gridsizer = wx.FlexGridSizer(cols=2, hgap=0, rows=4, vgap=5)
         top_right_gridsizer.AddGrowableCol(1)
         self.RightGridSizer.AddSizer(top_right_gridsizer, flag=wx.GROW)
-        
+
         # Create label for block name
         name_label = wx.StaticText(self, label=_('Name:'))
-        top_right_gridsizer.AddWindow(name_label, 
+        top_right_gridsizer.AddWindow(name_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         # Create text control for defining block name
         self.BlockName = wx.TextCtrl(self)
         self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.BlockName)
         top_right_gridsizer.AddWindow(self.BlockName, flag=wx.GROW)
-        
+
         # Create label for extended block input number
         inputs_label = wx.StaticText(self, label=_('Inputs:'))
-        top_right_gridsizer.AddWindow(inputs_label, 
+        top_right_gridsizer.AddWindow(inputs_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         # Create spin control for defining extended block input number
         self.Inputs = wx.SpinCtrl(self, min=2, max=20,
               style=wx.SP_ARROW_KEYS)
         self.Bind(wx.EVT_SPINCTRL, self.OnInputsChanged, self.Inputs)
         top_right_gridsizer.AddWindow(self.Inputs, flag=wx.GROW)
-        
+
         # Create label for block execution order
-        execution_order_label = wx.StaticText(self, 
+        execution_order_label = wx.StaticText(self,
               label=_('Execution Order:'))
-        top_right_gridsizer.AddWindow(execution_order_label, 
+        top_right_gridsizer.AddWindow(execution_order_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         # Create spin control for defining block execution order
         self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
-        self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, 
+        self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged,
                   self.ExecutionOrder)
         top_right_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW)
-                
+
         # Create label for block execution control
-        execution_control_label = wx.StaticText(self, 
+        execution_control_label = wx.StaticText(self,
               label=_('Execution Control:'))
-        top_right_gridsizer.AddWindow(execution_control_label, 
+        top_right_gridsizer.AddWindow(execution_control_label,
               flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         # Create check box to enable block execution control
         self.ExecutionControl = wx.CheckBox(self)
-        self.Bind(wx.EVT_CHECKBOX, self.OnExecutionOrderChanged, 
+        self.Bind(wx.EVT_CHECKBOX, self.OnExecutionOrderChanged,
                   self.ExecutionControl)
         top_right_gridsizer.AddWindow(self.ExecutionControl, flag=wx.GROW)
-        
+
         # Add preview panel and associated label to sizers
         self.RightGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW)
         self.RightGridSizer.AddWindow(self.Preview, flag=wx.GROW)
-        
+
         # Add buttons sizer to sizers
-        self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
+        self.MainSizer.AddSizer(self.ButtonSizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         # Dictionary containing correspondence between parameter exchanged and
         # control to fill with parameter value
         self.ParamsControl = {
@@ -142,20 +142,20 @@
             "executionOrder": self.ExecutionOrder,
             "executionControl": self.ExecutionControl
         }
-        
+
         # Init controls value and sensibility
         self.BlockName.SetValue("")
         self.BlockName.Enable(False)
         self.Inputs.Enable(False)
-        
+
         # Variable containing last name typed
         self.CurrentBlockName = None
-        
+
         # Refresh Library panel values
         self.LibraryPanel.SetBlockList(controller.GetBlockTypes(tagname))
         self.Fit()
         self.LibraryPanel.SetFocus()
-    
+
     def SetValues(self, values):
         """
         Set default block parameters
@@ -163,38 +163,38 @@
         """
         # Extract block type defined in parameters
         blocktype = values.get("type", None)
-        
-        # Select block type in library panel    
+
+        # Select block type in library panel
         if blocktype is not None:
-            self.LibraryPanel.SelectTreeItem(blocktype, 
+            self.LibraryPanel.SelectTreeItem(blocktype,
                                              values.get("inputs", None))
-        
+
         # Define regular expression for determine if block name is block
         # default name
         default_name_model = GetBlockTypeDefaultNameModel(blocktype)
-        
+
         # For each parameters defined, set corresponding control value
         for name, value in values.items():
-            
+
             # Parameter is block name
             if name == "name":
                 if value != "":
                     # Set default graphic element name for testing
                     self.DefaultElementName = value
-                    
+
                     # Test if block name is type default block name and save
                     # block name if not (name have been typed by user)
                     if default_name_model.match(value) is None:
                         self.CurrentBlockName = value
-            
+
                 self.BlockName.ChangeValue(value)
-            
+
             # Set value of other controls
             else:
                 control = self.ParamsControl.get(name, None)
                 if control is not None:
                     control.SetValue(value)
-        
+
         # Refresh preview panel
         self.RefreshPreview()
 
@@ -211,7 +211,7 @@
             name: control.GetValue()
             for name, control in self.ParamsControl.iteritems()})
         return values
-    
+
     def OnOK(self, event):
         """
         Called when dialog OK button is pressed
@@ -219,31 +219,31 @@
         @param event: wx.Event from OK button
         """
         message = None
-        
+
         # Get block type selected
         selected = self.LibraryPanel.GetSelectedBlock()
-        
+
         # Get block type name and if block is a function block
         block_name = self.BlockName.GetValue()
         name_enabled = self.BlockName.IsEnabled()
-        
+
         # Test that a type has been selected for block
         if selected is None:
             message = _("Form isn't complete. Valid block type must be selected!")
-        
+
         # Test, if block is a function block, that a name have been defined
         elif name_enabled and block_name == "":
             message = _("Form isn't complete. Name must be filled!")
-        
+
         # Show error message if an error is detected
         if message is not None:
             self.ShowErrorMessage(message)
-        
+
         # Test block name validity if necessary
         elif not name_enabled or self.TestElementName(block_name):
             # Call BlockPreviewDialog function
             BlockPreviewDialog.OnOK(self, event)
-    
+
     def OnLibraryTreeItemSelected(self, event):
         """
         Called when block type selected in library panel
@@ -251,12 +251,12 @@
         """
         # Get type selected in library panel
         values = self.LibraryPanel.GetSelectedBlock()
-        
+
         # Get block type informations
-        blocktype = (self.Controller.GetBlockType(values["type"], 
+        blocktype = (self.Controller.GetBlockType(values["type"],
                                                   values["inputs"])
                      if values is not None else None)
-        
+
         # Set input number spin control according to block type informations
         if blocktype is not None:
             self.Inputs.SetValue(len(blocktype["inputs"]))
@@ -264,12 +264,12 @@
         else:
             self.Inputs.SetValue(2)
             self.Inputs.Enable(False)
-        
+
         # Update block name with default value if block type is a function and
         # current block name wasn't typed by user
         if blocktype is not None and blocktype["type"] != "function":
             self.BlockName.Enable(True)
-            
+
             if self.CurrentBlockName is None:
                 # Generate new block name according to block type, taking
                 # default element name if it was already a default name for this
@@ -277,21 +277,21 @@
                 default_name_model = GetBlockTypeDefaultNameModel(values["type"])
                 block_name = (
                     self.DefaultElementName
-                    if (self.DefaultElementName is not None and 
+                    if (self.DefaultElementName is not None and
                         default_name_model.match(self.DefaultElementName))
                     else self.Controller.GenerateNewName(
                         self.TagName, None, values["type"]+"%d", 0))
             else:
                 block_name = self.CurrentBlockName
-                
+
             self.BlockName.ChangeValue(block_name)
         else:
             self.BlockName.Enable(False)
             self.BlockName.ChangeValue("")
-        
+
         # Refresh preview panel
         self.RefreshPreview()
-    
+
     def OnNameChanged(self, event):
         """
         Called when block name value changed
@@ -302,7 +302,7 @@
             self.CurrentBlockName = self.BlockName.GetValue()
             self.RefreshPreview()
         event.Skip()
-    
+
     def OnInputsChanged(self, event):
         """
         Called when block inputs number changed
@@ -311,7 +311,7 @@
         if self.Inputs.IsEnabled():
             self.RefreshPreview()
         event.Skip()
-    
+
     def OnExecutionOrderChanged(self, event):
         """
         Called when block execution order value changed
@@ -319,7 +319,7 @@
         """
         self.RefreshPreview()
         event.Skip()
-    
+
     def OnExecutionControlChanged(self, event):
         """
         Called when block execution control value changed
@@ -327,7 +327,7 @@
         """
         self.RefreshPreview()
         event.Skip()
-    
+
     def RefreshPreview(self):
         """
         Refresh preview panel of graphic element
@@ -335,22 +335,22 @@
         """
         # Get type selected in library panel
         values = self.LibraryPanel.GetSelectedBlock()
-        
+
         # If a block type is selected in library panel
         if values is not None:
             # Set graphic element displayed, creating a FBD block element
-            self.Element = FBD_Block(self.Preview, values["type"], 
+            self.Element = FBD_Block(self.Preview, values["type"],
                     (self.BlockName.GetValue()
                      if self.BlockName.IsEnabled()
-                     else ""), 
-                    extension = self.Inputs.GetValue(), 
-                    inputs = values["inputs"], 
-                    executionControl = self.ExecutionControl.GetValue(), 
+                     else ""),
+                    extension = self.Inputs.GetValue(),
+                    inputs = values["inputs"],
+                    executionControl = self.ExecutionControl.GetValue(),
                     executionOrder = self.ExecutionOrder.GetValue())
-        
+
         # Reset graphic element displayed
         else:
-            self.Element = None 
-        
+            self.Element = None
+
         # Call BlockPreviewDialog function
         BlockPreviewDialog.RefreshPreview(self)
--- a/dialogs/FBDVariableDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/FBDVariableDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -62,69 +62,69 @@
         """
         BlockPreviewDialog.__init__(self, parent, controller, tagname,
               title=_('Variable Properties'))
-        
+
         # Init common sizers
         self._init_sizers(4, 2, 4, None, 3, 2)
-        
+
         # Create label for variable class
         class_label = wx.StaticText(self, label=_('Class:'))
         self.LeftGridSizer.AddWindow(class_label, flag=wx.GROW)
-        
+
         # Create a combo box for defining variable class
         self.Class = wx.ComboBox(self, style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnClassChanged, self.Class)
         self.LeftGridSizer.AddWindow(self.Class, flag=wx.GROW)
-        
+
         # Create label for variable execution order
-        execution_order_label = wx.StaticText(self, 
+        execution_order_label = wx.StaticText(self,
               label=_('Execution Order:'))
         self.LeftGridSizer.AddWindow(execution_order_label, flag=wx.GROW)
-        
+
         # Create spin control for defining variable execution order
         self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
-        self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, 
+        self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged,
                   self.ExecutionOrder)
         self.LeftGridSizer.AddWindow(self.ExecutionOrder, flag=wx.GROW)
-        
+
         # Create label for variable expression
         name_label = wx.StaticText(self, label=_('Expression:'))
-        self.RightGridSizer.AddWindow(name_label, border=5, 
+        self.RightGridSizer.AddWindow(name_label, border=5,
               flag=wx.GROW|wx.BOTTOM)
-        
+
         # Create text control for defining variable expression
         self.Expression = wx.TextCtrl(self)
         self.Bind(wx.EVT_TEXT, self.OnExpressionChanged, self.Expression)
         self.RightGridSizer.AddWindow(self.Expression, flag=wx.GROW)
-        
+
         # Create a list box to selected variable expression in the list of
         # variables defined in POU
         self.VariableName = wx.ListBox(self, size=wx.Size(-1,120),
               style=wx.LB_SINGLE|wx.LB_SORT)
         self.Bind(wx.EVT_LISTBOX, self.OnNameChanged, self.VariableName)
         self.RightGridSizer.AddWindow(self.VariableName, border=4, flag=wx.GROW|wx.TOP)
-        
+
         # Add preview panel and associated label to sizers
         self.MainSizer.AddWindow(self.PreviewLabel, border=20,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
         self.MainSizer.AddWindow(self.Preview, border=20,
               flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        
+
         # Add buttons sizer to sizers
-        self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
+        self.MainSizer.AddSizer(self.ButtonSizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         # Set options that can be selected in class combo box
         for var_class, choice in VARIABLE_CLASSES_DICT.iteritems():
             if not exclude_input or var_class != INPUT:
                 self.Class.Append(choice)
         self.Class.SetSelection(0)
-        
+
         # Extract list of variables defined in POU
         self.RefreshVariableList()
-        
+
         # Refresh values in name list box
         self.RefreshNameList()
-        
+
         self.Preview.SetInitialSize(wx.Size(-1, 60))
         self.Fit()
 
@@ -138,32 +138,32 @@
         # Get variable class to select POU variable applicable
         var_class = VARIABLE_CLASSES_DICT_REVERSE[
                             self.Class.GetStringSelection()]
-        
+
         # Refresh names in name list box by selecting variables in POU variables
         # list that can be applied to variable class
         self.VariableName.Clear()
         for name, (var_type, value_type) in self.VariableList.iteritems():
             if var_type != "Input" or var_class == INPUT:
                 self.VariableName.Append(name)
-        
+
         # Get variable expression and select corresponding value in name list
         # box if it exists
         selected = self.Expression.GetValue()
-        if (selected != "" and 
+        if (selected != "" and
             self.VariableName.FindString(selected) != wx.NOT_FOUND):
             self.VariableName.SetStringSelection(selected)
         else:
             self.VariableName.SetSelection(wx.NOT_FOUND)
-        
+
         # Disable name list box if no name present inside
         self.VariableName.Enable(self.VariableName.GetCount() > 0)
-            
+
     def SetValues(self, values):
         """
         Set default variable parameters
         @param values: Variable parameters values
         """
-        
+
         # Get class parameter value
         var_class = values.get("class", None)
         if var_class is not None:
@@ -171,10 +171,10 @@
             self.Class.SetStringSelection(VARIABLE_CLASSES_DICT[var_class])
             # Refresh names in name list box according to var class
             self.RefreshNameList()
-        
+
         # For each parameters defined, set corresponding control value
         for name, value in values.items():
-            
+
             # Parameter is variable expression
             if name == "expression":
                 # Set expression text control value
@@ -184,15 +184,15 @@
                     self.VariableName.SetStringSelection(value)
                 else:
                     self.VariableName.SetSelection(wx.NOT_FOUND)
-            
+
             # Parameter is variable execution order
             elif name == "executionOrder":
                 self.ExecutionOrder.SetValue(value)
-        
+
         # Refresh preview panel
         self.RefreshPreview()
         self.Fit()
-        
+
     def GetValues(self):
         """
         Return block parameters defined in dialog
@@ -215,16 +215,16 @@
         @param event: wx.Event from OK button
         """
         message = None
-        
+
         # Test that an expression have been selected or typed by user
         value = self.Expression.GetValue()
         if value == "":
             message = _("At least a variable or an expression must be selected!")
-        
+
         # Show error message if an error is detected
         if message is not None:
             self.ShowErrorMessage(message)
-        
+
         else:
             # Call BlockPreviewDialog function
             BlockPreviewDialog.OnOK(self, event)
@@ -236,7 +236,7 @@
         """
         # Refresh name list box values
         self.RefreshNameList()
-        
+
         self.RefreshPreview()
         event.Skip()
 
@@ -249,10 +249,10 @@
         # list box if value selected is valid
         if self.VariableName.GetSelection() != wx.NOT_FOUND:
             self.Expression.ChangeValue(self.VariableName.GetStringSelection())
-        
-        self.RefreshPreview()
-        event.Skip()
-    
+
+        self.RefreshPreview()
+        event.Skip()
+
     def OnExpressionChanged(self, event):
         """
         Called when expression text control is changed by user
@@ -261,10 +261,10 @@
         # Select the corresponding value in name list box if it exists
         self.VariableName.SetSelection(
             self.VariableName.FindString(self.Expression.GetValue()))
-        
-        self.RefreshPreview()
-        event.Skip()
-    
+
+        self.RefreshPreview()
+        event.Skip()
+
     def OnExecutionOrderChanged(self, event):
         """
         Called when block execution control value changed
@@ -272,7 +272,7 @@
         """
         self.RefreshPreview()
         event.Skip()
-    
+
     def RefreshPreview(self):
         """
         Refresh preview panel of graphic element
@@ -280,16 +280,14 @@
         """
         # Get expression value to put in FBD variable element
         name = self.Expression.GetValue()
-        
+
         # Set graphic element displayed, creating a FBD variable element
-        self.Element = FBD_Variable(self.Preview, 
+        self.Element = FBD_Variable(self.Preview,
                     VARIABLE_CLASSES_DICT_REVERSE[
-                        self.Class.GetStringSelection()], 
-                    name, 
-                    self.VariableList.get(name, ("", ""))[1], 
+                        self.Class.GetStringSelection()],
+                    name,
+                    self.VariableList.get(name, ("", ""))[1],
                     executionOrder = self.ExecutionOrder.GetValue())
-        
+
         # Call BlockPreviewDialog function
         BlockPreviewDialog.RefreshPreview(self)
-        
-        
--- a/dialogs/FindInPouDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/FindInPouDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -32,80 +32,80 @@
         if parent and parent.icon:
                 self.SetIcon(parent.icon)
 
-    
+
     def __init__(self, parent):
-        wx.Dialog.__init__(self, parent, title=_("Find"),         
+        wx.Dialog.__init__(self, parent, title=_("Find"),
               style=wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN|wx.RESIZE_BORDER)
-        
+
         self._init_icon(parent)
         panel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=2, vgap=5)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         controls_sizer = wx.BoxSizer(wx.VERTICAL)
-        main_sizer.AddSizer(controls_sizer, border=20, 
+        main_sizer.AddSizer(controls_sizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         patterns_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=5)
         patterns_sizer.AddGrowableCol(1)
         controls_sizer.AddSizer(patterns_sizer, border=5, flag=wx.GROW|wx.BOTTOM)
-        
+
         find_label = wx.StaticText(panel, label=_("Find:"))
         patterns_sizer.AddWindow(find_label, flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         self.FindPattern = wx.TextCtrl(panel)
         self.Bind(wx.EVT_TEXT, self.OnFindPatternChanged, self.FindPattern)
         self.Bind(wx.EVT_CHAR_HOOK, self.OnEscapeKey)
         patterns_sizer.AddWindow(self.FindPattern, flag=wx.GROW)
-        
+
         params_sizer = wx.BoxSizer(wx.HORIZONTAL)
         controls_sizer.AddSizer(params_sizer, border=5, flag=wx.GROW|wx.BOTTOM)
-        
+
         direction_staticbox = wx.StaticBox(panel, label=_("Direction"))
         direction_staticboxsizer = wx.StaticBoxSizer(
               direction_staticbox, wx.VERTICAL)
-        params_sizer.AddSizer(direction_staticboxsizer, 1, border=5, 
+        params_sizer.AddSizer(direction_staticboxsizer, 1, border=5,
               flag=wx.GROW|wx.RIGHT)
-        
-        self.Forward = wx.RadioButton(panel, label=_("Forward"), 
+
+        self.Forward = wx.RadioButton(panel, label=_("Forward"),
               style=wx.RB_GROUP)
-        direction_staticboxsizer.AddWindow(self.Forward, border=5, 
+        direction_staticboxsizer.AddWindow(self.Forward, border=5,
               flag=wx.ALL|wx.GROW)
-        
+
         self.Backward = wx.RadioButton(panel, label=_("Backward"))
-        direction_staticboxsizer.AddWindow(self.Backward, border=5, 
+        direction_staticboxsizer.AddWindow(self.Backward, border=5,
               flag=wx.ALL|wx.GROW)
-        
+
         options_staticbox = wx.StaticBox(panel, label=_("Options"))
         options_staticboxsizer = wx.StaticBoxSizer(
               options_staticbox, wx.VERTICAL)
         params_sizer.AddSizer(options_staticboxsizer, 1, flag=wx.GROW)
-        
+
         self.CaseSensitive = wx.CheckBox(panel, label=_("Case sensitive"))
         self.CaseSensitive.SetValue(True)
-        options_staticboxsizer.AddWindow(self.CaseSensitive, border=5, 
+        options_staticboxsizer.AddWindow(self.CaseSensitive, border=5,
               flag=wx.ALL|wx.GROW)
-        
+
         self.WrapSearch = wx.CheckBox(panel, label=_("Wrap search"))
         self.WrapSearch.SetValue(True)
-        options_staticboxsizer.AddWindow(self.WrapSearch, border=5, 
+        options_staticboxsizer.AddWindow(self.WrapSearch, border=5,
               flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
-        
+
         self.RegularExpressions = wx.CheckBox(panel, label=_("Regular expressions"))
-        options_staticboxsizer.AddWindow(self.RegularExpressions, border=5, 
+        options_staticboxsizer.AddWindow(self.RegularExpressions, border=5,
               flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.GROW)
-        
+
         buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
-        main_sizer.AddSizer(buttons_sizer, border=20, 
+        main_sizer.AddSizer(buttons_sizer, border=20,
               flag=wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_RIGHT)
-        
+
         self.FindButton = wx.Button(panel, label=_("Find"))
         self.FindButton.SetDefault()
         self.Bind(wx.EVT_BUTTON, self.OnFindButton, self.FindButton)
         buttons_sizer.AddWindow(self.FindButton, border=5, flag=wx.RIGHT)
-        
+
         self.CloseButton = wx.Button(panel, label=_("Close"))
         self.Bind(wx.EVT_BUTTON, self.OnCloseButton, self.CloseButton)
         buttons_sizer.AddWindow(self.CloseButton)
@@ -115,30 +115,30 @@
         self.RegExpSyntaxErrMsg = _("Syntax error in regular expression of pattern to search!")
         self.StatusLabel = wx.StaticText(panel, label= self.RegExpSyntaxErrMsg)
         controls_sizer.AddWindow(self.StatusLabel, flag=wx.ALIGN_CENTER_VERTICAL)
-        
+
         panel.SetSizer(main_sizer)
         main_sizer.Fit(self)
 
         # clear message after dialog size calculation
         self.SetStatusText("")
 
-        
+
         self.ParentWindow = parent
-        
+
         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
         self.infosPrev = {}
         self.criteria = {}
         self.FindPattern.SetFocus()
         self.RefreshButtonsState()
-    
+
     def RefreshButtonsState(self):
         find_pattern = self.FindPattern.GetValue()
         self.FindButton.Enable(find_pattern != "")
-    
+
     def OnCloseFrame(self, event):
         self.Hide()
         event.Veto()
-        
+
     def OnCloseButton(self, event):
         self.Hide()
         event.Skip()
@@ -157,7 +157,7 @@
     def SetStatusText(self, msg):
         self.StatusLabel.SetLabel(msg)
         self.Layout()
-        
+
     def OnFindButton(self, event):
         infos = {
             "find_pattern": self.FindPattern.GetValue(),
--- a/dialogs/ForceVariableDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/ForceVariableDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -34,7 +34,7 @@
                      "B" : ["SINT", "USINT", "BYTE", "STRING"],
                      "W" : ["INT", "UINT", "WORD", "WSTRING"],
                      "D" : ["DINT", "UDINT", "REAL", "DWORD"],
-                     "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} 
+                     "L" : ["LINT", "ULINT", "LREAL", "LWORD"]}
 
 def gen_get_function(f):
     def get_function(v):
@@ -68,7 +68,7 @@
 IEC_DATETIME_MODEL = re.compile("(?:(?:DT|DATE_AND_TIME)#)?([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
 IEC_TIMEOFDAY_MODEL = re.compile("(?:(?:TOD|TIME_OF_DAY)#)?([0-9]{2}):([0-9]{2}):([0-9]{2}(?:\.[0-9]+)?)$")
 
-def gettime(v):    
+def gettime(v):
     result = IEC_TIME_MODEL.match(v.upper())
     if result is not None:
         negative, days, hours, minutes, seconds, milliseconds = result.groups()
@@ -87,8 +87,8 @@
         if negative is not None:
             microseconds = -microseconds
         return datetime.timedelta(microseconds=microseconds)
-    
-    else: 
+
+    else:
         return None
 
 def getdate(v):
@@ -101,7 +101,7 @@
             return None
         base_date = datetime.datetime(1970, 1, 1)
         return date - base_date
-    else: 
+    else:
         return None
 
 def getdatetime(v):
@@ -114,7 +114,7 @@
             return None
         base_date = datetime.datetime(1970, 1, 1)
         return date - base_date
-    else: 
+    else:
         return None
 
 def gettimeofday(v):
@@ -159,13 +159,13 @@
 class ForceVariableDialog(wx.TextEntryDialog):
 
     def __init__(self, parent, iec_type, defaultValue=""):
-        wx.TextEntryDialog.__init__(self, parent, message = _("Forcing Variable Value"), 
-                caption = _("Please enter value for a \"%s\" variable:") % iec_type, defaultValue = defaultValue, 
+        wx.TextEntryDialog.__init__(self, parent, message = _("Forcing Variable Value"),
+                caption = _("Please enter value for a \"%s\" variable:") % iec_type, defaultValue = defaultValue,
                 style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition)
-        
-        self.IEC_Type = iec_type 
-        
-        self.Bind(wx.EVT_BUTTON, self.OnOK, 
+
+        self.IEC_Type = iec_type
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK,
               self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton())
         self.ValueTextCtrl=self.GetSizer().GetItem(1).GetWindow()
         if self.IEC_Type == "BOOL":
--- a/dialogs/LDElementDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/LDElementDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -41,7 +41,7 @@
 """
 
 class LDElementDialog(BlockPreviewDialog):
-    
+
     def __init__(self, parent, controller, tagname, type):
         """
         Constructor
@@ -50,24 +50,24 @@
         @param tagname: Tagname of project POU edited
         @param type: Type of LD element ('contact or 'coil')
         """
-        BlockPreviewDialog.__init__(self, parent, controller, tagname, 
+        BlockPreviewDialog.__init__(self, parent, controller, tagname,
               title=(_("Edit Contact Values")
                      if type == "contact"
                      else _("Edit Coil Values")))
-        
+
         # Init common sizers
-        self._init_sizers(2, 0, 
+        self._init_sizers(2, 0,
               (7 if type == "contact" else 9), None, 2, 1)
-        
+
         # Create label for LD element modifier
         modifier_label = wx.StaticText(self, label=_('Modifier:'))
-        self.LeftGridSizer.AddWindow(modifier_label, border=5, 
+        self.LeftGridSizer.AddWindow(modifier_label, border=5,
               flag=wx.GROW|wx.BOTTOM)
-        
+
         # Create radio buttons for selecting LD element modifier
         self.ModifierRadioButtons = {}
         first = True
-        element_modifiers = ([CONTACT_NORMAL, CONTACT_REVERSE, 
+        element_modifiers = ([CONTACT_NORMAL, CONTACT_REVERSE,
                               CONTACT_RISING, CONTACT_FALLING]
                              if type == "contact"
                              else [COIL_NORMAL, COIL_REVERSE, COIL_SET,
@@ -75,55 +75,55 @@
         modifiers_label = [_("Normal"), _("Negated")] + \
                           ([_("Set"), _("Reset")] if type == "coil" else []) + \
                           [_("Rising Edge"), _("Falling Edge")]
-        
+
         for modifier, label in zip(element_modifiers, modifiers_label):
-            radio_button = wx.RadioButton(self, label=label, 
+            radio_button = wx.RadioButton(self, label=label,
                   style=(wx.RB_GROUP if first else 0))
             radio_button.SetValue(first)
             self.Bind(wx.EVT_RADIOBUTTON, self.OnModifierChanged, radio_button)
             self.LeftGridSizer.AddWindow(radio_button, flag=wx.GROW)
             self.ModifierRadioButtons[modifier] = radio_button
             first = False
-        
+
         # Create label for LD element variable
         element_variable_label = wx.StaticText(self, label=_('Variable:'))
         self.LeftGridSizer.AddWindow(element_variable_label, border=5,
               flag=wx.GROW|wx.TOP)
-        
+
         # Create a combo box for defining LD element variable
         self.ElementVariable = wx.ComboBox(self, style=wx.CB_SORT)
-        self.Bind(wx.EVT_COMBOBOX, self.OnVariableChanged, 
+        self.Bind(wx.EVT_COMBOBOX, self.OnVariableChanged,
                   self.ElementVariable)
-        self.Bind(wx.EVT_TEXT, self.OnVariableChanged, 
-                  self.ElementVariable)        
+        self.Bind(wx.EVT_TEXT, self.OnVariableChanged,
+                  self.ElementVariable)
         self.LeftGridSizer.AddWindow(self.ElementVariable, border=5,
              flag=wx.GROW|wx.TOP)
-        
+
         # Add preview panel and associated label to sizers
         self.RightGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW)
         self.RightGridSizer.AddWindow(self.Preview, flag=wx.GROW)
-        
+
         # Add buttons sizer to sizers
-        self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
+        self.MainSizer.AddSizer(self.ButtonSizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
+
         # Save LD element class
         self.ElementClass = (LD_Contact if type == "contact" else LD_Coil)
-        
+
         # Extract list of variables defined in POU
         self.RefreshVariableList()
-        
+
         # Set values in ElementVariable
         for name, (var_type, value_type) in self.VariableList.iteritems():
             # Only select BOOL variable and avoid input for coil
             if (type == "contact" or var_type != "Input") and \
                value_type == "BOOL":
                 self.ElementVariable.Append(name)
-        
+
         self.Fit()
         # Normal radio button is default control having keyboard focus
         self.ModifierRadioButtons[element_modifiers[0]].SetFocus()
-    
+
     def GetElementModifier(self):
         """
         Return modifier selected for LD element
@@ -143,15 +143,15 @@
         """
         # For each parameters defined, set corresponding control value
         for name, value in values.items():
-            
+
             # Parameter is LD element variable
             if name == "variable":
                 self.ElementVariable.SetValue(value)
-            
+
             # Set value of other controls
             elif name == "modifier":
                 self.ModifierRadioButtons[value].SetValue(True)
-        
+
         # Refresh preview panel
         self.RefreshPreview()
 
@@ -188,20 +188,19 @@
         Override BlockPreviewDialog function
         """
         value = self.ElementVariable.GetValue()
-        
+
         # Set graphic element displayed, creating a LD element
         self.Element = self.ElementClass(
-                self.Preview, 
+                self.Preview,
                 self.GetElementModifier(),
                 value)
 
         button = self.ButtonSizer.GetAffirmativeButton()
         button.Enable(value != "")
-        
+
         # Call BlockPreviewDialog function
         BlockPreviewDialog.RefreshPreview(self)
-        
+
     def OnOK(self, event):
         if self.ElementVariable.GetValue() != "":
             self.EndModal(wx.ID_OK)
-
--- a/dialogs/LDPowerRailDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/LDPowerRailDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -39,7 +39,7 @@
 """
 
 class LDPowerRailDialog(BlockPreviewDialog):
-    
+
     def __init__(self, parent, controller, tagname):
         """
         Constructor
@@ -49,50 +49,50 @@
         """
         BlockPreviewDialog.__init__(self, parent, controller, tagname,
               title=_('Power Rail Properties'))
-        
+
         # Init common sizers
         self._init_sizers(2, 0, 5, None, 2, 1)
-        
+
         # Create label for connection type
         type_label = wx.StaticText(self, label=_('Type:'))
         self.LeftGridSizer.AddWindow(type_label, flag=wx.GROW)
-        
+
         # Create radio buttons for selecting power rail type
         self.TypeRadioButtons = {}
         first = True
         for type, label in [(LEFTRAIL, _('Left PowerRail')),
                             (RIGHTRAIL, _('Right PowerRail'))]:
-            radio_button = wx.RadioButton(self, label=label, 
+            radio_button = wx.RadioButton(self, label=label,
                   style=(wx.RB_GROUP if first else 0))
             radio_button.SetValue(first)
             self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, radio_button)
             self.LeftGridSizer.AddWindow(radio_button, flag=wx.GROW)
             self.TypeRadioButtons[type] = radio_button
             first = False
-        
+
         # Create label for power rail pin number
         pin_number_label = wx.StaticText(self, label=_('Pin number:'))
         self.LeftGridSizer.AddWindow(pin_number_label, flag=wx.GROW)
-        
+
         # Create spin control for defining power rail pin number
         self.PinNumber = wx.SpinCtrl(self, min=1, max=50,
               style=wx.SP_ARROW_KEYS)
         self.PinNumber.SetValue(1)
         self.Bind(wx.EVT_SPINCTRL, self.OnPinNumberChanged, self.PinNumber)
         self.LeftGridSizer.AddWindow(self.PinNumber, flag=wx.GROW)
-        
+
         # Add preview panel and associated label to sizers
         self.RightGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW)
         self.RightGridSizer.AddWindow(self.Preview, flag=wx.GROW)
-        
+
         # Add buttons sizer to sizers
-        self.MainSizer.AddSizer(self.ButtonSizer, border=20, 
+        self.MainSizer.AddSizer(self.ButtonSizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
         self.Fit()
-        
+
         # Left Power Rail radio button is default control having keyboard focus
         self.TypeRadioButtons[LEFTRAIL].SetFocus()
-    
+
     def GetMinElementSize(self):
         """
         Get minimal graphic element size
@@ -100,7 +100,7 @@
         element defined
         """
         return self.Element.GetMinSize(True)
-    
+
     def GetPowerRailType(self):
         """
         Return type selected for power rail
@@ -109,7 +109,7 @@
         return (LEFTRAIL
                 if self.TypeRadioButtons[LEFTRAIL].GetValue()
                 else RIGHTRAIL)
-    
+
     def SetValues(self, values):
         """
         Set default power rail parameters
@@ -117,11 +117,11 @@
         """
         # For each parameters defined, set corresponding control value
         for name, value in values.items():
-            
+
             # Parameter is power rail type
             if name == "type":
                 self.TypeRadioButtons[value].SetValue(True)
-            
+
             # Parameter is power rail pin number
             elif name == "pin_number":
                 self.PinNumber.SetValue(value)
@@ -158,11 +158,11 @@
         Refresh preview panel of graphic element
         Override BlockPreviewDialog function
         """
-        
+
         # Set graphic element displayed, creating a power rail element
-        self.Element = LD_PowerRail(self.Preview, 
-                self.GetPowerRailType(), 
+        self.Element = LD_PowerRail(self.Preview,
+                self.GetPowerRailType(),
                 connectors = self.PinNumber.GetValue())
-        
+
         # Call BlockPreviewDialog function
         BlockPreviewDialog.RefreshPreview(self)
--- a/dialogs/PouActionDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/PouActionDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -33,48 +33,48 @@
 ACTION_LANGUAGES_DICT = dict([(_(language), language) for language in GetActionLanguages()])
 
 class PouActionDialog(wx.Dialog):
-    
+
     def __init__(self, parent):
         wx.Dialog.__init__(self, parent, title=_('Create a new action'))
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         infos_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=3, vgap=15)
         infos_sizer.AddGrowableCol(1)
-        main_sizer.AddSizer(infos_sizer, border=20, 
+        main_sizer.AddSizer(infos_sizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         actionname_label = wx.StaticText(self, label=_('Action Name:'))
-        infos_sizer.AddWindow(actionname_label, border=4, 
+        infos_sizer.AddWindow(actionname_label, border=4,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP)
-        
+
         self.ActionName = wx.TextCtrl(self, size=wx.Size(180,-1))
         infos_sizer.AddWindow(self.ActionName, flag=wx.GROW)
-        
+
         language_label = wx.StaticText(self, label=_('Language:'))
-        infos_sizer.AddWindow(language_label, border=4, 
+        infos_sizer.AddWindow(language_label, border=4,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP)
-        
+
         self.Language = wx.ComboBox(self, style=wx.CB_READONLY)
         infos_sizer.AddWindow(self.Language, flag=wx.GROW)
-        
+
         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
-        self.Bind(wx.EVT_BUTTON, self.OnOK, 
+        self.Bind(wx.EVT_BUTTON, self.OnOK,
               button_sizer.GetAffirmativeButton())
-        main_sizer.AddSizer(button_sizer, border=20, 
+        main_sizer.AddSizer(button_sizer, border=20,
               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-            
+
         self.SetSizer(main_sizer)
-        
+
         for option in GetActionLanguages():
             self.Language.Append(_(option))
-        
+
         self.Fit()
         self.PouNames = []
         self.PouElementNames = []
-    
+
     def OnOK(self, event):
         error = []
         action_name = self.ActionName.GetValue()
@@ -91,7 +91,7 @@
                 elif i == len(error) - 1:
                     text += _(" and %s")%item
                 else:
-                    text += _(", %s")%item 
+                    text += _(", %s")%item
             message = _("Form isn't complete. %s must be filled!") % text
         elif not TestIdentifier(action_name):
             message = _("\"%s\" is not a valid identifier!") % action_name
@@ -107,23 +107,22 @@
             dialog.Destroy()
         else:
             self.EndModal(wx.ID_OK)
-    
+
     def SetPouNames(self, pou_names):
         self.PouNames = [pou_name.upper() for pou_name in pou_names]
-        
+
     def SetPouElementNames(self, element_names):
         self.PouElementNames = [element_name.upper() for element_name in element_names]
-        
+
     def SetValues(self, values):
         for item, value in values.items():
             if item == "actionName":
                 self.ActionName.SetValue(value)
             elif item == "language":
                 self.Language.SetStringSelection(_(value))
-                
+
     def GetValues(self):
         values = {}
         values["actionName"] = self.ActionName.GetValue()
         values["language"] = ACTION_LANGUAGES_DICT[self.Language.GetStringSelection()]
         return values
-
--- a/dialogs/PouNameDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/PouNameDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -30,15 +30,15 @@
 
 class PouNameDialog(wx.TextEntryDialog):
 
-    def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", 
+    def __init__(self, parent, message, caption = "Please enter text", defaultValue = "",
                        style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition):
         wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos)
-        
+
         self.PouNames = []
-        
-        self.Bind(wx.EVT_BUTTON, self.OnOK, 
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK,
               self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton())
-        
+
     def OnOK(self, event):
         message = None
         step_name = self.GetSizer().GetItem(1).GetWindow().GetValue()
@@ -60,4 +60,3 @@
 
     def SetPouNames(self, pou_names):
         self.PouNames = [pou_name.upper() for pou_name in pou_names]
-
--- a/dialogs/PouTransitionDialog.py	Fri Aug 11 15:18:19 2017 +0300
+++ b/dialogs/PouTransitionDialog.py	Mon Aug 14 19:13:01 2017 +0300
@@ -37,46 +37,46 @@
 TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()])
 
 class PouTransitionDialog(wx.Dialog):
-    
+
     def __init__(self, parent):
         wx.Dialog.__init__(self, parent, title=_('Create a new transition'))
-        
+
         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
         main_sizer.AddGrowableCol(0)
         main_sizer.AddGrowableRow(0)
-        
+
         infos_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=3, vgap=10)
         infos_sizer.AddGrowableCol(1)
-        main_sizer.AddSizer(infos_sizer, border=20, 
+        main_sizer.AddSizer(infos_sizer, border=20,
               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        
+
         transitionname_label = wx.StaticText(self, label=_('Transition Name:'))
-        infos_sizer.AddWindow(transitionname_label, border=4, 
+        infos_sizer.AddWindow(transitionname_label, border=4,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP)
 
         self.TransitionName = wx.TextCtrl(self, size=wx.Size(180,-1))
         infos_sizer.AddWindow(self.TransitionName, flag=wx.GROW)
 
         language_label = wx.StaticText(self, label=_('Language:'))
-        infos_sizer.AddWindow(language_label, border=4, 
+        infos_sizer.AddWindow(language_label, border=4,
               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP)
-        
+
         self.Language = wx.ComboBox(self, style=wx.CB_READONLY)