--- a/ConfigTreeNode.py Wed Apr 24 18:34:00 2013 +0900
+++ b/ConfigTreeNode.py Wed Apr 24 17:37:46 2013 +0200
@@ -73,10 +73,12 @@
return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
- def CTNPath(self,CTNName=None):
+ def CTNPath(self,CTNName=None,project_path=None): - return os.path.join(self.CTNParent.CTNPath(),
+ project_path = self.CTNParent.CTNPath() + return os.path.join(project_path, CTNName + NameTypeSeparator + self.CTNType)
@@ -113,7 +115,7 @@
def RemoteExec(self, script, **kwargs):
return self.CTNParent.RemoteExec(script, **kwargs)
+ def OnCTNSave(self, from_project_path=None): #Default, do nothing and return success
@@ -155,7 +157,7 @@
- def CTNRequestSave(self):
+ def CTNRequestSave(self, from_project_path=None): if self.GetCTRoot().CheckProjectPathPerm(False):
# If confnode do not have corresponding directory
@@ -178,7 +180,7 @@
# Call the confnode specific OnCTNSave method
- result = self.OnCTNSave()
+ result = self.OnCTNSave(from_project_path) return _("Error while saving \"%s\"\n")%self.CTNPath()
@@ -186,7 +188,8 @@
self.ChangesToSave = False
# go through all children and do the same
for CTNChild in self.IterChildren():
- result = CTNChild.CTNRequestSave()
+ result = CTNChild.CTNRequestSave( + CTNChild.CTNPath(project_path=from_project_path)) --- a/ProjectController.py Wed Apr 24 18:34:00 2013 +0900
+++ b/ProjectController.py Wed Apr 24 17:37:46 2013 +0200
@@ -234,7 +234,9 @@
- def _getProjectFilesPath(self):
+ def _getProjectFilesPath(self, project_path=None): + if project_path is not None: + return os.path.join(project_path, "project_files") projectfiles_path = os.path.join(self.GetProjectPath(), "project_files")
if not os.path.exists(projectfiles_path):
os.mkdir(projectfiles_path)
@@ -348,14 +350,19 @@
+ def SaveProject(self, from_project_path=None): if self.CheckProjectPathPerm(False):
+ if from_project_path is not None: + old_projectfiles_path = self._getProjectFilesPath(from_project_path) + if os.path.isdir(old_projectfiles_path): + shutil.copytree(old_projectfiles_path, + self._getProjectFilesPath(self.ProjectPath)) self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
- result = self.CTNRequestSave()
+ result = self.CTNRequestSave(from_project_path) self.logger.write_error(result)
- def SaveProjectAs(self, dosave=True):
+ def SaveProjectAs(self): # Ask user to choose a path with write permissions
if wx.Platform == '__WXMSW__':
path = os.getenv("USERPROFILE")
@@ -367,9 +374,8 @@
newprojectpath = dirdialog.GetPath()
if os.path.isdir(newprojectpath):
- self.ProjectPath = newprojectpath
+ self.ProjectPath, old_project_path = newprojectpath, self.ProjectPath + self.SaveProject(old_project_path) self._setBuildPath(self.BuildPath)
--- a/c_ext/CFileEditor.py Wed Apr 24 18:34:00 2013 +0900
+++ b/c_ext/CFileEditor.py Wed Apr 24 17:37:46 2013 +0200
@@ -8,24 +8,7 @@
from controls import CustomGrid, CustomTable
from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
from util.BitmapLibrary import GetBitmap
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'other': 'Comic Sans MS',
- faces = { 'times': 'Times',
- 'other': 'new century schoolbook',
+from editors.TextViewer import GetCursorPos, faces def AppendMenu(parent, help, id, kind, text):
if wx.VERSION >= (2, 6, 0):
@@ -47,27 +30,6 @@
"typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
"void", "volatile", "wchar_t", "while"]
-def GetCursorPos(old, new):
- common_length = min(old_length, new_length)
- for i in xrange(common_length):
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- 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]:
class CppEditor(stc.StyledTextCtrl):
@@ -165,15 +127,15 @@
self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
- self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
- self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
- self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
- self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
+ 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) + self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE,size:%(size)d' % faces) + self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056,size:%(size)d' % faces) + self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff,size:%(size)d' % faces) + self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056,size:%(size)d' % faces) + self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold,size:%(size)d' % faces) + self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF,size:%(size)d' % faces) # register some images for use in the AutoComplete box.
#self.RegisterImage(1, images.getSmilesBitmap())
@@ -254,16 +216,19 @@
self.DisableEvents = True
old_cursor_pos = self.GetCurrentPos()
+ line = self.GetFirstVisibleLine() + column = self.GetXOffset() old_text = self.GetText()
new_text = self.Controler.GetPartText(self.Name)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.GotoPos(new_cursor_pos)
- self.GotoPos(old_cursor_pos)
+ if old_text != new_text: + new_cursor_pos = GetCursorPos(old_text, new_text) + self.LineScroll(column, line) + if new_cursor_pos != None: + self.GotoPos(new_cursor_pos) + self.GotoPos(old_cursor_pos) self.DisableEvents = False
--- a/c_ext/c_ext.py Wed Apr 24 18:34:00 2013 +0900
+++ b/c_ext/c_ext.py Wed Apr 24 17:37:46 2013 +0200
@@ -144,7 +144,7 @@
def CTNTestModified(self):
return self.ChangesToSave or not self.CFileIsSaved()
+ def OnCTNSave(self, from_project_path=None): filepath = self.CFileName()
text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
--- a/canfestival/canfestival.py Wed Apr 24 18:34:00 2013 +0900
+++ b/canfestival/canfestival.py Wed Apr 24 17:37:46 2013 +0200
@@ -1,4 +1,4 @@
base_folder = os.path.split(sys.path[0])[0]
CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
@@ -154,7 +154,7 @@
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):
@@ -378,8 +378,10 @@
def CTNTestModified(self):
return self.ChangesToSave or self.HasChanged()
+ def OnCTNSave(self, from_project_path=None): self.SetRoot(self.CTNPath())
+ shutil.copytree(self.GetEDSFolder(from_project_path), return self.SaveProject() is None
def CTNGenerate_C(self, buildpath, locations):
--- a/dialogs/FindInPouDialog.py Wed Apr 24 18:34:00 2013 +0900
+++ b/dialogs/FindInPouDialog.py Wed Apr 24 17:37:46 2013 +0200
@@ -109,7 +109,8 @@
self.ParentWindow = parent
self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
+ self.FindPattern.SetFocus() self.RefreshButtonsState()
def RefreshButtonsState(self):
--- a/editors/ConfTreeNodeEditor.py Wed Apr 24 18:34:00 2013 +0900
+++ b/editors/ConfTreeNodeEditor.py Wed Apr 24 17:37:46 2013 +0200
@@ -147,57 +147,22 @@
def _init_Editor(self, parent):
tabs_num = len(self.CONFNODEEDITOR_TABS)
+ if self.SHOW_PARAMS and len(self.Controler.GetParamsAttributes()) > 0:
+ if tabs_num > 1 or self.SHOW_BASE_PARAMS: self.Editor = wx.Panel(parent,
style=wx.SUNKEN_BORDER|wx.SP_3D)
- main_sizer = wx.BoxSizer(wx.VERTICAL)
- self.ConfNodeNoteBook = wx.Notebook(self.Editor)
- parent = self.ConfNodeNoteBook
- main_sizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW)
+ self.Editor.SetBackgroundColour(WINDOW_COLOUR) - self.Editor.SetSizer(main_sizer)
- self.ConfNodeNoteBook = None
- for title, create_func_name in self.CONFNODEEDITOR_TABS:
- editor = getattr(self, create_func_name)(parent)
- if self.ConfNodeNoteBook is not None:
- self.ConfNodeNoteBook.AddPage(editor, title)
- panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL
- if self.ConfNodeNoteBook is None:
- panel_style |= wx.SUNKEN_BORDER
- self.ParamsEditor = wx.ScrolledWindow(parent,
- self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR)
- self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize)
- self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
- # Variable allowing disabling of ParamsEditor scroll when Popup shown
- self.ScrollingEnabled = True
+ self.MainSizer = wx.BoxSizer(wx.VERTICAL) if self.SHOW_BASE_PARAMS:
- self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
- self.ParamsEditorSizer.AddGrowableCol(0)
- self.ParamsEditorSizer.AddGrowableRow(1)
- self.ParamsEditor.SetSizer(self.ParamsEditorSizer)
+ baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.MainSizer.AddSizer(baseparamseditor_sizer, border=5, - baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL)
- self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5,
- flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP)
- self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1)
+ self.FullIECChannel = wx.StaticText(self.Editor, -1) self.FullIECChannel.SetFont(
wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL,
wx.BOLD, faceName = faces["helv"]))
@@ -208,19 +173,19 @@
baseparamseditor_sizer.AddSizer(updownsizer, border=5,
flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
- self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.ParamsEditor,
+ self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.Editor, bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER)
self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1),
updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT)
- self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.ParamsEditor,
+ self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.Editor, bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER)
self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1),
updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT)
- self.ConfNodeName = wx.TextCtrl(self.ParamsEditor,
+ self.ConfNodeName = wx.TextCtrl(self.Editor, size=wx.Size(150, 25), style=wx.NO_BORDER)
self.ConfNodeName.SetFont(
wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL,
@@ -234,10 +199,46 @@
buttons_sizer = self.GenerateMethodButtonSizer()
baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER)
+ self.ConfNodeNoteBook = wx.Notebook(self.Editor) + parent = self.ConfNodeNoteBook + self.MainSizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW) - self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5)
- self.ParamsEditorSizer.AddGrowableCol(0)
- self.ParamsEditorSizer.AddGrowableRow(0)
+ self.ConfNodeNoteBook = None + self.Editor.SetSizer(self.MainSizer) + self.ConfNodeNoteBook = None + for title, create_func_name in self.CONFNODEEDITOR_TABS: + editor = getattr(self, create_func_name)(parent) + if self.ConfNodeNoteBook is not None: + self.ConfNodeNoteBook.AddPage(editor, title) + elif self.SHOW_BASE_PARAMS: + self.MainSizer.AddWindow(editor, 1, flag=wx.GROW) + if self.SHOW_PARAMS and len(self.Controler.GetParamsAttributes()) > 0: + panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL + if self.ConfNodeNoteBook is None and parent != self.Editor: + panel_style |= wx.SUNKEN_BORDER + self.ParamsEditor = wx.ScrolledWindow(parent, + self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR) + self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize) + self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) + # Variable allowing disabling of ParamsEditor scroll when Popup shown + self.ScrollingEnabled = True + self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5) + self.ParamsEditorSizer.AddGrowableCol(0) + self.ParamsEditorSizer.AddGrowableRow(0) + self.ParamsEditor.SetSizer(self.ParamsEditorSizer) self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL)
self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5,
@@ -247,6 +248,8 @@
if self.ConfNodeNoteBook is not None:
self.ConfNodeNoteBook.AddPage(self.ParamsEditor, _("Config"))
+ elif self.SHOW_BASE_PARAMS: + self.MainSizer.AddWindow(self.ParamsEditor, 1, flag=wx.GROW) self.Editor = self.ParamsEditor
@@ -287,10 +290,10 @@
EditorPanel.RefreshView(self)
+ if self.SHOW_BASE_PARAMS: + self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName()) + self.RefreshIECChannelControlsState() if self.ParamsEditor is not None:
- if self.SHOW_BASE_PARAMS:
- self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName())
- self.RefreshIECChannelControlsState()
self.RefreshConfNodeParamsSizer()
@@ -300,6 +303,7 @@
def RefreshIECChannelControlsState(self):
self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel())
self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0)
+ self.MainSizer.Layout() def RefreshConfNodeParamsSizer(self):
@@ -320,7 +324,7 @@
for confnode_method in self.Controler.ConfNodeMethods:
if "method" in confnode_method and confnode_method.get("shown",True):
- button = GenBitmapTextButton(self.ParamsEditor,
+ button = GenBitmapTextButton(self.Editor, bitmap=GetBitmap(confnode_method.get("bitmap", "Unknown")),
label=confnode_method["name"], style=wx.NO_BORDER)
button.SetFont(normal_bt_font)
--- a/editors/IECCodeViewer.py Wed Apr 24 18:34:00 2013 +0900
+++ b/editors/IECCodeViewer.py Wed Apr 24 17:37:46 2013 +0200
@@ -1,9 +1,13 @@
from editors.TextViewer import TextViewer
+from plcopen.plcopen import TestTextElement class IECCodeViewer(TextViewer):
if getattr(self, "_OnClose"):
\ No newline at end of file
+ def Search(self, criteria): + return [((self.TagName, "body", 0),) + result for result in TestTextElement(self.Editor.GetText(), criteria)] \ No newline at end of file
--- a/editors/ProjectNodeEditor.py Wed Apr 24 18:34:00 2013 +0900
+++ b/editors/ProjectNodeEditor.py Wed Apr 24 17:37:46 2013 +0200
@@ -33,12 +33,10 @@
ConfTreeNodeEditor.__init__(self, parent, controler, window, tagname)
- if self.SHOW_BASE_PARAMS:
- buttons_sizer = self.GenerateMethodButtonSizer()
- self.ParamsEditorSizer.InsertSizer(0, buttons_sizer, 0, border=5,
- flag=wx.LEFT|wx.RIGHT|wx.TOP)
- self.ParamsEditorSizer.Layout()
+ buttons_sizer = self.GenerateMethodButtonSizer() + self.MainSizer.InsertSizer(0, buttons_sizer, 0, border=5, flag=wx.ALL) + self.MainSizer.Layout() self.VariableEditor = self.VariableEditorPanel
--- a/editors/TextViewer.py Wed Apr 24 18:34:00 2013 +0900
+++ b/editors/TextViewer.py Wed Apr 24 17:37:46 2013 +0200
@@ -80,6 +80,8 @@
def GetCursorPos(old, new):
common_length = min(old_length, new_length)
@@ -445,17 +447,20 @@
self.DisableEvents = True
old_cursor_pos = self.GetCurrentPos()
+ line = self.Editor.GetFirstVisibleLine() + column = self.Editor.GetXOffset() old_text = self.GetText()
new_text = self.Controler.GetEditedElementText(self.TagName, self.Debug)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.Editor.GotoPos(new_cursor_pos)
- self.Editor.GotoPos(old_cursor_pos)
- self.Editor.ScrollToColumn(0)
- self.Editor.EmptyUndoBuffer()
+ if old_text != new_text: + new_cursor_pos = GetCursorPos(old_text, new_text) + self.Editor.LineScroll(column, line) + if new_cursor_pos != None: + self.Editor.GotoPos(new_cursor_pos) + self.Editor.GotoPos(old_cursor_pos) + self.Editor.EmptyUndoBuffer() self.DisableEvents = False
self.RefreshVariableTree()
@@ -764,6 +769,9 @@
+ def Search(self, criteria): + return self.Controler.SearchInPou(self.TagName, criteria, self.Debug) def Find(self, direction, search_params):
if self.SearchParams != search_params:
self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
@@ -779,7 +787,8 @@
(infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
for infos, start, end, text in
- self.Controler.SearchInPou(self.TagName, criteria, self.Debug)]
+ self.CurrentFindHighlight = None if len(self.SearchResults) > 0:
if self.CurrentFindHighlight is not None:
@@ -801,6 +810,8 @@
self.RemoveHighlight(*self.CurrentFindHighlight)
self.CurrentFindHighlight = None
+ print self.CurrentFindHighlight self.Controler.SetEditedElementText(self.TagName, self.GetText())
--- a/editors/Viewer.py Wed Apr 24 18:34:00 2013 +0900
+++ b/editors/Viewer.py Wed Apr 24 17:37:46 2013 +0200
@@ -3167,6 +3167,7 @@
blocks.append((block, (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)))
self.SearchResults.extend([infos for block, infos in blocks])
+ self.CurrentFindHighlight = None if len(self.SearchResults) > 0:
if self.CurrentFindHighlight is not None:
--- a/graphics/FBD_Objects.py Wed Apr 24 18:34:00 2013 +0900
+++ b/graphics/FBD_Objects.py Wed Apr 24 17:37:46 2013 +0200
@@ -263,43 +263,49 @@
self.Pen = MiterPen(self.Colour)
# Extract the inputs properties and create or modify the corresponding connector
- for idx, (input_name, input_type, input_modifier) in enumerate(inputs):
- if idx < len(self.Inputs):
- connector = self.Inputs[idx]
- connector.SetName(input_name)
- connector.SetType(input_type)
- connector = Connector(self, input_name, input_type, wx.Point(0, 0), WEST, onlyone = True)
- self.Inputs.append(connector)
+ for input_name, input_type, input_modifier in inputs: + connector = Connector(self, input_name, input_type, wx.Point(0, 0), WEST, onlyone = True) if input_modifier == "negated":
connector.SetNegated(True)
elif input_modifier != "none":
connector.SetEdge(input_modifier)
- for i in xrange(idx + 1, len(self.Inputs)):
- self.Inputs[i].UnConnect(delete = True)
- self.Inputs = self.Inputs[:idx + 1]
+ for input in self.Inputs: + if input.GetName() == input_name: + wires = input.GetWires()[:] + connector.Connect(wire) + input_connectors.append(connector) + for input in self.Inputs: + input.UnConnect(delete = True) + self.Inputs = input_connectors # Extract the outputs properties and create or modify the corresponding connector
- for idx, (output_name, output_type, output_modifier) in enumerate(outputs):
- if idx < len(self.Outputs):
- connector = self.Outputs[idx]
- connector.SetName(output_name)
- connector.SetType(output_type)
- connector = Connector(self, output_name, output_type, wx.Point(0, 0), EAST)
- self.Outputs.append(connector)
+ for output_name, output_type, output_modifier in outputs: + connector = Connector(self, output_name, output_type, wx.Point(0, 0), EAST) if output_modifier == "negated":
connector.SetNegated(True)
elif output_modifier != "none":
connector.SetEdge(output_modifier)
- for i in xrange(idx + 1, len(self.Outputs)):
- self.Outputs[i].UnConnect(delete = True)
- self.Outputs = self.Outputs[:idx + 1]
+ for output in self.Outputs: + if output.GetName() == output_name: + wires = output.GetWires()[:] + connector.Connect(wire) + output_connectors.append(connector) + for output in self.Outputs: + output.UnConnect(delete = True) + self.Outputs = output_connectors + for output in self.Outputs: self.RefreshBoundingBox()
--- a/graphics/GraphicCommons.py Wed Apr 24 18:34:00 2013 +0900
+++ b/graphics/GraphicCommons.py Wed Apr 24 17:37:46 2013 +0200
@@ -1695,6 +1695,10 @@
def InsertConnect(self, idx, wire, refresh = True):
if wire not in self.Wires:
self.Wires.insert(idx, wire)
+ wire[0].ConnectStartPoint(None, self) + wire[0].ConnectEndPoint(None, self) self.ParentBlock.RefreshModel(False)
--- a/py_ext/PythonEditor.py Wed Apr 24 18:34:00 2013 +0900
+++ b/py_ext/PythonEditor.py Wed Apr 24 17:37:46 2013 +0200
@@ -1,59 +1,25 @@
-from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'other': 'Comic Sans MS',
-elif wx.Platform == '__WXMAC__':
- faces = { 'times': 'Times New Roman',
- 'other': 'Comic Sans MS',
- faces = { 'times': 'Times',
- 'other': 'new century schoolbook',
+from plcopen.plcopen import TestTextElement +from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD +from editors.ConfTreeNodeEditor import ConfTreeNodeEditor +from editors.TextViewer import GetCursorPos, faces +[STC_PYTHON_ERROR, STC_PYTHON_SEARCH_RESULT] = range(15, 17) + ERROR_HIGHLIGHT: STC_PYTHON_ERROR, + SEARCH_RESULT_HIGHLIGHT: STC_PYTHON_SEARCH_RESULT, ] = [wx.NewId() for _init_ctrls in range(1)]
-def GetCursorPos(old, new):
- common_length = min(old_length, new_length)
- for i in xrange(common_length):
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- 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]:
class PythonEditor(ConfTreeNodeEditor):
@@ -136,7 +102,7 @@
self.PythonCodeEditor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
self.PythonCodeEditor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
self.PythonCodeEditor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
if wx.Platform == '__WXMSW__':
self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
@@ -155,39 +121,43 @@
# The rest remains unchanged.
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_INDENTGUIDE, 'fore:#CDCDCD,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_DEFAULT, 'fore:#000000,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0,size:%(size)d' % faces) + self.PythonCodeEditor.StyleSetSpec(stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_NUMBER, 'fore:#008080,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_STRING, 'fore:#800080,size:%(size)d' % faces) + self.PythonCodeEditor.StyleSetSpec(stc.STC_P_CHARACTER, 'fore:#800080,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_WORD, 'fore:#000080,bold,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA,size:%(size)d' % faces) + self.PythonCodeEditor.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_CLASSNAME, 'fore:#0000FF,bold,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_DEFNAME, 'fore:#008080,bold,size:%(size)d' % faces) - self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_OPERATOR, 'fore:#800000,bold,size:%(size)d' % faces) # Identifiers. I leave this as not bold because everything seems
# to be an identifier if it doesn't match the above criterae
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_IDENTIFIER, 'fore:#000000,size:%(size)d' % faces) + self.PythonCodeEditor.StyleSetSpec(STC_PYTHON_ERROR, 'fore:#FF0000,back:#FFFF00,size:%(size)d' % faces) + self.PythonCodeEditor.StyleSetSpec(STC_PYTHON_SEARCH_RESULT, 'fore:#FFFFFF,back:#FFA500,size:%(size)d' % faces) self.PythonCodeEditor.SetCaretForeground("BLUE")
@@ -219,13 +189,13 @@
# EOL: Since we are loading/saving ourselves, and the
# strings will always have \n's in them, set the STC to
- self.PythonCodeEditor.SetEOLMode(wx.stc.STC_EOL_LF)
+ self.PythonCodeEditor.SetEOLMode(stc.STC_EOL_LF) self.PythonCodeEditor.SetViewEOL(False)
# No right-edge mode indicator
self.PythonCodeEditor.SetEdgeMode(stc.STC_EDGE_NONE)
- self.PythonCodeEditor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
+ self.PythonCodeEditor.SetModEventMask(stc.STC_MOD_BEFOREINSERT|stc.STC_MOD_BEFOREDELETE) self.PythonCodeEditor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
self.PythonCodeEditor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
@@ -239,6 +209,14 @@
self.DisableEvents = False
self.CurrentAction = None
+ self.SearchParams = None + self.SearchResults = None + self.CurrentFindHighlight = None + self.RefreshHighlightsTimer = wx.Timer(self, -1) + self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer) def GetBufferState(self):
return self.Controler.GetBufferState()
@@ -305,19 +283,24 @@
self.DisableEvents = True
old_cursor_pos = self.PythonCodeEditor.GetCurrentPos()
+ line = self.PythonCodeEditor.GetFirstVisibleLine() + column = self.PythonCodeEditor.GetXOffset() old_text = self.PythonCodeEditor.GetText()
new_text = self.Controler.GetPythonCode()
- self.PythonCodeEditor.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.PythonCodeEditor.GotoPos(new_cursor_pos)
- self.PythonCodeEditor.GotoPos(old_cursor_pos)
- self.PythonCodeEditor.ScrollToColumn(0)
- self.PythonCodeEditor.EmptyUndoBuffer()
+ if old_text != new_text: + self.PythonCodeEditor.SetText(new_text) + new_cursor_pos = GetCursorPos(old_text, new_text) + self.PythonCodeEditor.LineScroll(column, line) + if new_cursor_pos != None: + self.PythonCodeEditor.GotoPos(new_cursor_pos) + self.PythonCodeEditor.GotoPos(old_cursor_pos) + self.PythonCodeEditor.EmptyUndoBuffer() self.DisableEvents = False
self.PythonCodeEditor.Colourise(0, -1)
self.Controler.SetPythonCode(self.PythonCodeEditor.GetText())
@@ -338,7 +321,7 @@
self.PythonCodeEditor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
def OnKillFocus(self, event):
self.PythonCodeEditor.AutoCompCancel()
@@ -483,3 +466,89 @@
self.DisableEvents = False
+ def Find(self, direction, search_params): + if self.SearchParams != search_params: + self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) + self.SearchParams = search_params + "raw_pattern": search_params["find_pattern"], + "pattern": re.compile(search_params["find_pattern"]), + "case_sensitive": search_params["case_sensitive"], + "regular_expression": search_params["regular_expression"], + (start, end, SEARCH_RESULT_HIGHLIGHT) + for start, end, text in + TestTextElement(self.PythonCodeEditor.GetText(), criteria)] + self.CurrentFindHighlight = None + if len(self.SearchResults) > 0: + if self.CurrentFindHighlight is not None: + old_idx = self.SearchResults.index(self.CurrentFindHighlight) + if self.SearchParams["wrap"]: + idx = (old_idx + direction) % len(self.SearchResults) + idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1)) + self.RemoveHighlight(*self.CurrentFindHighlight) + self.CurrentFindHighlight = self.SearchResults[idx] + self.AddHighlight(*self.CurrentFindHighlight) + self.CurrentFindHighlight = self.SearchResults[0] + self.AddHighlight(*self.CurrentFindHighlight) + if self.CurrentFindHighlight is not None: + self.RemoveHighlight(*self.CurrentFindHighlight) + self.CurrentFindHighlight = None +#------------------------------------------------------------------------------- +# Highlights showing functions +#------------------------------------------------------------------------------- + def OnRefreshHighlightsTimer(self, event): + def ClearHighlights(self, highlight_type=None): + if highlight_type is None: + highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) + if highlight_type is not None: + self.Highlights = [(start, end, highlight) for (start, end, highlight) in self.Highlights if highlight != highlight_type] + def AddHighlight(self, start, end, highlight_type): + highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) + if highlight_type is not None: + self.Highlights.append((start, end, highlight_type)) + self.PythonCodeEditor.GotoPos(self.PythonCodeEditor.PositionFromLine(start[0]) + start[1]) + self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) + def RemoveHighlight(self, start, end, highlight_type): + highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) + if (highlight_type is not None and + (start, end, highlight_type) in self.Highlights): + self.Highlights.remove((start, end, highlight_type)) + self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) + def ShowHighlights(self): + for start, end, highlight_type in self.Highlights: + highlight_start_pos = start[1] + highlight_start_pos = self.PythonCodeEditor.GetLineEndPosition(start[0] - 1) + start[1] + 1 + highlight_end_pos = end[1] - indent + 1 + highlight_end_pos = self.PythonCodeEditor.GetLineEndPosition(end[0] - 1) + end[1] + 2 + self.PythonCodeEditor.StartStyling(highlight_start_pos, 0xff) + self.PythonCodeEditor.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type) + self.PythonCodeEditor.StartStyling(highlight_start_pos, 0x00) + self.PythonCodeEditor.SetStyling(len(self.PythonCodeEditor.GetText()) - highlight_end_pos, stc.STC_STYLE_DEFAULT) --- a/py_ext/PythonFileCTNMixin.py Wed Apr 24 18:34:00 2013 +0900
+++ b/py_ext/PythonFileCTNMixin.py Wed Apr 24 17:37:46 2013 +0200
@@ -48,7 +48,7 @@
def CTNTestModified(self):
return self.ChangesToSave or not self.PythonIsSaved()
+ def OnCTNSave(self, from_project_path=None): filepath = self.PythonFileName()
text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
--- a/svgui/svgui.py Wed Apr 24 18:34:00 2013 +0900
+++ b/svgui/svgui.py Wed Apr 24 17:37:46 2013 +0200
@@ -5,12 +5,13 @@
from POULibrary import POULibrary
from docutil import open_svg
+from py_ext import PythonFileCTNMixin class SVGUILibrary(POULibrary):
def GetLibraryPath(self):
return os.path.join(os.path.split(__file__)[0], "pous.xml")
+class SVGUI(PythonFileCTNMixin): @@ -26,13 +27,21 @@
return os.path.join(os.path.dirname(__file__))
- # define name for IEC raw code file
- return os.path.join(self.CTNPath(), "gui.svg")
+ def _getSVGpath(self, project_path=None): + if project_path is None: + project_path = self.CTNPath() + # define name for SVG file containing gui layout + return os.path.join(project_path, "gui.svg") def _getSVGUIserverpath(self):
return os.path.join(os.path.dirname(__file__), "svgui_server.py")
+ def OnCTNSave(self, from_project_path=None): + if from_project_path is not None: + shutil.copyfile(self._getSVGpath(from_project_path), + return PythonFileCTNMixin.OnCTNSave(self, from_project_path) def CTNGenerate_C(self, buildpath, locations):
Return C code generated by iec2c compiler
--- a/wxglade_hmi/wxglade_hmi.py Wed Apr 24 18:34:00 2013 +0900
+++ b/wxglade_hmi/wxglade_hmi.py Wed Apr 24 17:37:46 2013 +0200
@@ -1,5 +1,5 @@
from xml.dom import minidom
from py_ext import PythonFileCTNMixin
@@ -16,9 +16,11 @@
return os.path.join(os.path.dirname(__file__))
- def _getWXGLADEpath(self):
- # define name for IEC raw code file
- return os.path.join(self.CTNPath(), "hmi.wxg")
+ def _getWXGLADEpath(self, project_path=None): + if project_path is None: + project_path = self.CTNPath() + # define name for wxGlade gui file + return os.path.join(project_path, "hmi.wxg") def launch_wxglade(self, options, wait=False):
from wxglade import __file__ as fileName
@@ -29,6 +31,11 @@
mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)
+ def OnCTNSave(self, from_project_path=None): + if from_project_path is not None: + shutil.copyfile(self._getWXGLADEpath(from_project_path), + self._getWXGLADEpath()) + return PythonFileCTNMixin.OnCTNSave(self, from_project_path) def CTNGenerate_C(self, buildpath, locations):
@@ -128,3 +135,4 @@
if wx.Platform == '__WXMSW__':
wxg_filename = "\"%s\""%wxg_filename
self.launch_wxglade([wxg_filename])