--- a/Dialogs.py Wed Jul 25 10:06:29 2007 +0200
+++ b/Dialogs.py Thu Jul 26 17:23:21 2007 +0200
@@ -384,21 +384,23 @@
self.RefreshNameList()
def SetValues(self, values):
- for name, value in values.items():
- if name == "type":
- if value == INPUT:
- self.Class.SetStringSelection("Input")
- if value == OUTPUT:
- self.Class.SetStringSelection("Output")
- if value == INOUT:
- self.Class.SetStringSelection("InOut")
- elif name == "name" and value != "":
- if self.Name.FindString(value) != wxNOT_FOUND:
- self.Name.SetStringSelection(value)
- self.Expression.Enable(False)
- else:
- self.Expression.SetValue(value)
- self.Name.Enable(False)
+ value_type = values.get("type", None)
+ value_name = values.get("name", None)
+ if value_type:
+ if value_type == INPUT:
+ self.Class.SetStringSelection("Input")
+ if value_type == OUTPUT:
+ self.Class.SetStringSelection("Output")
+ if value_type == INOUT:
+ self.Class.SetStringSelection("InOut")
+ self.RefreshNameList()
+ if value_name:
+ if self.Name.FindString(value_name) != wxNOT_FOUND:
+ self.Name.SetStringSelection(value_name)
+ self.Expression.Enable(False)
+ else:
+ self.Expression.SetValue(value_name)
+ self.Name.Enable(False)
self.RefreshPreview()
def GetValues(self):
--- a/LDViewer.py Wed Jul 25 10:06:29 2007 +0200
+++ b/LDViewer.py Thu Jul 26 17:23:21 2007 +0200
@@ -411,7 +411,29 @@
self.DeleteWire(self.SelectedElement)
else:
self.SelectedElement.Delete()
- self.Refresh()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
+ elif keycode == WXK_LEFT:
+ if event.ControlDown() and event.ShiftDown():
+ self.Scroll(0, ypos)
+ elif event.ControlDown():
+ self.Scroll(max(0, xpos - 1), ypos)
+ elif keycode == WXK_RIGHT:
+ if event.ControlDown() and event.ShiftDown():
+ self.Scroll(xmax, ypos)
+ elif event.ControlDown():
+ self.Scroll(min(xpos + 1, xmax), ypos)
+ elif keycode == WXK_UP:
+ if event.ControlDown() and event.ShiftDown():
+ self.Scroll(xpos, 0)
+ elif event.ControlDown():
+ self.Scroll(xpos, max(0, ypos - 1))
+ elif keycode == WXK_DOWN:
+ if event.ControlDown() and event.ShiftDown():
+ self.Scroll(xpos, ymax)
+ elif event.ControlDown():
+ self.Scroll(xpos, min(ypos + 1, ymax))
event.Skip()
#-------------------------------------------------------------------------------
@@ -493,6 +515,8 @@
rung.SelectElement(wire)
self.RefreshPosition(coil)
self.Rungs.append(rung)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
def AddLadderContact(self):
@@ -584,6 +608,8 @@
rung.RefreshBoundingBox()
new_bbox = rung.GetBoundingBox()
self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
else:
message = wxMessageDialog(self, "You must select the wire where a contact should be added!", "Error", wxOK|wxICON_ERROR)
@@ -803,6 +829,8 @@
rung.RefreshBoundingBox()
new_bbox = rung.GetBoundingBox()
self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
else:
message = wxMessageDialog(self, "The group of block must be coherent!", "Error", wxOK|wxICON_ERROR)
@@ -1158,6 +1186,8 @@
contact.SetName(values["name"])
contact.SetType(values["type"])
contact.RefreshModel(False)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1182,6 +1212,8 @@
coil.SetName(values["name"])
coil.SetType(values["type"])
coil.RefreshModel(False)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
--- a/PLCControler.py Wed Jul 25 10:06:29 2007 +0200
+++ b/PLCControler.py Thu Jul 26 17:23:21 2007 +0200
@@ -162,6 +162,7 @@
self.VerifyXML = False
self.Project = None
self.ProjectBuffer = None
+ self.Buffering = False
self.FilePath = ""
self.FileName = ""
self.ProgramFilePath = ""
@@ -187,16 +188,10 @@
# Create the project
self.Project = plcopen.project()
self.Project.setName(name)
+ self.SetFilePath("")
# Initialize the project buffer
- #self.ProjectBuffer = UndoBuffer(self.Copy(self.Project))
-
- # Change project name
- def SetProjectName(self, name):
- self.Project.setName(name)
-
- # Return project name
- def GetProjectName(self):
- return self.Project.getName()
+ self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
+ self.Buffering = False
# Return project pou names
def GetProjectPouNames(self):
@@ -219,6 +214,10 @@
variables.append(action.getName())
return variables
+ # Return if project is saved
+ def ProjectIsSaved(self):
+ return self.ProjectBuffer.IsCurrentSaved()
+
# Return file path if project is an open file
def GetFilePath(self):
return self.FilePath
@@ -244,12 +243,19 @@
self.FileName = os.path.splitext(os.path.basename(filepath))[0]
# Change project properties
- def SetProjectProperties(self, values):
- self.Project.setFileHeader(values)
-
+ def SetProjectProperties(self, name = None, properties = None):
+ if name != None:
+ self.Project.setName(name)
+ if properties != None:
+ self.Project.setFileHeader(properties)
+ if name != None or properties != None:
+ self.BufferProject()
+
# Return project properties
def GetProjectProperties(self):
- return self.Project.getFileHeader()
+ properties = self.Project.getFileHeader()
+ properties["projectName"] = self.Project.getName()
+ return properties
# Return project informations
def GetProjectInfos(self):
@@ -376,15 +382,15 @@
def GenerateProgram(self, filepath):
if self.Project:
- #try:
- program = GenerateCurrentProgram(self.Project)
- programfile = open(filepath, "w")
- programfile.write(program)
- programfile.close()
- self.ProgramFilePath = filepath
- return True
- #except:
- # pass
+ try:
+ program = GenerateCurrentProgram(self.Project)
+ programfile = open(filepath, "w")
+ programfile.write(program)
+ programfile.close()
+ self.ProgramFilePath = filepath
+ return True
+ except:
+ pass
return False
#-------------------------------------------------------------------------------
@@ -397,6 +403,7 @@
self.Project.appendPou(name, pou_type, body_type)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Remove a pou from project
def ProjectRemovePou(self, name):
@@ -418,40 +425,47 @@
self.Project.removePou(name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Add a configuration to Project
def ProjectAddConfiguration(self, name):
self.Project.addConfiguration(name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Remove a configuration from project
def ProjectRemoveConfiguration(self, name):
self.Project.removeConfiguration(name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Add a resource to a configuration of the Project
def ProjectAddConfigurationResource(self, config, name):
self.Project.addConfigurationResource(config, name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Remove a resource from a configuration of the project
def ProjectRemoveConfigurationResource(self, config, name):
self.Project.removeConfigurationResource(config, name)
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Add a Transition to a Project Pou
def ProjectAddPouTransition(self, pou_name, transition_name, transition_type):
pou = self.Project.getPou(pou_name)
pou.addTransition(transition_name, transition_type)
+ self.BufferProject()
# Add a Transition to a Project Pou
def ProjectAddPouAction(self, pou_name, action_name, action_type):
pou = self.Project.getPou(pou_name)
pou.addAction(action_name, action_type)
+ self.BufferProject()
# Change the name of a pou
def ChangePouName(self, old_name, new_name):
@@ -464,6 +478,7 @@
self.ElementsOpened[idx] = new_name
self.RefreshPouUsingTree()
self.RefreshBlockTypes()
+ self.BufferProject()
# Change the name of a pou transition
def ChangePouTransitionName(self, pou_name, old_name, new_name):
@@ -477,6 +492,7 @@
if old_computedname in self.ElementsOpened:
idx = self.ElementsOpened.index(old_computedname)
self.ElementsOpened[idx] = new_computedname
+ self.BufferProject()
# Change the name of a pou action
def ChangePouActionName(self, pou_name, old_name, new_name):
@@ -490,7 +506,8 @@
if old_computedname in self.ElementsOpened:
idx = self.ElementsOpened.index(old_computedname)
self.ElementsOpened[idx] = new_computedname
-
+ self.BufferProject()
+
# Change the name of a pou action
def ChangePouVariableName(self, pou_name, old_name, new_name):
# Found the pou action corresponding to old name and change its name to new name
@@ -500,6 +517,7 @@
if var.getName() == old_name:
var.setName(new_name)
self.RefreshBlockTypes()
+ self.BufferProject()
# Change the name of a configuration
def ChangeConfigurationName(self, old_name, new_name):
@@ -509,7 +527,8 @@
# If configuration is currently opened, change its name in the list of opened elements
for idx, element in enumerate(self.ElementsOpened):
self.ElementsOpened[idx] = element.replace(old_name, new_name)
-
+ self.BufferProject()
+
# Change the name of a configuration resource
def ChangeConfigurationResourceName(self, config_name, old_name, new_name):
# Found the resource corresponding to old name and change its name to new name
@@ -521,6 +540,7 @@
if old_computedname in self.ElementsOpened:
idx = self.ElementsOpened.index(old_computedname)
self.ElementsOpened[idx] = new_computedname
+ self.BufferProject()
# Return the type of the pou given by its name
def GetPouType(self, name):
@@ -579,11 +599,13 @@
def ProjectRemovePouTransition(self, pou_name, transition_name):
pou = self.Project.getPou(pou_name)
pou.removeTransition(transition_name)
+ self.BufferProject()
# Add a Transition to a Project Pou
def ProjectRemovePouAction(self, pou_name, action_name):
pou = self.Project.getPou(pou_name)
pou.removeAction(action_name)
+ self.BufferProject()
# Extract varlists from a list of vars
def ExtractVarLists(self, vars):
@@ -627,7 +649,8 @@
for vartype, varlist in self.ExtractVarLists(vars):
configuration.globalVars.append(varlist)
self.RefreshBlockTypes()
-
+ self.BufferProject()
+
# Return the configuration globalvars
def GetConfigurationGlobalVars(self, name):
vars = []
@@ -669,7 +692,8 @@
for vartype, varlist in self.ExtractVarLists(vars):
resource.globalVars.append(varlist)
self.RefreshBlockTypes()
-
+ self.BufferProject()
+
# Return the resource globalvars
def GetConfigurationResourceGlobalVars(self, config_name, name):
vars = []
@@ -745,7 +769,8 @@
# Set Pou interface
pou.setVars(self.ExtractVarLists(vars))
self.RefreshBlockTypes()
-
+ self.BufferProject()
+
# Replace the return type of the pou given by its name (only for functions)
def SetPouInterfaceReturnType(self, name, type):
pou = self.Project.getPou(name)
@@ -759,6 +784,7 @@
# Change return type
return_type.setValue(type)
self.RefreshBlockTypes()
+ self.BufferProject()
# Return the return type of the pou given by its name
def GetPouInterfaceReturnTypeByName(self, name):
@@ -1951,8 +1977,9 @@
self.Project = plcopen.project()
self.Project.loadXMLTree(tree.childNodes[0])
- self.UndoBuffer = UndoBuffer(self.Copy(self.Project), True)
self.SetFilePath(filepath)
+ self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True)
+ self.Buffering = False
self.ElementsOpened = []
self.CurrentElementEditing = None
self.RefreshPouUsingTree()
@@ -1982,7 +2009,7 @@
xmlfile = open(self.FilePath,"w")
xmlfile.write(text)
xmlfile.close()
- #self.ProjectBuffer.CurrentSaved()
+ self.ProjectBuffer.CurrentSaved()
if filepath:
self.SetFilePath(filepath)
return True
@@ -1998,18 +2025,25 @@
return cPickle.loads(cPickle.dumps(model))
def BufferProject(self):
- self.ProjectBuffer.Buffering(self.Copy(self))
+ self.ProjectBuffer.Buffering(self.Copy(self.Project))
+
+ def StartBuffering(self):
+ self.ProjectBuffer.Buffering(self.Project)
+ self.Buffering = True
+
+ def EndBuffering(self):
+ if self.Buffering:
+ self.Project = self.Copy(self.Project)
+ self.Buffering = False
def ProjectIsSaved(self):
return self.ProjectBuffer.IsCurrentSaved()
def LoadPrevious(self):
self.Project = self.Copy(self.ProjectBuffer.Previous())
- self.RefreshElementsOpened()
def LoadNext(self):
self.Project = self.Copy(self.ProjectBuffer.Next())
- self.RefreshElementsOpened()
def GetBufferState(self):
first = self.ProjectBuffer.IsFirst()
--- a/PLCOpenEditor.py Wed Jul 25 10:06:29 2007 +0200
+++ b/PLCOpenEditor.py Thu Jul 26 17:23:21 2007 +0200
@@ -190,6 +190,10 @@
kind=wx.ITEM_NORMAL, text=u'Remove Configuration')
self.Bind(wx.EVT_MENU, self.OnRefreshMenu,
id=wxID_PLCOPENEDITOREDITMENUITEMS0)
+ self.Bind(wx.EVT_MENU, self.OnUndoMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS1)
+ self.Bind(wx.EVT_MENU, self.OnRedoMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS2)
self.Bind(wx.EVT_MENU, self.OnCutMenu,
id=wxID_PLCOPENEDITOREDITMENUITEMS4)
self.Bind(wx.EVT_MENU, self.OnCopyMenu,
@@ -373,6 +377,7 @@
self._init_utils()
self.SetClientSize(wx.Size(1000, 600))
self.SetMenuBar(self.menuBar1)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseFrame, id=wxID_PLCOPENEDITOR)
self.splitterWindow1 = wx.SplitterWindow(id=wxID_PLCOPENEDITORSPLITTERWINDOW1,
name='splitterWindow1', parent=self, point=wx.Point(0, 0),
@@ -443,11 +448,18 @@
self.RefreshFileMenu()
self.RefreshEditMenu()
+ self.RefreshTitle()
self.RefreshToolBar()
def GetDrawingMode(self):
return self.DrawingMode
+ def RefreshTitle(self):
+ if self.Controler.HasOpenedProject() > 0:
+ self.SetTitle("PLCOpenEditor - %s"%self.Controler.GetFilename())
+ else:
+ self.SetTitle("PLCOpenEditor")
+
def RefreshFileMenu(self):
if self.FileMenu:
if self.Controler.HasOpenedProject():
@@ -470,8 +482,13 @@
def RefreshEditMenu(self):
if self.EditMenu:
- self.EditMenu.FindItemByPosition(1).Enable(False)
- self.EditMenu.FindItemByPosition(2).Enable(False)
+ if self.Controler.HasOpenedProject():
+ undo, redo = self.Controler.GetBufferState()
+ self.EditMenu.Enable(wxID_PLCOPENEDITOREDITMENUITEMS1, undo)
+ self.EditMenu.Enable(wxID_PLCOPENEDITOREDITMENUITEMS2, redo)
+ else:
+ self.EditMenu.Enable(wxID_PLCOPENEDITOREDITMENUITEMS1, False)
+ self.EditMenu.Enable(wxID_PLCOPENEDITOREDITMENUITEMS2, False)
if self.Controler.HasOpenedProject():
if self.TabsOpened.GetPageCount() > 0:
self.EditMenu.FindItemByPosition(0).Enable(True)
@@ -495,18 +512,29 @@
def ShowProperties(self):
old_values = self.Controler.GetProjectProperties()
- old_values["projectName"] = self.Controler.GetProjectName()
dialog = ProjectDialog(self)
dialog.SetValues(old_values)
if dialog.ShowModal() == wxID_OK:
new_values = dialog.GetValues()
projectname = new_values.pop("projectName")
new_values["creationDateTime"] = old_values["creationDateTime"]
- self.Controler.SetProjectName(projectname)
- self.Controler.SetProjectProperties(new_values)
+ self.Controler.SetProjectProperties(projectname, new_values)
self.RefreshProjectTree()
dialog.Destroy()
+ def OnCloseFrame(self, event):
+ if not self.Controler.ProjectIsSaved():
+ dialog = wxMessageDialog(self, "There are changes, do you want to save?", "Close Application", wxYES_NO|wxCANCEL|wxICON_QUESTION)
+ answer = dialog.ShowModal()
+ dialog.Destroy()
+ if answer == wxID_YES:
+ self.SaveProject()
+ event.Skip()
+ elif answer == wxID_NO:
+ event.Skip()
+ else:
+ event.Skip()
+
def OnNewProjectMenu(self, event):
dialog = ProjectDialog(self)
if dialog.ShowModal() == wxID_OK:
@@ -514,7 +542,8 @@
projectname = values.pop("projectName")
values["creationDateTime"] = datetime(*localtime()[:6])
self.Controler.CreateNewProject(projectname)
- self.Controler.SetProjectProperties(values)
+ self.Controler.SetProjectProperties(projectname, values)
+ self.RefreshTitle()
self.RefreshFileMenu()
self.RefreshEditMenu()
self.RefreshProjectTree()
@@ -533,6 +562,7 @@
self.Controler.OpenXMLFile(filepath)
self.TabsOpened.DeleteAllPages()
self.RefreshProjectTree()
+ self.RefreshTitle()
self.RefreshFileMenu()
self.RefreshEditMenu()
self.RefreshToolBar()
@@ -546,6 +576,7 @@
self.TabsOpened.DeletePage(selected)
if self.TabsOpened.GetPageCount() > 0:
self.TabsOpened.SetSelection(min(selected, self.TabsOpened.GetPageCount() - 1))
+ self.RefreshTitle()
self.RefreshFileMenu()
self.RefreshEditMenu()
self.RefreshToolBar()
@@ -555,6 +586,7 @@
self.Controler.Reset()
self.TabsOpened.DeleteAllPages()
self.ProjectTree.DeleteAllItems()
+ self.RefreshTitle()
self.RefreshFileMenu()
self.RefreshEditMenu()
self.RefreshToolBar()
@@ -589,13 +621,15 @@
result = self.Controler.SaveXMLFile()
if not result:
self.SaveProjectAs()
+ else:
+ self.RefreshTitle()
def SaveProjectAs(self):
filepath = self.Controler.GetFilePath()
if filepath != "":
directory, filename = os.path.split(filepath)
else:
- directory, filename = os.getcwd(), "%s.xml"%self.Controler.GetProjectName()
+ directory, filename = os.getcwd(), "%(projectName)s.xml"%self.Controler.GetProjectProperties()
dialog = wxFileDialog(self, "Choose a file", directory, filename, "PLCOpen files (*.xml)|*.xml|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT)
if dialog.ShowModal() == wxID_OK:
filepath = dialog.GetPath()
@@ -609,6 +643,7 @@
message = wxMessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wxOK|wxICON_ERROR)
message.ShowModal()
message.Destroy()
+ self.RefreshTitle()
dialog.Destroy()
def OnPropertiesMenu(self, event):
@@ -768,6 +803,9 @@
event.Skip()
def OnPouSelectedChanged(self, event):
+ old_selected = self.TabsOpened.GetSelection()
+ if old_selected >= 0:
+ self.TabsOpened.GetPage(old_selected).ResetBuffer()
selected = event.GetSelection()
if selected >= 0:
self.Controler.RefreshCurrentElementEditing(selected)
@@ -809,7 +847,7 @@
item = event.GetItem()
itemtype = self.ProjectTree.GetPyData(item)
if itemtype == ITEM_PROJECT:
- self.Controler.SetProjectName(new_name)
+ self.Controler.SetProjectProperties(name = new_name)
elif itemtype == ITEM_POU:
if new_name.upper() in self.Controler.GetProjectPouNames():
message = "\"%s\" pou already exists!"%new_name
@@ -1088,6 +1126,9 @@
else:
idx = self.Controler.ChangePouActionEditing(grandparent_name, name)
if idx != None:
+ old_selected = self.TabsOpened.GetSelection()
+ if old_selected >= 0:
+ self.TabsOpened.GetPage(old_selected).ResetBuffer()
self.TabsOpened.SetSelection(idx)
window = self.TabsOpened.GetPage(idx)
window.RefreshView()
@@ -1197,9 +1238,30 @@
def OnRefreshMenu(self, event):
selected = self.TabsOpened.GetSelection()
if selected != -1:
+ self.TabsOpened.GetPage(selected).RefreshView()
self.TabsOpened.GetPage(selected).Refresh()
event.Skip()
-
+
+ def OnUndoMenu(self, event):
+ self.Controler.LoadPrevious()
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).RefreshView()
+ self.TabsOpened.GetPage(selected).Refresh()
+ self.RefreshTitle()
+ self.RefreshEditMenu()
+ event.Skip()
+
+ def OnRedoMenu(self, event):
+ self.Controler.LoadNext()
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).RefreshView()
+ self.TabsOpened.GetPage(selected).Refresh()
+ self.RefreshTitle()
+ self.RefreshEditMenu()
+ event.Skip()
+
def OnCutMenu(self, event):
selected = self.TabsOpened.GetSelection()
if selected != -1:
@@ -1244,9 +1306,12 @@
selected = dialog.GetStringSelection()
if not self.Controler.PouIsUsed(selected):
self.Controler.ProjectRemovePou(selected)
+ deleted = None
for i in xrange(self.TabsOpened.GetPageCount()):
if self.TabsOpened.GetPageText(i) == selected:
- self.TabsOpened.DeletePage(i)
+ deleted = i
+ if deleted != None:
+ self.TabsOpened.DeletePage(i)
self.RefreshProjectTree()
self.RefreshToolBar()
else:
@@ -2173,6 +2238,8 @@
self.Viewer = wx.Panel(id=wxID_POUEDITORPANELVIEWER,
name='ConfigPanel', parent=self, pos=wx.Point(0, 0),
size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
+ self.Viewer.ResetBuffer = lambda: None
+ self.Viewer.RefreshView = lambda: None
elif element_type == "resource":
self.Viewer = ResourceEditor(self, self.Parent, self.Controler)
elif element_type == "FBD":
@@ -2327,6 +2394,9 @@
if language not in ["IL", "ST"]:
self.Viewer.SetMode(mode)
+ def ResetBuffer(self):
+ self.Viewer.ResetBuffer()
+
def RefreshView(self):
self.PouNames = self.Controler.GetProjectPouNames()
@@ -2360,9 +2430,8 @@
self.ReturnType.SetStringSelection(returnType)
self.RefreshValues()
self.RefreshButtons()
- if self.ElementType != "config":
- self.Viewer.RefreshView()
-
+ self.Viewer.RefreshView()
+
def OnClassFilter(self, event):
self.Filter = self.FilterChoiceTransfer[self.ClassFilter.GetStringSelection()]
self.RefreshTypeList()
@@ -2381,15 +2450,16 @@
self.ClassList = [self.Filter]
def RefreshButtons(self):
- table_length = len(self.Table.data)
- row_class = None
- if table_length and self.PouIsUsed:
- row = self.VariablesGrid.GetGridCursorRow()
- row_class = self.Table.GetValueByName(row, "Class")
- self.AddButton.Enable(not self.PouIsUsed or self.Filter not in ["Interface", "Input", "Output", "InOut"])
- self.DeleteButton.Enable(table_length > 0 and row_class not in ["Input", "Output", "InOut"])
- self.UpButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
- self.DownButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
+ if self.Table:
+ table_length = len(self.Table.data)
+ row_class = None
+ if table_length and self.PouIsUsed:
+ row = self.VariablesGrid.GetGridCursorRow()
+ row_class = self.Table.GetValueByName(row, "Class")
+ self.AddButton.Enable(not self.PouIsUsed or self.Filter not in ["Interface", "Input", "Output", "InOut"])
+ self.DeleteButton.Enable(table_length > 0 and row_class not in ["Input", "Output", "InOut"])
+ self.UpButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
+ self.DownButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
def OnAddButton(self, event):
new_row = self.DefaultValue.copy()
--- a/RessourceEditor.py Wed Jul 25 10:06:29 2007 +0200
+++ b/RessourceEditor.py Thu Jul 26 17:23:21 2007 +0200
@@ -419,6 +419,16 @@
def RefreshModel(self):
self.Controler.SetCurrentResourceEditingInfos(self.TasksTable.GetData(), self.InstancesTable.GetData())
+ self.RefreshBuffer()
+
+ def ResetBuffer(self):
+ pass
+
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferProject()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
def RefreshView(self):
tasks, instances = self.Controler.GetCurrentResourceEditingInfos()
@@ -433,7 +443,6 @@
def OnAddTaskButton(self, event):
self.TasksTable.AppendRow(self.TasksDefaultValue.copy())
self.RefreshModel()
- self.RefreshView()
event.Skip()
def OnDeleteTaskButton(self, event):
--- a/SFCViewer.py Wed Jul 25 10:06:29 2007 +0200
+++ b/SFCViewer.py Thu Jul 26 17:23:21 2007 +0200
@@ -313,6 +313,9 @@
if keycode == WXK_DELETE and self.SelectedElement:
self.SelectedElement.Delete()
self.SelectedElement = None
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_LEFT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(0, ypos)
@@ -320,6 +323,9 @@
self.Scroll(max(0, xpos - 1), ypos)
elif self.SelectedElement:
self.SelectedElement.Move(-scaling[0], 0)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_RIGHT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xmax, ypos)
@@ -327,6 +333,9 @@
self.Scroll(min(xpos + 1, xmax), ypos)
elif self.SelectedElement:
self.SelectedElement.Move(scaling[0], 0)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_UP:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, 0)
@@ -334,6 +343,9 @@
self.Scroll(xpos, max(0, ypos - 1))
elif self.SelectedElement:
self.SelectedElement.Move(0, -scaling[1])
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_DOWN:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, ymax)
@@ -341,7 +353,9 @@
self.Scroll(xpos, min(ypos + 1, ymax))
elif self.SelectedElement:
self.SelectedElement.Move(0, scaling[1])
- self.Refresh()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
#-------------------------------------------------------------------------------
# Adding element functions
@@ -364,6 +378,8 @@
self.Controler.AddCurrentElementEditingStep(id)
self.RefreshStepModel(step)
self.Parent.RefreshProjectTree()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -417,6 +433,8 @@
self.SelectedElement = step
self.SelectedElement.SetSelected(True)
self.Parent.RefreshProjectTree()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -444,6 +462,8 @@
self.AddBlock(actionblock)
self.Controler.AddCurrentElementEditingActionBlock(id)
self.RefreshActionBlockModel(actionblock)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -638,6 +658,8 @@
transition_connectors = transition.GetConnectors()
previous = transition_connectors["output"]
self.CreateStep("Step", previous)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -654,6 +676,8 @@
else:
previous = divergence_connectors["outputs"][-1]
step = self.CreateStep("Step", previous)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
def AddJump(self):
@@ -681,23 +705,10 @@
transition.RefreshOutputPosition()
wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
self.RefreshJumpModel(jump)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
-
- def AddComment(self, bbox):
- dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE)
- if dialog.ShowModal() == wxID_OK:
- value = dialog.GetValue()
- id = self.GetNewId()
- comment = Comment(self, value, id)
- comment.SetPosition(bbox.x, bbox.y)
- min_width, min_height = comment.GetMinSize()
- comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height))
- self.AddComment(comment)
- self.Controler.AddCurrentElementEditingComment(id)
- self.RefreshCommentModel(comment)
- self.Refresh()
- dialog.Destroy()
def EditStepContent(self, step):
dialog = StepNameDialog(self.Parent, "Edit step name", "Please enter step name", step.GetName(), wxOK|wxCANCEL)
@@ -711,6 +722,8 @@
size = step.GetSize()
step.UpdateSize(max(min_size[0], size[0]), max(min_size[1], size[1]))
step.RefreshModel()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -723,6 +736,8 @@
transition.SetType(values["type"])
transition.SetCondition(values["value"])
transition.RefreshModel()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -737,6 +752,8 @@
value = dialog.GetStringSelection()
jump.SetTarget(value)
jump.RefreshModel()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -750,6 +767,8 @@
actions = dialog.GetValues()
actionblock.SetActions(actions)
actionblock.RefreshModel()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
--- a/TextViewer.py Wed Jul 25 10:06:29 2007 +0200
+++ b/TextViewer.py Thu Jul 26 17:23:21 2007 +0200
@@ -25,6 +25,7 @@
from wxPython.wx import *
from wxPython.stc import *
import wx
+from types import *
import re
@@ -68,6 +69,27 @@
IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
+def GetCursorPos(old, new):
+ old_length = len(old)
+ new_length = len(new)
+ common_length = min(old_length, new_length)
+ i = 0
+ for i in xrange(common_length):
+ if old[i] != new[i]:
+ break
+ if old_length < new_length:
+ if common_length > 0 and old[i] != new[i]:
+ return i + new_length - old_length
+ else:
+ return i + new_length - old_length + 1
+ elif old_length > new_length or i < min(old_length, new_length) - 1:
+ if common_length > 0 and old[i] != new[i]:
+ return i
+ else:
+ return i + 1
+ else:
+ return None
+
class TextViewer(wxStyledTextCtrl):
def __init__(self, parent, window, controler):
@@ -112,14 +134,40 @@
self.Functions = []
self.Jumps = []
self.TextChanged = False
+ self.DisableEvents = True
self.TextSyntax = "ST"
-
+ self.CurrentAction = None
+
+ self.Parent = window
self.Controler = controler
+ self.SetModEventMask(wxSTC_MOD_BEFOREINSERT|wxSTC_MOD_BEFOREDELETE)
+
EVT_KEY_DOWN(self, self.OnKeyDown)
EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
EVT_STC_DO_DROP(self, wxID_TEXTVIEWER, self.OnDoDrop)
EVT_KILL_FOCUS(self, self.OnKillFocus)
+ EVT_STC_MODIFIED(self, wxID_TEXTVIEWER, self.OnModification)
+
+ def OnModification(self, event):
+ if not self.DisableEvents:
+ mod_type = event.GetModificationType()
+ if not (mod_type&wxSTC_PERFORMED_UNDO or mod_type&wxSTC_PERFORMED_REDO):
+ if mod_type&wxSTC_MOD_BEFOREINSERT:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Add", event.GetPosition())
+ elif mod_type&wxSTC_MOD_BEFOREDELETE:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Delete", event.GetPosition())
+ event.Skip()
def OnDoDrop(self, event):
try:
@@ -156,10 +204,39 @@
self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
self.Colourise(0, -1)
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferProject()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
+
+ def StartBuffering(self):
+ self.Controler.StartBuffering()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
+
+ def ResetBuffer(self):
+ if self.CurrentAction != None:
+ self.Controler.EndBuffering()
+ self.CurrentAction = None
+
def RefreshView(self):
- self.SetText(self.Controler.GetCurrentElementEditingText())
+ self.ResetBuffer()
+ self.DisableEvents = True
+ old_cursor_pos = self.GetCurrentPos()
+ old_text = self.GetText()
+ new_text = self.Controler.GetCurrentElementEditingText()
+ self.SetText(new_text)
+ new_cursor_pos = GetCursorPos(old_text, new_text)
+ if new_cursor_pos != None:
+ self.SetSelection(new_cursor_pos, new_cursor_pos)
+ self.EnsureCaretVisible()
+ else:
+ self.SetSelection(old_cursor_pos, old_cursor_pos)
self.RefreshJumpList()
-
+ self.EmptyUndoBuffer()
+ self.DisableEvents = False
+
def OnStyleNeeded(self, event):
self.TextChanged = True
line = self.LineFromPosition(self.GetEndStyled())
@@ -273,13 +350,17 @@
event.Skip()
def Cut(self):
+ self.ResetBuffer()
self.CmdKeyExecute(wxSTC_CMD_CUT)
-
+ self.RefreshBuffer()
+
def Copy(self):
self.CmdKeyExecute(wxSTC_CMD_COPY)
def Paste(self):
+ self.ResetBuffer()
self.CmdKeyExecute(wxSTC_CMD_PASTE)
+ self.RefreshBuffer()
def RefreshModel(self):
if self.TextChanged:
--- a/Viewer.py Wed Jul 25 10:06:29 2007 +0200
+++ b/Viewer.py Thu Jul 26 17:23:21 2007 +0200
@@ -266,15 +266,24 @@
self.SelectedElement.SetSelected(False)
self.SelectedElement = None
self.Refresh()
-
+
# Return current drawing mode
def GetDrawingMode(self):
return self.Parent.GetDrawingMode()
+
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferProject()
+ self.Parent.RefreshTitle()
+ self.Parent.RefreshEditMenu()
#-------------------------------------------------------------------------------
# Refresh functions
#-------------------------------------------------------------------------------
+ def ResetBuffer(self):
+ pass
+
# Refresh Viewer elements
def RefreshView(self):
self.current_id = 0
@@ -849,6 +858,7 @@
self.SelectedElement.GeneratePoints()
self.SelectedElement.RefreshModel()
self.SelectedElement.SetSelected(True)
+ self.RefreshBuffer()
else:
self.SelectedElement.Delete()
self.SelectedElement = None
@@ -927,6 +937,9 @@
self.SelectedElement.Clean()
self.SelectedElement.Delete()
self.SelectedElement = None
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_LEFT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(0, ypos)
@@ -934,6 +947,9 @@
self.Scroll(max(0, xpos - 1), ypos)
elif self.SelectedElement:
self.SelectedElement.Move(-scaling[0], 0)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_RIGHT:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xmax, ypos)
@@ -941,6 +957,9 @@
self.Scroll(min(xpos + 1, xmax), ypos)
elif self.SelectedElement:
self.SelectedElement.Move(scaling[0], 0)
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_UP:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, 0)
@@ -948,6 +967,9 @@
self.Scroll(xpos, max(0, ypos - 1))
elif self.SelectedElement:
self.SelectedElement.Move(0, -scaling[1])
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
elif keycode == WXK_DOWN:
if event.ControlDown() and event.ShiftDown():
self.Scroll(xpos, ymax)
@@ -955,7 +977,9 @@
self.Scroll(xpos, min(ypos + 1, ymax))
elif self.SelectedElement:
self.SelectedElement.Move(0, scaling[1])
- self.Refresh()
+ self.RefreshBuffer()
+ self.RefreshScrollBars()
+ self.Refresh()
#-------------------------------------------------------------------------------
# Model adding functions
@@ -977,6 +1001,7 @@
self.AddBlock(block)
self.Controler.AddCurrentElementEditingBlock(id)
self.RefreshBlockModel(block)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1002,6 +1027,7 @@
self.AddBlock(variable)
self.Controler.AddCurrentElementEditingVariable(id, values["type"])
self.RefreshVariableModel(variable)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1018,6 +1044,7 @@
self.AddBlock(connection)
self.Controler.AddCurrentElementEditingConnection(id, values["type"])
self.RefreshConnectionModel(connection)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1034,6 +1061,7 @@
self.AddComment(comment)
self.Controler.AddCurrentElementEditingComment(id)
self.RefreshCommentModel(comment)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1058,6 +1086,7 @@
self.AddBlock(contact)
self.Controler.AddCurrentElementEditingContact(id)
self.RefreshContactModel(contact)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1085,6 +1114,7 @@
self.AddBlock(coil)
self.Controler.AddCurrentElementEditingCoil(id)
self.RefreshCoilModel(contact)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1101,6 +1131,7 @@
self.AddBlock(powerrail)
self.Controler.AddCurrentElementEditingPowerRail(id, values["type"])
self.RefreshPowerRailModel(powerrail)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1118,6 +1149,7 @@
self.AddBlock(transition)
self.Controler.AddCurrentElementEditingTransition(id)
self.RefreshTransitionModel(transition)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1135,6 +1167,7 @@
self.AddBlock(divergence)
self.Controler.AddCurrentElementEditingDivergence(id, values["type"])
self.RefreshDivergenceModel(divergence)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1158,6 +1191,7 @@
block.SetSize(values["width"], values["height"])
block.SetType(values["type"], values["extension"])
self.RefreshBlockModel(block)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1187,6 +1221,7 @@
self.Controler.RemoveCurrentElementEditingInstance(id)
self.Controler.AddCurrentElementEditingVariable(id, values["type"])
self.RefreshVariableModel(variable)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1207,6 +1242,7 @@
self.Controler.RemoveCurrentElementEditingInstance(id)
self.Controler.AddCurrentElementEditingConnection(id, values["type"])
self.RefreshConnectionModel(connection)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1229,6 +1265,7 @@
contact.SetType(values["type"])
contact.SetSize(values["width"], values["height"])
self.RefreshContactModel(contact)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1254,6 +1291,7 @@
coil.SetType(values["type"])
coil.SetSize(values["width"], values["height"])
self.RefreshContactModel(coil)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
@@ -1271,6 +1309,7 @@
self.Controler.RemoveCurrentElementEditingInstance(id)
self.Controler.AddCurrentElementEditingPowerRail(id, values["type"])
self.RefreshPowerRailModel(powerrail)
+ self.RefreshBuffer()
self.RefreshScrollBars()
self.Refresh()
dialog.Destroy()
--- a/examples/example.xml Wed Jul 25 10:06:29 2007 +0200
+++ b/examples/example.xml Thu Jul 26 17:23:21 2007 +0200
@@ -862,6 +862,7 @@
Control_State := TRUE;
ELSE
Control_State := FALSE;
+
PumpSpeed := 10.0;
END_IF;
</ST>
@@ -873,11 +874,11 @@
<configurations>
<configuration name="ConfigTest">
<resource name="ResourceTest">
- <task interval="01:00:00.100000" name="Toto" priority="6">
+ <task interval="00:00:00.010000" name="Toto" priority="6">
<pouInstance type="SFCTest" name="Program1"/>
</task>
<globalVars>
- <variable name="Titi" address="M30">
+ <variable name="Titi" address="%MW30">
<type>
<INT/>
</type>
@@ -885,19 +886,18 @@
</globalVars>
</resource>
<globalVars>
- <variable name="Toto" address="M10">
+ <variable name="Toto" address="%MW10">
<type>
<INT/>
</type>
</variable>
- <variable name="Tutu" address="M20">
+ <variable name="Tutu" address="%MX20">
<type>
<BOOL/>
</type>
</variable>
</globalVars>
</configuration>
- <configuration name="ConfigTest2"/>
</configurations>
</instances>
</project>
--- a/graphics/GraphicCommons.py Wed Jul 25 10:06:29 2007 +0200
+++ b/graphics/GraphicCommons.py Thu Jul 26 17:23:21 2007 +0200
@@ -401,6 +401,7 @@
movey = pos.y - self.oldPos.y
self.ProcessDragging(movex, movey)
self.RefreshModel()
+ self.Parent.RefreshBuffer()
self.SetSelected(True)
self.oldPos = None
@@ -1601,7 +1602,6 @@
if self.EndConnected:
self.UnConnectEndPoint()
self.MoveEndPoint(new_pos)
- self.RefreshModel()
# A segment has been handled, move a segment
elif handle_type == HANDLE_SEGMENT:
self.MoveSegment(handle[0], movex, movey)