Beremiz.py
changeset 248 444d4db3faea
parent 242 fc6d1988e4da
child 249 a770187273e9
equal deleted inserted replaced
247:655d5fef0204 248:444d4db3faea
   252               kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N')
   252               kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N')
   253         parent.Append(help='', id=wx.ID_OPEN,
   253         parent.Append(help='', id=wx.ID_OPEN,
   254               kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O')
   254               kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O')
   255         parent.Append(help='', id=wx.ID_SAVE,
   255         parent.Append(help='', id=wx.ID_SAVE,
   256               kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S')
   256               kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S')
   257         parent.Append(help='', id=wx.ID_CLOSE,
   257         parent.Append(help='', id=wx.ID_CLOSE_ALL,
   258               kind=wx.ITEM_NORMAL, text=u'Close Project')
   258               kind=wx.ITEM_NORMAL, text=u'Close Project')
   259         parent.AppendSeparator()
   259         parent.AppendSeparator()
   260         parent.Append(help='', id=wx.ID_PROPERTIES,
   260         parent.Append(help='', id=wx.ID_PROPERTIES,
   261               kind=wx.ITEM_NORMAL, text=u'Properties')
   261               kind=wx.ITEM_NORMAL, text=u'Properties')
   262         parent.AppendSeparator()
   262         parent.AppendSeparator()
   410         self.Log = LogPseudoFile(self.LogConsole)
   410         self.Log = LogPseudoFile(self.LogConsole)
   411         
   411         
   412         # create temporary directory for runtime working directory
   412         # create temporary directory for runtime working directory
   413         self.local_runtime_tmpdir = tempfile.mkdtemp()
   413         self.local_runtime_tmpdir = tempfile.mkdtemp()
   414         # choose an arbitrary random port for runtime
   414         # choose an arbitrary random port for runtime
   415         runtime_port = int(random.random() * 1000) + 61131
   415         self.runtime_port = int(random.random() * 1000) + 61131
   416         # launch local runtime
   416         # launch local runtime
   417         self.local_runtime = ProcessLogger(self.Log,
   417         self.local_runtime = ProcessLogger(self.Log,
   418                                            "\"%s\" \"%s\" -p %s -i localhost %s"%(sys.executable,
   418                                            "\"%s\" \"%s\" -p %s -i localhost %s"%(sys.executable,
   419                                                        Bpath("Beremiz_service.py"),
   419                                                        Bpath("Beremiz_service.py"),
   420                                                        runtime_port,
   420                                                        self.runtime_port,
   421                                                        self.local_runtime_tmpdir),
   421                                                        self.local_runtime_tmpdir),
   422                                                        no_gui=False)
   422                                                        no_gui=False)
   423         
   423         
   424         # Add beremiz's icon in top left corner of the frame
   424         # Add beremiz's icon in top left corner of the frame
   425         self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
   425         self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
   426         
   426         
   427         self.PluginRoot = PluginsRoot(self, self.Log, runtime_port)
       
   428         self.DisableEvents = False
   427         self.DisableEvents = False
   429         
   428         
   430         self.PluginInfos = {}
   429         self.PluginInfos = {}
   431         
   430         
   432         if projectOpen:
   431         if projectOpen:
       
   432             self.PluginRoot = PluginsRoot(self, self.Log, self.runtime_port)
   433             self.PluginRoot.LoadProject(projectOpen)
   433             self.PluginRoot.LoadProject(projectOpen)
   434             self.RefreshPLCParams()
   434             self.RefreshPLCParams()
   435             self.RefreshPluginTree()
   435             self.RefreshPluginTree()
       
   436         else:
       
   437             self.PluginRoot = None
   436         
   438         
   437         self.RefreshMainMenu()
   439         self.RefreshMainMenu()
   438 
   440 
   439     def OnOpenWidgetInspector(self, evt):
   441     def OnOpenWidgetInspector(self, evt):
   440         # Activate the widget inspection tool
   442         # Activate the widget inspection tool
   452     def OnLogConsoleDClick(self, event):
   454     def OnLogConsoleDClick(self, event):
   453         wx.CallAfter(self.SearchLineForError)
   455         wx.CallAfter(self.SearchLineForError)
   454         event.Skip()
   456         event.Skip()
   455 
   457 
   456     def SearchLineForError(self):
   458     def SearchLineForError(self):
   457         text = self.LogConsole.GetRange(0, self.LogConsole.GetInsertionPoint())
   459         if self.PluginRoot is not None:
   458         line = self.LogConsole.GetLineText(len(text.splitlines()) - 1)
   460             text = self.LogConsole.GetRange(0, self.LogConsole.GetInsertionPoint())
   459         result = MATIEC_ERROR_MODEL.match(line)
   461             line = self.LogConsole.GetLineText(len(text.splitlines()) - 1)
   460         if result is not None:
   462             result = MATIEC_ERROR_MODEL.match(line)
   461             first_line, first_column, last_line, last_column, error = result.groups()
   463             if result is not None:
   462             infos = self.PluginRoot.ShowError(self.Log,
   464                 first_line, first_column, last_line, last_column, error = result.groups()
   463                                               (int(first_line), int(first_column)), 
   465                 infos = self.PluginRoot.ShowError(self.Log,
   464                                               (int(last_line), int(last_column)))
   466                                                   (int(first_line), int(first_column)), 
       
   467                                                   (int(last_line), int(last_column)))
   465 		
   468 		
   466     def OnCloseFrame(self, event):
   469     def OnCloseFrame(self, event):
   467         
   470         if self.PluginRoot is not None:
   468         if self.PluginRoot.HasProjectOpened():
       
   469             if self.PluginRoot.ProjectTestModified():
   471             if self.PluginRoot.ProjectTestModified():
   470                 dialog = wx.MessageDialog(self,
   472                 dialog = wx.MessageDialog(self,
   471                                           "Save changes ?",
   473                                           "Save changes ?",
   472                                           "Close Application", 
   474                                           "Close Application", 
   473                                           wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
   475                                           wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
   494         self.GetBestSize()
   496         self.GetBestSize()
   495         self.RefreshScrollBars()
   497         self.RefreshScrollBars()
   496         event.Skip()
   498         event.Skip()
   497     
   499     
   498     def OnFrameActivated(self, event):
   500     def OnFrameActivated(self, event):
   499         if not event.GetActive():
   501         if not event.GetActive() and self.PluginRoot is not None:
   500             self.PluginRoot.RefreshPluginsBlockLists()
   502             self.PluginRoot.RefreshPluginsBlockLists()
   501     
   503     
   502     def RefreshMainMenu(self):
   504     def RefreshMainMenu(self):
   503         if self.MenuBar:
   505         if self.PluginRoot is not None:
   504             if self.PluginRoot.HasProjectOpened():
   506 ##            self.MenuBar.EnableTop(1, True)
   505 ##                self.MenuBar.EnableTop(1, True)
   507 ##            self.MenuBar.EnableTop(2, True)
   506 ##                self.MenuBar.EnableTop(2, True)
   508             self.FileMenu.Enable(wx.ID_SAVE, True)
   507                 self.FileMenu.Enable(wx.ID_SAVE, True)
   509             self.FileMenu.Enable(wx.ID_CLOSE, True)
   508                 self.FileMenu.Enable(wx.ID_CLOSE, True)
   510             self.FileMenu.Enable(wx.ID_PROPERTIES, True)
   509                 self.FileMenu.Enable(wx.ID_PROPERTIES, True)
   511         else:
   510             else:
   512 ##            self.MenuBar.EnableTop(1, False)
   511 ##                self.MenuBar.EnableTop(1, False)
   513 ##            self.MenuBar.EnableTop(2, False)
   512 ##                self.MenuBar.EnableTop(2, False)
   514             self.FileMenu.Enable(wx.ID_SAVE, False)
   513                 self.FileMenu.Enable(wx.ID_SAVE, False)
   515             self.FileMenu.Enable(wx.ID_CLOSE, False)
   514                 self.FileMenu.Enable(wx.ID_CLOSE, False)
   516             self.FileMenu.Enable(wx.ID_PROPERTIES, False)
   515                 self.FileMenu.Enable(wx.ID_PROPERTIES, False)
       
   516 
   517 
   517     def RefreshScrollBars(self):
   518     def RefreshScrollBars(self):
   518         xstart, ystart = self.PLCConfig.GetViewStart()
   519         xstart, ystart = self.PLCConfig.GetViewStart()
   519         window_size = self.PLCConfig.GetClientSize()
   520         window_size = self.PLCConfig.GetClientSize()
   520         sizer = self.PLCConfig.GetSizer()
   521         sizer = self.PLCConfig.GetSizer()
   527 
   528 
   528     def RefreshPLCParams(self):
   529     def RefreshPLCParams(self):
   529         self.Freeze()
   530         self.Freeze()
   530         self.ClearSizer(self.PLCParamsSizer)
   531         self.ClearSizer(self.PLCParamsSizer)
   531         
   532         
   532         if self.PluginRoot.HasProjectOpened():    
   533         if self.PluginRoot is not None:    
   533             plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
   534             plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
   534             if self.PluginRoot.PlugTestModified():
   535             if self.PluginRoot.PlugTestModified():
   535                 bkgdclr = CHANGED_TITLE_COLOUR
   536                 bkgdclr = CHANGED_TITLE_COLOUR
   536             else:
   537             else:
   537                 bkgdclr = TITLE_COLOUR
   538                 bkgdclr = TITLE_COLOUR
   671         return msizer
   672         return msizer
   672 
   673 
   673     def RefreshPluginTree(self):
   674     def RefreshPluginTree(self):
   674         self.Freeze()
   675         self.Freeze()
   675         self.ClearSizer(self.PluginTreeSizer)
   676         self.ClearSizer(self.PluginTreeSizer)
   676         if self.PluginRoot.HasProjectOpened():
   677         if self.PluginRoot is not None:
   677             for child in self.PluginRoot.IECSortedChilds():
   678             for child in self.PluginRoot.IECSortedChilds():
   678                 self.GenerateTreeBranch(child)
   679                 self.GenerateTreeBranch(child)
   679                 if not self.PluginInfos[child]["expanded"]:
   680                 if not self.PluginInfos[child]["expanded"]:
   680                     self.CollapsePlugin(child)
   681                     self.CollapsePlugin(child)
   681         self.PLCConfigMainSizer.Layout()
   682         self.PLCConfigMainSizer.Layout()
  1170                         textctrl.ChangeValue(str(element_infos["value"]))
  1171                         textctrl.ChangeValue(str(element_infos["value"]))
  1171                         textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path))
  1172                         textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path))
  1172             first = False
  1173             first = False
  1173     
  1174     
  1174     def OnNewProjectMenu(self, event):
  1175     def OnNewProjectMenu(self, event):
  1175         defaultpath = self.PluginRoot.GetProjectPath()
  1176         defaultpath = ""
       
  1177         if self.PluginRoot is not None:
       
  1178             defaultpath = self.PluginRoot.GetProjectPath()
  1176         if not defaultpath:
  1179         if not defaultpath:
  1177             defaultpath = os.getcwd()
  1180             defaultpath = os.getcwd()
  1178         dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
  1181         dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
  1179         if dialog.ShowModal() == wx.ID_OK:
  1182         if dialog.ShowModal() == wx.ID_OK:
  1180             projectpath = dialog.GetPath()
  1183             projectpath = dialog.GetPath()
  1181             dialog.Destroy()
  1184             dialog.Destroy()
       
  1185             self.PluginRoot = PluginsRoot(self, self.Log, self.runtime_port)
  1182             res = self.PluginRoot.NewProject(projectpath)
  1186             res = self.PluginRoot.NewProject(projectpath)
  1183             if not res :
  1187             if not res :
  1184                 self.RefreshPLCParams()
  1188                 self.RefreshPLCParams()
  1185                 self.RefreshPluginTree()
  1189                 self.RefreshPluginTree()
  1186                 self.RefreshMainMenu()
  1190                 self.RefreshMainMenu()
  1189                 message.ShowModal()
  1193                 message.ShowModal()
  1190                 message.Destroy()
  1194                 message.Destroy()
  1191         event.Skip()
  1195         event.Skip()
  1192     
  1196     
  1193     def OnOpenProjectMenu(self, event):
  1197     def OnOpenProjectMenu(self, event):
  1194         defaultpath = self.PluginRoot.GetProjectPath()
  1198         defaultpath = ""
       
  1199         if self.PluginRoot is not None:
       
  1200             defaultpath = self.PluginRoot.GetProjectPath()
  1195         if not defaultpath:
  1201         if not defaultpath:
  1196             defaultpath = os.getcwd()
  1202             defaultpath = os.getcwd()
  1197         dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
  1203         dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
  1198         if dialog.ShowModal() == wx.ID_OK:
  1204         if dialog.ShowModal() == wx.ID_OK:
  1199             projectpath = dialog.GetPath()
  1205             projectpath = dialog.GetPath()
  1200             if os.path.isdir(projectpath):
  1206             if os.path.isdir(projectpath):
       
  1207                 self.PluginRoot = PluginsRoot(self, self.Log, self.runtime_port)
  1201                 result = self.PluginRoot.LoadProject(projectpath)
  1208                 result = self.PluginRoot.LoadProject(projectpath)
  1202                 if not result:
  1209                 if not result:
  1203                     self.RefreshPLCParams()
  1210                     self.RefreshPLCParams()
  1204                     self.RefreshPluginTree()
  1211                     self.RefreshPluginTree()
  1205                     self.RefreshMainMenu()
  1212                     self.RefreshMainMenu()
  1213                 message.Destroy()
  1220                 message.Destroy()
  1214             dialog.Destroy()
  1221             dialog.Destroy()
  1215         event.Skip()
  1222         event.Skip()
  1216     
  1223     
  1217     def OnCloseProjectMenu(self, event):
  1224     def OnCloseProjectMenu(self, event):
  1218         self.PluginInfos = {}
  1225         if self.PluginRoot is not None:
  1219         self.PluginRoot.CloseProject()
  1226             if self.PluginRoot.ProjectTestModified():
  1220         self.Log.flush()
  1227                 dialog = wx.MessageDialog(self,
  1221         self.RefreshPLCParams()
  1228                                           "Save changes ?",
  1222         self.RefreshPluginTree()
  1229                                           "Close Application", 
  1223         self.RefreshMainMenu()
  1230                                           wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
       
  1231                 answer = dialog.ShowModal()
       
  1232                 dialog.Destroy()
       
  1233                 if answer == wx.ID_YES:
       
  1234                     self.PluginRoot.SaveProject()
       
  1235                 elif answer == wx.ID_CANCEL:
       
  1236                     return
       
  1237             self.PluginInfos = {}
       
  1238             self.PluginRoot = None
       
  1239             self.Log.flush()
       
  1240             self.RefreshPLCParams()
       
  1241             self.RefreshPluginTree()
       
  1242             self.RefreshMainMenu()
  1224         event.Skip()
  1243         event.Skip()
  1225     
  1244     
  1226     def OnSaveProjectMenu(self, event):
  1245     def OnSaveProjectMenu(self, event):
  1227         if self.PluginRoot.HasProjectOpened():
  1246         if self.PluginRoot is not None:
  1228             self.PluginRoot.SaveProject()
  1247             self.PluginRoot.SaveProject()
  1229             self.RefreshAll()
  1248             self.RefreshAll()
  1230         event.Skip()
  1249         event.Skip()
  1231     
  1250     
  1232     def OnPropertiesMenu(self, event):
  1251     def OnPropertiesMenu(self, event):