--- a/Beremiz.py Wed Apr 24 18:34:00 2013 +0900
+++ b/Beremiz.py Wed Apr 24 17:37:46 2013 +0200
@@ -980,7 +980,6 @@
self.CTR.SaveProjectAs()
self.RefreshAll()
self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
- event.Skip()
def OnQuitMenu(self, event):
self.Close()
--- 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 @@
def ConfNodePath(self):
return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType)
- def CTNPath(self,CTNName=None):
+ def CTNPath(self,CTNName=None,project_path=None):
if not CTNName:
CTNName = self.CTNName()
- return os.path.join(self.CTNParent.CTNPath(),
+ if not project_path:
+ project_path = self.CTNParent.CTNPath()
+ return os.path.join(project_path,
CTNName + NameTypeSeparator + self.CTNType)
def CTNName(self):
@@ -113,7 +115,7 @@
def RemoteExec(self, script, **kwargs):
return self.CTNParent.RemoteExec(script, **kwargs)
- def OnCTNSave(self):
+ def OnCTNSave(self, from_project_path=None):
#Default, do nothing and return success
return True
@@ -155,7 +157,7 @@
def CTNMakeDir(self):
os.mkdir(self.CTNPath())
- def CTNRequestSave(self):
+ def CTNRequestSave(self, from_project_path=None):
if self.GetCTRoot().CheckProjectPathPerm(False):
# If confnode do not have corresponding directory
ctnpath = self.CTNPath()
@@ -178,7 +180,7 @@
XMLFile.close()
# Call the confnode specific OnCTNSave method
- result = self.OnCTNSave()
+ result = self.OnCTNSave(from_project_path)
if not result:
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))
if result:
return result
return None
--- 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 @@
return True
return False
- 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 @@
self.ClearChildren()
self.ResetAppFrame(None)
- def SaveProject(self):
+ 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)
if result:
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 @@
if answer == wx.ID_OK:
newprojectpath = dirdialog.GetPath()
if os.path.isdir(newprojectpath):
- self.ProjectPath = newprojectpath
- if dosave:
- self.SaveProject()
+ self.ProjectPath, old_project_path = newprojectpath, self.ProjectPath
+ self.SaveProject(old_project_path)
self._setBuildPath(self.BuildPath)
return True
return False
--- 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',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 10,
- 'size2': 8,
- }
-else:
- faces = { 'times': 'Times',
- 'mono' : 'Courier',
- 'helv' : 'Helvetica',
- 'other': 'new century schoolbook',
- 'size' : 12,
- 'size2': 10,
- }
-
+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):
- 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 CppEditor(stc.StyledTextCtrl):
fold_symbols = 3
@@ -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.ResetBuffer()
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)
self.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.GotoPos(new_cursor_pos)
- else:
- self.GotoPos(old_cursor_pos)
- self.ScrollToColumn(0)
- self.EmptyUndoBuffer()
+ 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)
+ else:
+ self.GotoPos(old_cursor_pos)
+ self.EmptyUndoBuffer()
self.DisableEvents = False
self.Colourise(0, -1)
--- 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):
+ 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 @@
-import os, sys
+import os, sys, shutil
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):
+ 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):
+ def OnCTNSave(self, from_project_path=None):
self.SetRoot(self.CTNPath())
+ shutil.copytree(self.GetEDSFolder(from_project_path),
+ self.GetEDSFolder())
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:
+ if self.SHOW_PARAMS and len(self.Controler.GetParamsAttributes()) > 0:
tabs_num += 1
- if tabs_num > 1:
+ 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.SetSizer(main_sizer)
- else:
- self.ConfNodeNoteBook = None
- self.Editor = 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)
- else:
- self.Editor = editor
-
- if self.SHOW_PARAMS:
-
- panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL
- if self.ConfNodeNoteBook is None:
- panel_style |= wx.SUNKEN_BORDER
- self.ParamsEditor = wx.ScrolledWindow(parent,
- style=panel_style)
- 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.Editor.SetBackgroundColour(WINDOW_COLOUR)
+
+ 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.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5,
- flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP)
-
- self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1)
+ self.MainSizer.AddSizer(baseparamseditor_sizer, border=5,
+ flag=wx.GROW|wx.ALL)
+
+ 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),
self.IECCUpButton)
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),
self.IECCDownButton)
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)
+ if tabs_num > 1:
+ self.ConfNodeNoteBook = wx.Notebook(self.Editor)
+ parent = self.ConfNodeNoteBook
+ self.MainSizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW)
else:
- self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5)
- self.ParamsEditorSizer.AddGrowableCol(0)
- self.ParamsEditorSizer.AddGrowableRow(0)
+ parent = self.Editor
+ self.ConfNodeNoteBook = None
+
+ self.Editor.SetSizer(self.MainSizer)
+ else:
+ self.ConfNodeNoteBook = None
+ self.Editor = 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)
+ else:
+ self.Editor = editor
+
+ 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,
+ style=panel_style)
+ 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)
else:
self.Editor = self.ParamsEditor
else:
@@ -287,10 +290,10 @@
def RefreshView(self):
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()
self.RefreshScrollbars()
@@ -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):
self.Freeze()
@@ -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):
def __del__(self):
TextViewer.__del__(self)
if getattr(self, "_OnClose"):
- self._OnClose(self)
\ No newline at end of file
+ self._OnClose(self)
+
+ 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
def GetTagName(self):
--- 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):
+ if old == "":
+ return 0
old_length = len(old)
new_length = len(new)
common_length = min(old_length, new_length)
@@ -445,17 +447,20 @@
self.ResetBuffer()
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)
- self.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.Editor.GotoPos(new_cursor_pos)
- else:
- self.Editor.GotoPos(old_cursor_pos)
- self.Editor.ScrollToColumn(0)
- self.RefreshJumpList()
- self.Editor.EmptyUndoBuffer()
+ if old_text != new_text:
+ self.SetText(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)
+ else:
+ self.Editor.GotoPos(old_cursor_pos)
+ self.RefreshJumpList()
+ self.Editor.EmptyUndoBuffer()
self.DisableEvents = False
self.RefreshVariableTree()
@@ -764,6 +769,9 @@
self.RefreshModel()
self.RefreshBuffer()
+ 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 @@
self.SearchResults = [
(infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
for infos, start, end, text in
- self.Controler.SearchInPou(self.TagName, criteria, self.Debug)]
+ self.Search(criteria)]
+ 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
+
def RefreshModel(self):
self.RefreshJumpList()
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)))
blocks.sort(sort_blocks)
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
- idx = 0
- 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)
- else:
- connector = Connector(self, input_name, input_type, wx.Point(0, 0), WEST, onlyone = True)
- self.Inputs.append(connector)
+ input_connectors = []
+ 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()[:]
+ input.UnConnect()
+ for wire in wires:
+ connector.Connect(wire)
+ break
+ 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
- idx = 0
- 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)
- else:
- connector = Connector(self, output_name, output_type, wx.Point(0, 0), EAST)
- self.Outputs.append(connector)
+ output_connectors = []
+ 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()[:]
+ output.UnConnect()
+ for wire in wires:
+ connector.Connect(wire)
+ break
+ output_connectors.append(connector)
+ for output in self.Outputs:
+ output.UnConnect(delete = True)
+ self.Outputs = output_connectors
self.RefreshMinSize()
self.RefreshConnectors()
+ for output in self.Outputs:
+ output.RefreshWires()
self.RefreshBoundingBox()
# Returns the block type
--- 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)
+ if wire[1] == 0:
+ wire[0].ConnectStartPoint(None, self)
+ else:
+ wire[0].ConnectEndPoint(None, self)
if refresh:
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 @@
+import re
+import keyword
+
import wx
import wx.grid
-import wx.stc as stc
-import keyword
-
+import wx.stc as stc
+
+from plcopen.plcopen import TestTextElement
+from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
-
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 10,
- 'size2': 8,
- }
-elif wx.Platform == '__WXMAC__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Monaco',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 12,
- 'size2': 10,
- }
-else:
- faces = { 'times': 'Times',
- 'mono' : 'Courier',
- 'helv' : 'Helvetica',
- 'other': 'new century schoolbook',
- 'size' : 12,
- 'size2': 10,
- }
+from editors.TextViewer import GetCursorPos, faces
+
+[STC_PYTHON_ERROR, STC_PYTHON_SEARCH_RESULT] = range(15, 17)
+
+HIGHLIGHT_TYPES = {
+ ERROR_HIGHLIGHT: STC_PYTHON_ERROR,
+ SEARCH_RESULT_HIGHLIGHT: STC_PYTHON_SEARCH_RESULT,
+}
[ID_PYTHONEDITOR,
] = [wx.NewId() for _init_ctrls in range(1)]
-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 PythonEditor(ConfTreeNodeEditor):
fold_symbols = 3
@@ -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)
-
+
# Global default style
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.
# Line numbers in margin
- 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)
# Highlighted brace
- 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)
# Unmatched brace
- 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)
# Indentation guide
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_STYLE_INDENTGUIDE, 'fore:#CDCDCD,size:%(size)d' % faces)
# Python styles
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_DEFAULT, 'fore:#000000,size:%(size)d' % faces)
# Comments
- 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)
# Numbers
- self.PythonCodeEditor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
+ self.PythonCodeEditor.StyleSetSpec(stc.STC_P_NUMBER, 'fore:#008080,size:%(size)d' % faces)
# Strings and characters
- 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)
# Keywords
- 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)
# Triple quotes
- 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)
# Class names
- 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)
# Function names
- 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)
# Operators
- 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)
+
+ # Highlighting styles
+ 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)
+
# Caret color
self.PythonCodeEditor.SetCaretForeground("BLUE")
# Selection background
@@ -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
# edit them that way.
- 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.Highlights = []
+ 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.ResetBuffer()
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)
- else:
- 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)
+ else:
+ self.PythonCodeEditor.GotoPos(old_cursor_pos)
+ self.PythonCodeEditor.EmptyUndoBuffer()
self.DisableEvents = False
self.PythonCodeEditor.Colourise(0, -1)
+
+ self.ShowHighlights()
def RefreshModel(self):
self.Controler.SetPythonCode(self.PythonCodeEditor.GetText())
@@ -338,7 +321,7 @@
self.PythonCodeEditor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
else:
event.Skip()
-
+
def OnKillFocus(self, event):
self.PythonCodeEditor.AutoCompCancel()
event.Skip()
@@ -483,3 +466,89 @@
self.DisableEvents = False
self.RefreshModel()
self.RefreshBuffer()
+
+ def Find(self, direction, search_params):
+ if self.SearchParams != search_params:
+ self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
+
+ self.SearchParams = search_params
+ criteria = {
+ "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"],
+ "filter": "all"}
+
+ self.SearchResults = [
+ (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)
+ else:
+ idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1))
+ if idx != old_idx:
+ self.RemoveHighlight(*self.CurrentFindHighlight)
+ self.CurrentFindHighlight = self.SearchResults[idx]
+ self.AddHighlight(*self.CurrentFindHighlight)
+ else:
+ self.CurrentFindHighlight = self.SearchResults[0]
+ self.AddHighlight(*self.CurrentFindHighlight)
+
+ else:
+ if self.CurrentFindHighlight is not None:
+ self.RemoveHighlight(*self.CurrentFindHighlight)
+ self.CurrentFindHighlight = None
+
+#-------------------------------------------------------------------------------
+# Highlights showing functions
+#-------------------------------------------------------------------------------
+
+ def OnRefreshHighlightsTimer(self, event):
+ self.RefreshView()
+ event.Skip()
+
+ def ClearHighlights(self, highlight_type=None):
+ if highlight_type is None:
+ self.Highlights = []
+ else:
+ 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]
+ self.RefreshView()
+
+ 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)
+ self.RefreshView()
+
+ 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:
+ if start[0] == 0:
+ highlight_start_pos = start[1]
+ else:
+ highlight_start_pos = self.PythonCodeEditor.GetLineEndPosition(start[0] - 1) + start[1] + 1
+ if end[0] == 0:
+ highlight_end_pos = end[1] - indent + 1
+ else:
+ 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):
+ 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:
+class SVGUI(PythonFileCTNMixin):
ConfNodeMethods = [
{"bitmap" : "ImportSVG",
@@ -26,13 +27,21 @@
def ConfNodePath(self):
return os.path.join(os.path.dirname(__file__))
- def _getSVGpath(self):
- # 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),
+ self._getSVGpath())
+ 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 @@
import wx
-import os, sys
+import os, sys, shutil
from xml.dom import minidom
from py_ext import PythonFileCTNMixin
@@ -16,9 +16,11 @@
def ConfNodePath(self):
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])
+