--- a/BeremizIDE.py Mon Mar 18 12:20:46 2019 +0300
+++ b/BeremizIDE.py Fri Mar 22 13:26:31 2019 +0100
@@ -1033,6 +1033,14 @@
else:
IDEFrame.ProjectTreeItemSelect(self, select_item)
+ def GetProjectElementWindow(self, element, tagname):
+ is_a_CTN_tagname = len(tagname.split("::"))==1
+ if is_a_CTN_tagname:
+ confnode = self.CTR.GetChildByName(tagname)
+ return confnode.GetView()
+ else :
+ return IDEFrame.GetProjectElementWindow(self, element, tagname)
+
def SelectProjectTreeItem(self, tagname):
if self.ProjectTree is not None:
root = self.ProjectTree.GetRootItem()
--- a/CodeFileTreeNode.py Mon Mar 18 12:20:46 2019 +0300
+++ b/CodeFileTreeNode.py Fri Mar 22 13:26:31 2019 +0100
@@ -36,6 +36,9 @@
from PLCControler import UndoBuffer
from ConfigTreeNode import XSDSchemaErrorMessage
+from plcopen.plcopen import TestTextElement
+from editors.CodeFileEditor import GetSectionsText
+
CODEFILE_XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
@@ -209,6 +212,19 @@
if variable.getonchange()])
return ret
+ def CTNSearch(self, criteria):
+ variables = self.GetVariables()
+ results = []
+ tagname = self.CTNFullName()
+ for index, var in enumerate(variables):
+ varname = var["Name"]
+ results.extend([((tagname, "var_inout", index, "name"),) + result
+ for result in TestTextElement(varname, criteria)])
+ results.extend([((tagname, "body"),) + result
+ for result in TestTextElement(
+ GetSectionsText(self, lambda x:""), criteria)])
+ return results
+
# -------------------------------------------------------------------------------
# Current Buffering Management Functions
# -------------------------------------------------------------------------------
--- a/ConfigTreeNode.py Mon Mar 18 12:20:46 2019 +0300
+++ b/ConfigTreeNode.py Fri Mar 22 13:26:31 2019 +0100
@@ -36,6 +36,7 @@
import traceback
import types
import shutil
+from operator import add
from builtins import str as text
from past.builtins import execfile
@@ -121,6 +122,12 @@
return parent + "." + self.CTNName()
return self.BaseParams.getName()
+ def CTNSearch(self, criteria):
+ # TODO match config's fields name and fields contents
+ return reduce(add, [
+ CTNChild.CTNSearch(criteria)
+ for CTNChild in self.IterChildren()])
+
def GetIconName(self):
return None
@@ -464,20 +471,23 @@
def GetContextualMenuItems(self):
return None
+ def GetView(self):
+ if self._View is None and self.EditorType is not None:
+ app_frame = self.GetCTRoot().AppFrame
+ self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
+
+ return self._View
+
def _OpenView(self, name=None, onlyopened=False):
- if self.EditorType is not None:
+ view = self.GetView()
+
+ if view is not None:
+ if name is None:
+ name = self.CTNFullName()
app_frame = self.GetCTRoot().AppFrame
- if self._View is None and not onlyopened:
-
- self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
-
- if self._View is not None:
- if name is None:
- name = self.CTNFullName()
- app_frame.EditProjectElement(self._View, name)
-
- return self._View
- return None
+ app_frame.EditProjectElement(view, name)
+
+ return view
def _CloseView(self, view):
app_frame = self.GetCTRoot().AppFrame
--- a/IDEFrame.py Mon Mar 18 12:20:46 2019 +0300
+++ b/IDEFrame.py Fri Mar 22 13:26:31 2019 +0100
@@ -1819,6 +1819,47 @@
else:
event.Skip()
+ def GetProjectElementWindow(self, element, tagname):
+ new_window = None
+ if self.Controler.GetEditedElement(tagname) is not None:
+ new_window = None
+ if element == ITEM_CONFIGURATION:
+ new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
+ new_window.SetIcon(GetBitmap("CONFIGURATION"))
+ elif element == ITEM_RESOURCE:
+ new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
+ new_window.SetIcon(GetBitmap("RESOURCE"))
+ elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
+ bodytype = self.Controler.GetEditedElementBodyType(tagname)
+ if bodytype == "FBD":
+ new_window = Viewer(self.TabsOpened, tagname, self, self.Controler)
+ new_window.RefreshScaling(False)
+ elif bodytype == "LD":
+ new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler)
+ new_window.RefreshScaling(False)
+ elif bodytype == "SFC":
+ new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler)
+ new_window.RefreshScaling(False)
+ else:
+ new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler)
+ new_window.SetTextSyntax(bodytype)
+ if bodytype == "IL":
+ new_window.SetKeywords(IL_KEYWORDS)
+ else:
+ new_window.SetKeywords(ST_KEYWORDS)
+ if element == ITEM_POU:
+ pou_type = self.Controler.GetEditedElementType(tagname)[1].upper()
+ icon = GetBitmap(pou_type, bodytype)
+ elif element == ITEM_TRANSITION:
+ icon = GetBitmap("TRANSITION", bodytype)
+ elif element == ITEM_ACTION:
+ icon = GetBitmap("ACTION", bodytype)
+ new_window.SetIcon(icon)
+ elif element == ITEM_DATATYPE:
+ new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
+ new_window.SetIcon(GetBitmap("DATATYPE"))
+ return new_window
+
def EditProjectElement(self, element, tagname, onlyopened=False):
openedidx = self.IsOpened(tagname)
if openedidx is not None:
@@ -1831,49 +1872,11 @@
elif not onlyopened:
if isinstance(element, EditorPanel):
new_window = element
- self.AddPage(element, "")
- elif self.Controler.GetEditedElement(tagname) is not None:
- new_window = None
- if element == ITEM_CONFIGURATION:
- new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
- new_window.SetIcon(GetBitmap("CONFIGURATION"))
- self.AddPage(new_window, "")
- elif element == ITEM_RESOURCE:
- new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
- new_window.SetIcon(GetBitmap("RESOURCE"))
- self.AddPage(new_window, "")
- elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
- bodytype = self.Controler.GetEditedElementBodyType(tagname)
- if bodytype == "FBD":
- new_window = Viewer(self.TabsOpened, tagname, self, self.Controler)
- new_window.RefreshScaling(False)
- elif bodytype == "LD":
- new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler)
- new_window.RefreshScaling(False)
- elif bodytype == "SFC":
- new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler)
- new_window.RefreshScaling(False)
- else:
- new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler)
- new_window.SetTextSyntax(bodytype)
- if bodytype == "IL":
- new_window.SetKeywords(IL_KEYWORDS)
- else:
- new_window.SetKeywords(ST_KEYWORDS)
- if element == ITEM_POU:
- pou_type = self.Controler.GetEditedElementType(tagname)[1].upper()
- icon = GetBitmap(pou_type, bodytype)
- elif element == ITEM_TRANSITION:
- icon = GetBitmap("TRANSITION", bodytype)
- elif element == ITEM_ACTION:
- icon = GetBitmap("ACTION", bodytype)
- new_window.SetIcon(icon)
- self.AddPage(new_window, "")
- elif element == ITEM_DATATYPE:
- new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
- new_window.SetIcon(GetBitmap("DATATYPE"))
- self.AddPage(new_window, "")
+ else:
+ new_window = self.GetProjectElementWindow(element, tagname)
+
if new_window is not None:
+ self.AddPage(new_window, "")
openedidx = self.IsOpened(tagname)
old_selected = self.TabsOpened.GetSelection()
if old_selected != openedidx:
--- a/PLCControler.py Mon Mar 18 12:20:46 2019 +0300
+++ b/PLCControler.py Fri Mar 22 13:26:31 2019 +0100
@@ -2749,7 +2749,9 @@
# -------------------------------------------------------------------------------
def SearchInProject(self, criteria):
- return self.Project.Search(criteria)
+ project_matches = self.Project.Search(criteria)
+ ctn_matches = self.CTNSearch(criteria)
+ return project_matches + ctn_matches
def SearchInPou(self, tagname, criteria, debug=False):
pou = self.GetEditedElement(tagname, debug)
--- a/controls/SearchResultPanel.py Mon Mar 18 12:20:46 2019 +0300
+++ b/controls/SearchResultPanel.py Fri Mar 22 13:26:31 2019 +0100
@@ -130,7 +130,9 @@
("DATATYPE", ITEM_DATATYPE),
("ACTION", "action_block"),
("IL", "IL"),
- ("ST", "ST")]:
+ ("ST", "ST"),
+ ("FILE", ITEM_CONFNODE),
+ ]:
self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
for itemtype in ["function", "functionBlock", "program",
@@ -202,7 +204,12 @@
children = element_infos.setdefault("children", [])
for infos, start, end, text in results:
- if infos[1] == "name" or element_type == ITEM_DATATYPE:
+ if len(words) == 1: # CTN match
+ child_name = {"body":str(start[0])+":",
+ "var_inout":_("Variable:")}[infos[1]]
+ child_type = {"body":ITEM_CONFNODE,
+ "var_inout":"var_inout"}[infos[1]]
+ elif infos[1] == "name" or element_type == ITEM_DATATYPE:
child_name = GenerateName(infos[1:])
child_type = element_type
else:
@@ -232,6 +239,7 @@
}
children.append(child_infos)
+ # not Project node
if len(words) > 2:
for _element_infos in search_results_tree_children:
if _element_infos["name"] == words[1]:
@@ -240,7 +248,7 @@
break
if element_type == ITEM_RESOURCE:
search_results_tree_children.append(element_infos)
- else:
+ else: # Project node or CTN
search_results_tree_children.append(element_infos)
if matches_number < 2:
@@ -302,7 +310,7 @@
if text is not None:
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_style |= wx.TE_MULTILINE | wx.TE_NO_VSCROLL
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)
--- a/editors/CodeFileEditor.py Mon Mar 18 12:20:46 2019 +0300
+++ b/editors/CodeFileEditor.py Fri Mar 22 13:26:31 2019 +0100
@@ -56,6 +56,21 @@
EDGE_COLUMN = 80
+def GetSectionsText(controler, sections_headers):
+ parts = controler.GetTextParts()
+ text = ""
+ for section in controler.SECTIONS_NAMES:
+ text += sections_headers(section)
+ if parts[section] == "":
+ text += "\n"
+ else:
+ if not parts[section].startswith("\n"):
+ text += "\n"
+ text += parts[section]
+ if not parts[section].endswith("\n"):
+ text += "\n"
+ return text
+
class CodeEditor(CustomStyledTextCtrl):
KEYWORDS = []
@@ -239,20 +254,9 @@
self.CurrentAction = None
def GetCodeText(self):
- parts = self.Controler.GetTextParts()
- text = ""
- for section in self.Controler.SECTIONS_NAMES:
- section_comments = self.SectionsComments[section]
- text += section_comments["comment"]
- if parts[section] == "":
- text += "\n"
- else:
- if not parts[section].startswith("\n"):
- text += "\n"
- text += parts[section]
- if not parts[section].endswith("\n"):
- text += "\n"
- return text
+ return GetSectionsText(
+ self.Controler,
+ lambda section : self.SectionsComments[section]["comment"])
def RefreshView(self, scroll_to_highlight=False):
self.ResetBuffer()
@@ -644,6 +648,7 @@
"""
for row in range(self.GetNumberRows()):
+ row_highlights = self.Highlights.get(row, {})
for col in range(self.GetNumberCols()):
editor = None
renderer = None
@@ -656,7 +661,9 @@
grid.SetCellEditor(row, col, editor)
grid.SetCellRenderer(row, col, renderer)
- grid.SetCellBackgroundColour(row, col, wx.WHITE)
+ highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
+ grid.SetCellBackgroundColour(row, col, highlight_colours[0])
+ grid.SetCellTextColour(row, col, highlight_colours[1])
self.ResizeRow(grid, row)
@@ -859,6 +866,20 @@
return
event.Skip()
+ def AddVariableHighlight(self, infos, highlight_type):
+ self.Table.AddHighlight(infos, highlight_type)
+ cell_visible = infos[0]
+ colnames = [colname.lower() for colname in self.Table.colnames]
+ self.VariablesGrid.MakeCellVisible(cell_visible, colnames.index(infos[1]))
+ self.Table.ResetView(self.VariablesGrid)
+
+ def RemoveVariableHighlight(self, infos, highlight_type):
+ self.Table.RemoveHighlight(infos, highlight_type)
+ self.Table.ResetView(self.VariablesGrid)
+
+ def ClearHighlights(self, highlight_type=None):
+ self.Table.ClearHighlights(highlight_type)
+ self.Table.ResetView(self.VariablesGrid)
# -------------------------------------------------------------------------------
# CodeFileEditor Main Frame Class
@@ -914,3 +935,21 @@
def Find(self, direction, search_params):
self.CodeEditor.Find(direction, search_params)
+
+ def AddHighlight(self, infos, start, end, highlight_type):
+ if self.VariablesPanel is not None and infos[0] == "var_inout":
+ self.VariablesPanel.AddVariableHighlight(infos[1:], highlight_type)
+ else:
+ self.CodeEditor.AddHighlight(start, end, highlight_type)
+
+ def RemoveHighlight(self, infos, start, end, highlight_type):
+ if self.VariablesPanel is not None and infos[0] == "var_inout":
+ self.VariablesPanel.RemoveVariableHighlight(infos[1:], highlight_type)
+ else:
+ self.CodeEditor.RemoveHighlight(start, end, highlight_type)
+
+ def ClearHighlights(self, highlight_type=None):
+ if self.VariablesPanel is not None:
+ self.VariablesPanel.ClearHighlights(highlight_type)
+ else:
+ self.CodeEditor.ClearHighlights(highlight_type)
--- a/plcopen/plcopen.py Mon Mar 18 12:20:46 2019 +0300
+++ b/plcopen/plcopen.py Fri Mar 22 13:26:31 2019 +0100
@@ -856,6 +856,7 @@
setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter)
def Search(self, criteria, parent_infos=None):
+ # FIXME : two next lines are incompatible [][-1] raises exception !
parent_infos = [] if parent_infos is None else parent_infos
parent_infos = parent_infos[:-1] + ["R::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
search_result = _SearchInConfigurationResource(self, criteria, parent_infos)
--- a/plcopen/types_enums.py Mon Mar 18 12:20:46 2019 +0300
+++ b/plcopen/types_enums.py Fri Mar 22 13:26:31 2019 +0100
@@ -117,6 +117,8 @@
def GetElementType(tagname):
words = tagname.split("::")
+ if len(words) == 1:
+ return ITEM_CONFNODE
return {
"D": ITEM_DATATYPE,
"P": ITEM_POU,