# On Windows install schema, we compute path to beremiz
# relative to path to python folder (sys.path[0] in that case)
# note: beware that wx import messes up sys.path[0]
_dist_folder = os.path.split(sys.path[0])[0]
_beremiz_folder = os.path.join(_dist_folder, "beremiz")
# Then we add it to sys.path, to make "import Beremiz" possible
sys.path.append(_beremiz_folder)
from util.BitmapLibrary import AddBitmapFolder
# Path of directory containing current python file
_lpcmanager_path = os.path.split(__file__)[0]
PLC_GOT_module = ['GOT', 'GOT_111', 'GOT_131']
PLC_module = PLC_MC9_module + PLC_GOT_module
# XXX get ride of global arch
class LPCManagerLauncher(BeremizIDELauncher):
BeremizIDELauncher.__init__(self)
self.extensions = [os.path.join(_lpcmanager_path, "extention.py")]
print("\nUsage of LPCManager.py :")
print("\n %s Projectpath Buildpath port arch\n" % sys.argv[0])
def ProcessCommandLineArgs(self):
# Command line arguments parsing
opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
except getopt.GetoptError:
# print help information and exit:
# asking for help causes exit
if o in ("-h", "--help"):
self.projectOpen = args[0]
# overload with exacltly same code, but this is intended.
# we want extensions to use globals of this module, not Beremiz.py
CMDpipe = self.StdoutPseudoFile.StdoutPseudoFile(self.port)
if self.projectOpen is not None:
self.projectOpen = self.BeremizIDE.DecodeFileSystemPath(self.projectOpen, False)
CTR = self.LPCProjectController.LPCProjectController(
None, CMDpipe, self.buildpath)
if self.projectOpen is not None and os.path.isdir(self.projectOpen):
result = CTR.LoadProject(self.projectOpen)
CMDpipe.write("Error: Invalid project directory", result)
CMDpipe.write("Error: No such file or directory")
lpcberemiz_cmd = LPCCommand(CTR, CMDpipe)
cmd_thread = Thread(target=lpcberemiz_cmd.cmdloop)
# TODO: join() when exiting
self.frame = self.LPCBeremiz.LPCBeremiz(None, ctr=CTR)
# the "Show" command from composer does it instead
def CreateApplication(self):
# BEREMIZ_DEBUG file detection in beremiz isn't enough (module scope)
# here we set BMZ_DBG interpreter-wise, so that submodules can use it.
__builtin__.__dict__["BMZ_DBG"] = os.path.exists("LPC_DEBUG")
BeremizIDELauncher.CreateApplication(self)
# Add LPCmanager's image folder to searched ones.
AddBitmapFolder(os.path.join(_lpcmanager_path, "images"))
from LPCconnector import LPC_connector_factory
from LPCconnector.PYRO import MW_PYRO_connector_factory
from LPCconnector.WAMP import MWWAMP_connector_factory
from LPCtarget import LPC_target
targets.targets["LPC"] = {"xsd": os.path.join(_lpcmanager_path, "LPCtarget", "XSD"),
"class": lambda: LPC_target,
"code": {os.path.join(_lpcmanager_path, "LPCtarget", "plc_LPC_main.c")}}
targets.toolchains["makefile"] = os.path.join(_lpcmanager_path, "LPCtarget", "XSD_toolchain_makefile")
targets.targets["MC9"] = {"xsd": os.path.join(_lpcmanager_path, "MC9target", "XSD"),
"class": targets.targets["Xenomai"]["class"],
"code": {"plc_MC9_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"],
"plc_MC9_main_retain.c": os.path.join(_lpcmanager_path,
"MC9target", "plc_MC9_main_retain.c")}}
from ProjectController import ProjectController
from ConfigTreeNode import ConfigTreeNode
from editors.ProjectNodeEditor import ProjectNodeEditor
from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
from editors.CodeFileEditor import VariablesTable
from editors.CodeFileEditor import VariablesEditor
from editors.CodeFileEditor import CodeEditor
from controls import ProjectPropertiesPanel
from controls.SearchResultPanel import SearchResultPanel
# from controls.LogViewer import LogViewer
from WampOptionsEditor import WampOptionsEditor
from VariableExporter import VariableWriter
from PLCControler import PLCControler, ITEMS_UNEDITABLE, ITEM_POU
from wx.lib.scrolledpanel import ScrolledPanel
from types import MethodType
from IDEFrame import IDEFrame
from dialogs import SearchInProjectDialog
from controls import TextCtrlAutoComplete
from py_ext import PythonFileCTNMixin
from plcopen.structures import TestIdentifier, IDENTIFIER_MODEL
def CTNGenerate_C(self, buildpath, locations):
# location string for that CTN
location_str = "_".join(map(lambda x: str(x),
self.GetCurrentLocation()))
configname = self.GetCTRoot().GetProjectConfigNames()[0]
pyextname = self.CTNName()
varinfos = map(lambda variable: {
"name": variable.getname(),
"desc": repr(variable.getdesc()),
"onchangecode": '"' + variable.getonchange() + \
"('" + variable.getname() + "')\"" \
if variable.getonchange() else '""',
"onchange": repr(variable.getonchange()) \
if variable.getonchange() else None,
"opts": repr(variable.getopts()),
"configname": configname.upper(),
"uppername": variable.getname().upper(),
"IECtype": variable.gettype(),
"initial": repr(variable.getinitial()),
self.CodeFile.variables.variable)
# python side PLC global variables access stub
globalstubs = "\n".join(["""\
_%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\
TypeTranslator["%(IECtype)s"]
_PySafeGetPLCGlob_%(name)s = PLCBinary.__SafeGetPLCGlob_%(name)s
_PySafeGetPLCGlob_%(name)s.restype = None
_PySafeGetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
_PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s
_PySafeSetPLCGlob_%(name)s.restype = None
_PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
_%(pyextname)sGlobalsDesc.append((
for varinfo in varinfos])
# Runtime calls (start, stop, init, and cleanup)
for section in self.SECTIONS_NAMES:
rtcalls += "def _runtime_%s_%s():\n" % (location_str, section)
sectiontext = self.GetSection(section).strip()
sectiontext.replace('\n', '\n ') + "\n\n"
globalsection = self.GetSection("globals")
## Code generated by Beremiz python mixin confnode
## Code for PLC global variable access
from targets.typemapping import TypeTranslator
_%(pyextname)sGlobalsDesc = []
__ext_name__ = "%(pyextname)s"
PLCGlobalsDesc.append(( "%(pyextname)s" , _%(pyextname)sGlobalsDesc ))
## User code in "global" scope
## Beremiz python runtime calls
# write generated content to python file
runtimefile_path = os.path.join(buildpath,
"runtime_%s.py" % location_str)
runtimefile = open(runtimefile_path, 'w')
runtimefile.write(PyFileContent.encode('utf-8'))
# C code for safe global variables access
extern __IEC_%(IECtype)s_t %(configname)s__%(uppername)s;
IEC_%(IECtype)s __%(name)s_rbuffer = __INIT_%(IECtype)s;
IEC_%(IECtype)s __%(name)s_wbuffer;
long __%(name)s_rlock = 0;
long __%(name)s_wlock = 0;
int __%(name)s_wbuffer_written = 0;
void __SafeGetPLCGlob_%(name)s(IEC_%(IECtype)s *pvalue){
while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1));
*pvalue = __%(name)s_rbuffer;
AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
void __SafeSetPLCGlob_%(name)s(IEC_%(IECtype)s *value){
while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1));
__%(name)s_wbuffer = *value;
__%(name)s_wbuffer_written = 1;
AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
PYTHON_POLL* __%(name)s_notifier;
if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
if(__%(name)s_wbuffer_written == 1){
%(configname)s__%(uppername)s.value = __%(name)s_wbuffer;
__%(name)s_wbuffer_written = 0;
AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
__%(name)s_rbuffer = __GET_VAR(%(configname)s__%(uppername)s);
AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
IEC_%(IECtype)s tmp = __GET_VAR(%(configname)s__%(uppername)s);
if(__%(name)s_rbuffer != tmp){
__%(name)s_rbuffer = %(configname)s__%(uppername)s.value;
PYTHON_POLL_body__(__%(name)s_notifier);
AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
varinitonchangefmt = """\
__%(name)s_notifier = __GET_GLOBAL_ON%(uppername)sCHANGE();
__SET_VAR(__%(name)s_notifier->,TRIG,,__BOOL_LITERAL(TRUE));
__SET_VAR(__%(name)s_notifier->,CODE,,__STRING_LITERAL(%(onchangelen)d,%(onchangecode)s));
vardec = "\n".join([(vardecfmt + vardeconchangefmt
if varinfo["onchange"] else vardecfmt) % varinfo
for varinfo in varinfos])
varret = "\n".join([varretfmt % varinfo for varinfo in varinfos])
varpub = "\n".join([(varpubonchangefmt if varinfo["onchange"] else
for varinfo in varinfos])
varinit = "\n".join([varinitonchangefmt % dict(
onchangelen=len(varinfo["onchangecode"]), **varinfo)
for varinfo in varinfos if varinfo["onchange"]])
# TODO : use config name obtained from model instead of default
# "config.h". User cannot change config name, but project imported
# or created in older beremiz vesion could use different name.
* Code generated by Beremiz py_ext confnode
* for safe global variables access
#include "iec_types_all.h"
/* User variables reference */
/* Beremiz confnode functions */
int __init_%(location_str)s(int argc,char **argv){
void __cleanup_%(location_str)s(void){
void __retrieve_%(location_str)s(void){
void __publish_%(location_str)s(void){
Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c" % location_str)
pycfile = open(Gen_PyCfile_path, 'w')
pycfile.write(PyCFileContent)
matiec_CFLAGS = '"-I%s"' % os.path.abspath(
self.GetCTRoot().GetIECLibPath())
return ([(Gen_PyCfile_path, matiec_CFLAGS)],
("runtime_%s.py" % location_str, file(runtimefile_path, "rb")))
PythonFileCTNMixin.CTNGenerate_C = CTNGenerate_C
def ResetSearchResults(self):
self.SearchResults = None
self.VariableSearchResults = []
self.CurrentFindHighlight = None
CodeEditor.ResetSearchResults = ResetSearchResults
from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
[STC_CODE_ERROR, STC_CODE_SEARCH_RESULT,
STC_CODE_SECTION] = range(15, 18)
ERROR_HIGHLIGHT: STC_CODE_ERROR,
SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT,
def FindVariable(self, direction, search_params, variables):
if self.SearchParams != search_params:
self.SearchParams = search_params
if len(self.VariableSearchResults) > 0:
(r, c) = self.VariableSearchResults[self.index]
variables.VariablesGrid.SetCellBackgroundColour(r, c, SEARCH_RESULT_HIGHLIGHT[1])
grid = variables.VariablesGrid
cols = grid.GetNumberCols()
rows = grid.GetNumberRows()
self.VariableSearchResults = []
value = variables.VariablesGrid.GetCellValue(row, col)
search_value = search_params['find_pattern']
if search_params['case_sensitive'] == False:
search_value = search_value.lower()
if search_value in value:
self.VariableSearchResults.append((row, col))
if len(self.VariableSearchResults) > 0:
(r, c) = self.VariableSearchResults[self.index]
variables.VariablesGrid.SetCellBackgroundColour(r, c, SEARCH_RESULT_HIGHLIGHT[1])
self.index = self.index % len(self.VariableSearchResults)
(r, c) = self.VariableSearchResults[self.index]
variables.VariablesGrid.SetCellBackgroundColour(r, c, SEARCH_RESULT_HIGHLIGHT[0])
variables.VariablesGrid.MakeCellVisible(r, c)
variables.VariablesGrid.ForceRefresh()
CodeEditor.FindVariable = FindVariable
def SearchInPyfile(self, criteria):
from xml.dom import minidom
dir_list = next(os.walk(self.ProjectPath))[1]
if dir not in ["build", "CanOpen@CanOpen", "project_files"]:
path = os.path.join(self.ProjectPath, dir, 'pyfile.xml')
pyfile = minidom.parse(path)
variablelist = pyfile.getElementsByTagName('variable')
if criteria["find_pattern"] in s.attributes['name'].value:
PLCControler.SearchInPyfile = SearchInPyfile
def OnSearchInProjectMenu(self, event):
dialog = SearchInProjectDialog(self)
if dialog.ShowModal() == wx.ID_OK:
criteria = dialog.GetCriteria()
result = self.Controler.SearchInProject(criteria)
pyresult = self.Controler.SearchInPyfile(criteria)
self.ClearSearchResults()
self.SearchResultPanel.SetSearchResults(criteria, result, pyresult)
self.SearchResultPanel.AddPyFileResults(pyresult)
self.SelectTab(self.SearchResultPanel)
IDEFrame.OnSearchInProjectMenu = OnSearchInProjectMenu
def GenerateProjectTreeBranch(self, root, infos, item_alone=False):
item_name = infos["name"]
if infos["type"] in ITEMS_UNEDITABLE:
if len(infos["values"]) == 1:
return self.GenerateProjectTreeBranch(root, infos["values"][0], True)
self.ProjectTree.SetItemText(root, item_name)
self.ProjectTree.SetPyData(root, infos)
highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.WHITE, wx.BLACK))
self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0])
self.ProjectTree.SetItemTextColour(root, highlight_colours[1])
self.ProjectTree.SetItemExtraImage(root, None)
if infos["type"] == ITEM_POU:
self.ProjectTree.SetItemImage(root,
self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
self.ProjectTree.SetItemExtraImage(root, self.Controler.GetPouType(infos["name"]))
elif infos.has_key("icon") and infos["icon"] is not None:
icon_name = infos["icon"]
if not self.TreeImageDict.has_key(icon_name):
self.TreeImageDict[icon_name] = self.TreeImageList.Add(GetBitmap(icon_name))
self.ProjectTree.SetItemImage(root, self.TreeImageDict[icon_name])
elif self.TreeImageDict.has_key(infos["type"]):
self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
item, root_cookie = self.ProjectTree.GetFirstChild(root)
for values in infos["values"]:
if values["type"] not in ITEMS_UNEDITABLE or len(values["values"]) > 0:
if item is None or not item.IsOk():
item = self.ProjectTree.AppendItem(root, "")
item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
self.GenerateProjectTreeBranch(item, values)
item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
while item is not None and item.IsOk():
item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
self.ProjectTree.Delete(item)
IDEFrame.GenerateProjectTreeBranch = GenerateProjectTreeBranch
defaultSearchResultPanelInit = SearchResultPanel.__init__
def SearchResultPanelInit(self, parent, window):
defaultSearchResultPanelInit(self, parent, window)
self.TreeImageDict["py_file"] = self.TreeImageList.Add(GetBitmap("py_file"))
self.TreeImageDict["wx_glade"] = self.TreeImageList.Add(GetBitmap("wx_glade"))
SearchResultPanel.__init__ = SearchResultPanelInit
def SetSearchResults(self, criteria, search_results, py_results):
self.PySearchResults = py_results
for infos, start, end, text in search_results:
if infos[0] not in self.ElementsOrder:
self.ElementsOrder.append(infos[0])
results = self.SearchResults.setdefault(infos[0], [])
results.append((infos, start, end, text))
SearchResultPanel.SetSearchResults = SetSearchResults
def AddPyFileResults(self, search_results):
distinct_list = list(set(search_results))
for result in distinct_list:
matches = search_results.count(result)
root = self.SearchResultsTree.GetRootItem()
self.SearchResultsTree.AppendItem(root, name[0], image=self.TreeImageDict["py_file"])
root = self.SearchResultsTree.GetRootItem()
self.SearchResultsTree.AppendItem(root, name[0], image=self.TreeImageDict["wx_glade"])
text = _("(%d matches)") % search_results.count(result)
start_idx, end_idx = 0, len(text)
style = wx.TextAttr(wx.Colour(0, 127, 174))
text_ctrl_style = wx.BORDER_NONE | wx.TE_READONLY | wx.TE_RICH2
if wx.Platform != '__WXMSW__' or len(text.splitlines()) > 1:
text_ctrl_style |= wx.TE_MULTILINE
text_ctrl = wx.TextCtrl(id=-1, parent=self.SearchResultsTree, pos=wx.Point(0, 0),
value=text, style=text_ctrl_style)
width, height = text_ctrl.GetTextExtent(text)
text_ctrl.SetClientSize(wx.Size(width + 1, height))
text_ctrl.SetBackgroundColour(self.SearchResultsTree.GetBackgroundColour())
child = self.SearchResultsTree.GetLastChild(root)
text_ctrl.SetInsertionPoint(0)
text_ctrl.SetStyle(start_idx, end_idx, style)
self.SearchResultsTree.SetItemWindow(child, text_ctrl)
SearchResultPanel.AddPyFileResults = AddPyFileResults
def ResetSearchResults(self):
self.PySearchResults = []
SearchResultPanel.ResetSearchResults = ResetSearchResults
def GetPythonTextCtrlDClickFunction(self, item):
for type in self.ParentWindow.CTR.Children.values():
if name.BaseParams.attrib['Name'] == item:
selected = self.ParentWindow.TabsOpened.GetSelection()
window = self.ParentWindow.TabsOpened.GetPage(selected)
window.CodeEditor.FindVariable(1, {'find_pattern': self.Criteria['find_pattern'],
'regular_expression': self.Criteria['regular_expression'],
'pattern': self.Criteria['pattern'],
'case_sensitive': self.Criteria['case_sensitive'],
'filter': self.Criteria['filter']}, window.VariablesPanel)
for (r, c) in window.CodeEditor.VariableSearchResults:
window.VariablesPanel.VariablesGrid.SetCellBackgroundColour(r, c,
SEARCH_RESULT_HIGHLIGHT[0])
SearchResultPanel.GetPythonTextCtrlDClickFunction = GetPythonTextCtrlDClickFunction
def OnSearchResultsTreeItemActivated(self, event):
self.ShowSearchResults(event.GetItem())
if event.GetItem()._data is None:
self.GetPythonTextCtrlDClickFunction(event.GetItem()._text)
SearchResultPanel.OnSearchResultsTreeItemActivated = OnSearchResultsTreeItemActivated
defaultProjectPropertiesPanelInit = ProjectPropertiesPanel.__init__
def OurProjectPropertiesPanelInit(self, parent, controller=None, window=None, enable_required=True):
REQUIRED_PARAMS = ["projectName", "productName", "productVersion", "companyName"]
[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
def create_project_panel(self):
self.ProjectPanel = ScrolledPanel(self, -1, style=wx.TAB_TRAVERSAL)
self.ProjectPanel.SetAutoLayout(1)
self.ProjectPanel.SetupScrolling()
self.AddPage(self.ProjectPanel, _("Project"))
projectpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15)
projectpanel_sizer.AddGrowableCol(1)
self.ProjectPanel.SetSizer(projectpanel_sizer)
self.AddSizerParams(self.ProjectPanel, projectpanel_sizer,
[("projectName", _('Project Name (required):')),
("projectVersion", _('Project Version (optional):')),
("productName", _('Product Name (required):')),
("productVersion", _('Product Version (required):')),
("productRelease", _('Product Release (optional):'))])
self.AddPage(self.ProjectPanel, _("Project"))
def create_author_panel(self):
self.AuthorPanel = ScrolledPanel(self, -1, style=wx.TAB_TRAVERSAL)
self.AuthorPanel.SetAutoLayout(1)
self.AuthorPanel.SetupScrolling()
authorpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15)
authorpanel_sizer.AddGrowableCol(1)
self.AuthorPanel.SetSizer(authorpanel_sizer)
self.AddSizerParams(self.AuthorPanel, authorpanel_sizer,
[("companyName", _('Company Name (required):')),
("companyURL", _('Company URL (optional):')),
("authorName", _('Author Name (optional):')),
("organization", _('Organization (optional):'))])
self.AddPage(self.AuthorPanel, _("Author"))
def create_graphic_panel(self):
self.GraphicsPanel = ScrolledPanel(self, -1, style=wx.TAB_TRAVERSAL)
self.GraphicsPanel.SetAutoLayout(1)
self.GraphicsPanel.SetupScrolling()
graphicpanel_sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5)
graphicpanel_sizer.AddGrowableCol(0)
graphicpanel_sizer.AddGrowableRow(3)
self.GraphicsPanel.SetSizer(graphicpanel_sizer)
pageSize_st = wx.StaticText(self.GraphicsPanel,
label=_('Page Size (optional):'))
graphicpanel_sizer.AddWindow(pageSize_st, border=10,
flag=wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.LEFT | wx.RIGHT)
pageSize_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
pageSize_sizer.AddGrowableCol(1)
graphicpanel_sizer.AddSizer(pageSize_sizer, border=10,
flag=wx.GROW | wx.LEFT | wx.RIGHT)
for name, label in [('PageWidth', _('Width:')), ('PageHeight', _('Height:'))]:
st = wx.StaticText(self.GraphicsPanel, label=label)
pageSize_sizer.AddWindow(st, border=12,
flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT)
sp = wx.SpinCtrl(self.GraphicsPanel,
min=0, max=2 ** 16, style=wx.TE_PROCESS_ENTER)
callback = self.GetPageSizeChangedFunction(sp, name)
self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
sp.Bind(wx.EVT_KILL_FOCUS, callback)
pageSize_sizer.AddWindow(sp, flag=wx.GROW)
scaling_st = wx.StaticText(self.GraphicsPanel,
label=_('Grid Resolution:'))
graphicpanel_sizer.AddWindow(scaling_st, border=10,
flag=wx.GROW | wx.LEFT | wx.RIGHT)
scaling_nb = wx.Notebook(self.GraphicsPanel)
graphicpanel_sizer.AddWindow(scaling_nb, border=10,
flag=wx.GROW | wx.BOTTOM | wx.LEFT | wx.RIGHT)
for language, translation in [("FBD", _("FBD")), ("LD", _("LD")), ("SFC", _("SFC"))]:
scaling_panel = wx.Panel(scaling_nb, style=wx.TAB_TRAVERSAL)
scalingpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
scalingpanel_sizer.AddGrowableCol(1)
scaling_panel.SetSizer(scalingpanel_sizer)
for idx, (name, label) in enumerate([('XScale', _('Horizontal:')),
('YScale', _('Vertical:'))]):
st = wx.StaticText(scaling_panel, label=label)
scalingpanel_sizer.AddWindow(st, border=10,
flag=wx.ALIGN_CENTER_VERTICAL | border | wx.LEFT)
sp = wx.SpinCtrl(scaling_panel,
min=0, max=2 ** 16, style=wx.TE_PROCESS_ENTER)
scaling_controls.append(sp)
callback = self.GetScalingChangedFunction(sp, language, name)
self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
sp.Bind(wx.EVT_KILL_FOCUS, callback)
scalingpanel_sizer.AddWindow(sp, border=10,
flag=wx.GROW | border | wx.RIGHT)
self.Scalings[language] = scaling_controls
scaling_nb.AddPage(scaling_panel, translation)
self.AddPage(self.GraphicsPanel, _("Graphics"))
def create_miscellaneous_panel(self):
self.MiscellaneousPanel = ScrolledPanel(id=-1, parent=self,
name='MiscellaneousPanel', pos=wx.Point(0, 0),
size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
self.MiscellaneousPanel.SetAutoLayout(1)
self.MiscellaneousPanel.SetupScrolling()
miscellaneouspanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15)
miscellaneouspanel_sizer.AddGrowableCol(1)
miscellaneouspanel_sizer.AddGrowableRow(1)
self.MiscellaneousPanel.SetSizer(miscellaneouspanel_sizer)
language_label = wx.StaticText(self.MiscellaneousPanel,
label=_('Language (optional):'))
miscellaneouspanel_sizer.AddWindow(language_label, border=10,
flag=wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.LEFT)
self.Language = wx.ComboBox(self.MiscellaneousPanel,
self.Bind(wx.EVT_COMBOBOX, self.OnLanguageChanged, self.Language)
miscellaneouspanel_sizer.AddWindow(self.Language, border=10,
flag=wx.GROW | wx.TOP | wx.RIGHT)
description_label = wx.StaticText(self.MiscellaneousPanel,
label=_('Content Description (optional):'))
miscellaneouspanel_sizer.AddWindow(description_label, border=10,
flag=wx.BOTTOM | wx.LEFT)
self.ContentDescription = wx.TextCtrl(self.MiscellaneousPanel,
style=wx.TE_MULTILINE | wx.TE_PROCESS_ENTER)
self.Bind(wx.EVT_TEXT_ENTER, self.OnContentDescriptionChanged,
self.ContentDescription.Bind(wx.EVT_KILL_FOCUS,
self.OnContentDescriptionChanged)
miscellaneouspanel_sizer.AddWindow(self.ContentDescription, border=10,
flag=wx.GROW | wx.BOTTOM | wx.RIGHT)
self.AddPage(self.MiscellaneousPanel, _("Miscellaneous"))
wx.Notebook.__init__(self, parent, size=wx.Size(500, 300))
self.Controller = controller
self.ParentWindow = window
create_project_panel(self)
create_author_panel(self)
create_graphic_panel(self)
create_miscellaneous_panel(self)
for param in REQUIRED_PARAMS:
getattr(self, param).Enable(enable_required)
languages = ["", "en-US", "fr-FR", "zh-CN", "ru-RU"]
for language in languages:
self.Language.Append(language)
ProjectPropertiesPanel.__init__ = OurProjectPropertiesPanelInit
def LeftClick(self, event):
if event.GetCol() == self.grid.GetNumberCols()-1:
options = [self.grid.GetCellValue(event.GetRow(), event.GetCol()), self.grid.GetCellValue(event.GetRow(), event.GetCol()-1)]
desc = self.grid.GetCellValue(event.GetRow(), event.GetCol()-2)
if hasattr(self, "dialog"):
self.dialog.SetOptions(options, desc)
answer = self.dialog.ShowModal()
#self.dialog.SetOptions(options, desc)
self.dialog = WampOptionsEditor(self.Parent.Parent, options, desc)
answer = self.dialog.ShowModal()
opt,OnChange,value,description = self.dialog.GetOptions()
self.grid.SetCellValue(event.GetRow(), event.GetCol(), str(opt))
self.grid.SetCellValue(event.GetRow(), event.GetCol()-1, value)
self.grid.SetCellValue(event.GetRow(), event.GetCol()-2, description)
self.Parent.RefreshModel()
VariablesTable.LeftClick = LeftClick
def VariablesEditorSetCollSize(self):
ColSizes = [20, 150] + [130] * (len(self.VariablesDefaultValue) - 2) + [300]
for col in range(self.Table.GetNumberCols()):
self.VariablesGrid.SetColSize(col, ColSizes[col])
VariablesEditor.VariablesEditorSetCollSize = VariablesEditorSetCollSize
def _updateColAttrs(self, grid):
wxGrid -> update the column attributes to add the
appropriate renderer given the column name.
Otherwise default to the default renderer.
for row in range(self.GetNumberRows()):
for col in range(self.GetNumberCols()):
colname = self.GetColLabelValue(col, False)
if colname in ["Name", "Initial", "Description", "OnChange"]:
editor = wx.grid.GridCellTextEditor()
editor = wx.grid.GridCellChoiceEditor()
editor.SetParameters("input,memory,output")
grid.SetReadOnly(row, col, True)
grid.SetCellEditor(row, col, editor)
grid.SetCellRenderer(row, col, renderer)
grid.SetCellBackgroundColour(row, col, wx.WHITE)
self.grid.SetRowMinimalHeight
# updated column width, with function VariablesEditorSetCollSize added in VariablesEditor class
self.Parent.VariablesEditorSetCollSize()
# added left click option on grid, with function LeftClick added in VariablesTable class
self.grid.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.LeftClick)
VariablesTable._updateColAttrs = _updateColAttrs
"""Zakomentirano ker je ze v beremiz-u"""
# def OnCleanButton(self, event):
# if self.LogSource is not None:
# rez = self.LogSource.ResetLogCount()
# self.GrandParent.CTR.logger.write_warning("Can not reset log messages!\n")
# self.ResetLogMessages()
# LogViewer.OnCleanButton = OnCleanButton
from PLCControler import PLCControler, LOCATION_MODULE, LOCATION_GROUP
defaultGenerateNewName = PLCControler.GenerateNewName
def newGenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False):
return defaultGenerateNewName(self, tagname, name, format, start_idx=0, exclude={}, debug=False)
while name is None or names.get(name.upper(), False):
PLCControler.GenerateNewName = newGenerateNewName
from canfestival import RootClass as CanOpenRootClass
from canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager
from canfestival.NetworkEditor import NetworkEditor
from canfestival.SlaveEditor import SlaveEditor
# havecanfestival = False
# ConfTreeNodeEditor.SHOW_BASE_PARAMS = False
# -------------------------------------------------------------------------------
# CANFESTIVAL CONFNODE HACK
# -------------------------------------------------------------------------------
from canfestival import canfestival
defaultGetCFLAGS = canfestival.local_canfestival_config.getCFLAGS
defaultGetLDFLAGS = canfestival.local_canfestival_config.getLDFLAGS
return str(defaultGetCFLAGS(*args))
return str(defaultGetLDFLAGS(*args))
canfestival.local_canfestival_config.getCFLAGS = getCFLAGS
canfestival.local_canfestival_config.getLDFLAGS = getLDFLAGS
import LPCBus as LPCBus_mod
LPCBus_mod.LPCarch = "MC9"
LPCBus_mod.LPCarch = arch
# -------------------------------------------------------------------------------
# LPC CanFestival ConfNode Class
# -------------------------------------------------------------------------------
class LPCSlaveEditor(SlaveEditor):
# SHOW_BASE_PARAMS = False
class LPCCanOpenSlave(_SlaveCTN):
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CanFestivalSlaveNode">
<xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
<xsd:attribute name="NodeId" type="xsd:integer" use="optional" default="%(Slave_NodeId)d"/>
<xsd:attribute name="Sync_Align" type="xsd:integer" use="optional" default="0"/>
<xsd:attribute name="Sync_Align_Ratio" use="optional" default="50">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="99"/>
EditorType = LPCSlaveEditor
# TODO change netname when name change
NodeManager.__init__(self)
odfilepath = self.GetSlaveODPath()
if (os.path.isfile(odfilepath)):
self.OpenFileInCurrent(odfilepath)
self.CreateNewNode("SlaveNode", # Name - will be changed at build time
0x00, # NodeID - will be changed at build time
return str(self.BaseParams.getIEC_Channel())
{"bitmap": "NetworkEdit",
"tooltip": _("Edit CanOpen slave with ObjdictEdit"),
] + _SlaveCTN.ConfNodeMethods
class LPCNetworkEditor(NetworkEditor):
# SHOW_BASE_PARAMS = False
class LPCCanOpenMaster(_NodeListCTN):
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CanFestivalNode">
<xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
<xsd:attribute name="NodeId" type="xsd:integer" use="optional" default="%(Master_NodeId)d"/>
<xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
EditorType = LPCNetworkEditor
return str(self.BaseParams.getIEC_Channel())
{"bitmap": "NetworkEdit",
"name": _("Edit network"),
"tooltip": _("Edit CanOpen Network with NetworkEdit"),
] + _NodeListCTN.ConfNodeMethods
class LPCCanOpen(CanOpenRootClass):
CTNChildrenTypes = [("CanOpenNode", LPCCanOpenMaster, "CanOpen Master"),
("CanOpenSlave", LPCCanOpenSlave, "CanOpen Slave")]
ConfigTreeNode.LoadChildren(self)
if self.GetChildByName("Master") is None:
master = self.CTNAddChild("Master", "CanOpenNode", 0)
# master.BaseParams.setEnabled(False)
if self.GetChildByName("Slave") is None:
slave = self.CTNAddChild("Slave", "CanOpenSlave", 1)
# slave.BaseParams.setEnabled(False)
# -------------------------------------------------------------------------------
from threading import Thread, Semaphore, Lock
wx_eval_lock = Semaphore(0)
def wx_evaluator(callable, *args, **kwargs):
eval_res = callable(*args, **kwargs)
def evaluator(callable, *args, **kwargs):
wx.CallAfter(wx_evaluator, callable, *args, **kwargs)
# Command log for debug, for viewing from wxInspector
if __name__ == '__main__':
lpcmanager = LPCManagerLauncher()