--- a/IDEFrame.py Thu May 16 20:42:48 2013 +0900
+++ b/IDEFrame.py Fri May 17 20:58:34 2013 +0200
@@ -521,7 +521,8 @@
self.ProjectTree = CustomTree(id=ID_PLCOPENEDITORPROJECTTREE,
name='ProjectTree', parent=self.ProjectPanel,
pos=wx.Point(0, 0), size=wx.Size(0, 0),
- style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_EDIT_LABELS)
+ style=wx.SUNKEN_BORDER, + agwStyle=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.TR_EDIT_LABELS) self.ProjectTree.SetBackgroundBitmap(GetBitmap("custom_tree_background"),
wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM)
@@ -1217,7 +1218,7 @@
window = self.FindFocus()
if window == self.ProjectTree or window is None:
selected = self.ProjectTree.GetSelection()
+ if selected is not None and selected.IsOk(): function = self.DeleteFunctions.get(self.ProjectTree.GetPyData(selected)["type"], None)
@@ -1429,9 +1430,6 @@
#-------------------------------------------------------------------------------
def RefreshProjectTree(self):
- if wx.Platform == '__WXMSW__':
- self.ProjectTree.SetEvtHandlerEnabled(False)
# Extract current selected item tagname
selected = self.ProjectTree.GetSelection()
if selected is not None and selected.IsOk():
@@ -1443,7 +1441,7 @@
# Refresh treectrl items according to project infos
infos = self.Controler.GetProjectInfos()
root = self.ProjectTree.GetRootItem()
+ if root is None or not root.IsOk(): root = self.ProjectTree.AddRoot(infos["name"])
self.GenerateProjectTreeBranch(root, infos)
self.ProjectTree.Expand(root)
@@ -1451,18 +1449,16 @@
# Select new item corresponding to previous selected item
self.SelectProjectTreeItem(tagname)
- elif wx.Platform == '__WXMSW__':
- self.ProjectTree.SetEvtHandlerEnabled(True)
def ResetSelectedItem(self):
- def GenerateProjectTreeBranch(self, root, infos):
+ 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])
+ return self.GenerateProjectTreeBranch(root, infos["values"][0], True) self.ProjectTree.SetItemText(root, item_name)
self.ProjectTree.SetPyData(root, infos)
@@ -1470,7 +1466,10 @@
self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0])
self.ProjectTree.SetItemTextColour(root, highlight_colours[1])
if infos["type"] == ITEM_POU:
- self.ProjectTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
+ 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):
@@ -1479,53 +1478,42 @@
elif self.TreeImageDict.has_key(infos["type"]):
self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
- if wx.VERSION >= (2, 6, 0):
- item, root_cookie = self.ProjectTree.GetFirstChild(root)
- item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
+ 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, "")
- if wx.Platform != '__WXMSW__':
- item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
+ 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)
+ TagNamePartsItemTypes = { + "T": [ITEM_POU, ITEM_TRANSITION], + "A": [ITEM_POU, ITEM_ACTION], + "C": [ITEM_CONFIGURATION], + "R": [ITEM_CONFIGURATION, ITEM_RESOURCE]} def SelectProjectTreeItem(self, tagname):
- self.ProjectTree.SetEvtHandlerEnabled(False)
if self.ProjectTree is not None:
root = self.ProjectTree.GetRootItem()
+ if root is not None and root.IsOk(): words = tagname.split("::")
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_DATATYPE)])
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU)])
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)])
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)])
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)])
- result = self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)])
- self.ProjectTree.SetEvtHandlerEnabled(True)
+ result = self.RecursiveProjectTreeItemSelection(root, + zip(words[1:], self.TagNamePartsItemTypes.get(words[0], []))) def RecursiveProjectTreeItemSelection(self, root, items):
- if wx.VERSION >= (2, 6, 0):
- item, root_cookie = self.ProjectTree.GetFirstChild(root)
- item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
- while item.IsOk() and not found:
+ item, root_cookie = self.ProjectTree.GetFirstChild(root) + while item is not None and item.IsOk() and not found: item_infos = self.ProjectTree.GetPyData(item)
if (item_infos["name"].split(":")[-1].strip(), item_infos["type"]) == items[0]:
@@ -1686,7 +1674,7 @@
def ProjectTreeItemSelect(self, select_item):
+ if select_item is not None and select_item.IsOk(): name = self.ProjectTree.GetItemText(select_item)
item_infos = self.ProjectTree.GetPyData(select_item)
if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
@@ -1706,7 +1694,7 @@
pt = wx.Point(event.GetX(), event.GetY())
item, flags = self.ProjectTree.HitTest(pt)
- if item.IsOk() and flags & wx.TREE_HITTEST_ONITEMLABEL:
+ if item is not None and item.IsOk() and flags & wx.TREE_HITTEST_ONITEMLABEL: item_infos = self.ProjectTree.GetPyData(item)
if item != self.LastToolTipItem and self.LastToolTipItem is not None:
self.ProjectTree.SetToolTip(None)
--- a/controls/CustomTree.py Thu May 16 20:42:48 2013 +0900
+++ b/controls/CustomTree.py Fri May 17 20:58:34 2013 +0200
@@ -16,12 +16,30 @@
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+import wx.lib.agw.customtreectrl as CT -class CustomTree(wx.TreeCtrl):
+from util.BitmapLibrary import GetBitmap +# Customize CustomTreeItem for adding icon on item left +CT.GenericTreeItem._ExtraImage = None +def SetExtraImage(self, image): + self._ExtraImage = image +CT.GenericTreeItem.SetExtraImage = SetExtraImage +_DefaultGetCurrentCheckedImage = CT.GenericTreeItem.GetCurrentCheckedImage +def GetCurrentCheckedImage(self): + if self._ExtraImage is not None: + return self._ExtraImage + return _DefaultGetCurrentCheckedImage(self) +CT.GenericTreeItem.GetCurrentCheckedImage = GetCurrentCheckedImage +class CustomTree(CT.CustomTreeCtrl): def __init__(self, *args, **kwargs):
- wx.TreeCtrl.__init__(self, *args, **kwargs)
- self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+ CT.CustomTreeCtrl.__init__(self, *args, **kwargs) + #self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.BackgroundBitmap = None
self.BackgroundAlign = wx.ALIGN_LEFT|wx.ALIGN_TOP
@@ -29,18 +47,28 @@
- if wx.Platform == '__WXMSW__':
- self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
- self.Bind(wx.EVT_PAINT, self.OnPaint)
- self.Bind(wx.EVT_SIZE, self.OnResize)
- self.Bind(wx.EVT_SCROLL, self.OnScroll)
+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def SetBackgroundBitmap(self, bitmap, align):
self.BackgroundBitmap = bitmap
self.BackgroundAlign = align
+ def SetImageListCheck(self, sizex, sizey, imglist=None): + CT.CustomTreeCtrl.SetImageListCheck(self, sizex, sizey, imglist=None) + for image in ["function", "functionBlock", "program"]: + self.ExtraImages[image] = self._imageListCheck.Add(GetBitmap(image.upper())) + def SetItemExtraImage(self, item, bitmap): + image = self.ExtraImages.get(bitmap) + item.SetExtraImage(image) + self.CalculateSize(item, dc) def SetAddMenu(self, add_menu):
@@ -67,19 +95,6 @@
return wx.Rect(x, y, bitmap_size[0], bitmap_size[1])
- def RefreshBackground(self, refresh_base=False):
- bitmap_rect = self.GetBitmapRect()
- dc.DrawBitmap(self.BackgroundBitmap, bitmap_rect.x, bitmap_rect.y)
- def OnEraseBackground(self, event):
- self.RefreshBackground(True)
def OnLeftUp(self, event):
pos = event.GetPosition()
@@ -88,17 +103,26 @@
bitmap_rect = self.GetBitmapRect()
if (bitmap_rect.InsideXY(pos.x, pos.y) or
flags & wx.TREE_HITTEST_NOWHERE) and self.AddMenu is not None:
- self.PopupMenuXY(self.AddMenu, pos.x, pos.y)
+ wx.CallAfter(self.PopupMenuXY, self.AddMenu, pos.x, pos.y) + def OnEraseBackground(self, event): + rect = self.GetUpdateRegion().GetBox() + dc.SetClippingRect(rect) + bitmap_rect = self.GetBitmapRect() + dc.DrawBitmap(self.BackgroundBitmap, bitmap_rect.x, bitmap_rect.y) def OnScroll(self, event):
- self.RefreshBackground(True)
+ wx.CallAfter(self.Refresh) - def OnResize(self, event):
- self.RefreshBackground(True)
- def OnPaint(self, event):
- self.RefreshBackground()
\ No newline at end of file
+ def OnSize(self, event): + CT.CustomTreeCtrl.OnSize(self, event) --- a/editors/CodeFileEditor.py Thu May 16 20:42:48 2013 +0900
+++ b/editors/CodeFileEditor.py Fri May 17 20:58:34 2013 +0200
@@ -22,6 +22,8 @@
SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT,
class CodeEditor(CustomStyledTextCtrl):
@@ -30,13 +32,10 @@
def __init__(self, parent, window, controler):
CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition,
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
self.SetMarginWidth(1, 25)
- self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
- self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
self.SetProperty("fold", "1")
self.SetProperty("tab.timmy.whinge.level", "1")
@@ -44,7 +43,7 @@
self.SetViewWhiteSpace(False)
self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+ self.SetEdgeColumn(EDGE_COLUMN) # Setup a margin to hold fold markers
self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
@@ -88,17 +87,8 @@
self.StyleSetSpec(STC_CODE_SECTION, 'fore:#808080,size:%(size)d')
self.StyleSetChangeable(STC_CODE_SECTION, False)
- # register some images for use in the AutoComplete box.
- #self.RegisterImage(1, images.getSmilesBitmap())
- wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
- wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
- wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
@@ -121,7 +111,7 @@
self.SectionsComments = {}
for section in self.Controler.SECTIONS_NAMES:
section_comment = " %s section " % (section)
- len_headers = 78 - len(section_comment)
+ len_headers = EDGE_COLUMN - len(section_comment) section_comment = self.COMMENT_HEADER * (len_headers / 2) + \
self.COMMENT_HEADER * (len_headers - len_headers / 2)
@@ -371,8 +361,7 @@
selected_text = self.GetSelectedText()
self.ParentWindow.SetCopyBuffer(selected_text, True)
def OnMarginClick(self, event):
# fold and unfold as needed
@@ -623,12 +612,12 @@
def __init__(self, parent, window, controler):
wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
- main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
- main_sizer.AddGrowableCol(0)
- main_sizer.AddGrowableRow(1)
+ main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4) + main_sizer.AddGrowableCol(1) + main_sizer.AddGrowableRow(0) - controls_sizer = wx.BoxSizer(wx.HORIZONTAL)
- main_sizer.AddSizer(controls_sizer, border=5, flag=wx.TOP|wx.ALIGN_RIGHT)
+ controls_sizer = wx.BoxSizer(wx.VERTICAL) + main_sizer.AddSizer(controls_sizer, border=5, flag=wx.ALL) for name, bitmap, help in [
("AddVariableButton", "add_element", _("Add variable")),
@@ -639,7 +628,7 @@
size=wx.Size(28, 28), style=wx.NO_BORDER)
button.SetToolTipString(help)
setattr(self, name, button)
- controls_sizer.AddWindow(button, border=5, flag=wx.RIGHT)
+ controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM) self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
--- a/editors/ConfTreeNodeEditor.py Thu May 16 20:42:48 2013 +0900
+++ b/editors/ConfTreeNodeEditor.py Fri May 17 20:58:34 2013 +0200
@@ -29,24 +29,12 @@
-WINDOW_COLOUR = wx.Colour(240, 240, 240)
CWD = os.path.split(os.path.realpath(__file__))[0]
return os.path.join(CWD,*args)
-# Some helpers to tweak GenBitmapTextButtons
-# TODO: declare customized classes instead.
-gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID)
-gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,))
-def make_genbitmaptogglebutton_flat(button):
- button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button)
- button.SetBezelWidth(0)
- button.SetUseFocusIndicator(False)
# Patch wx.lib.imageutils so that gray is supported on alpha images
from wx.lib.imageutils import grayOut as old_grayOut
@@ -116,7 +104,7 @@
dc.DrawText(label, pos_x, pos_y) # draw the text
-class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap):
+class GenStaticBitmap(wx.StaticBitmap): """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32,
and accept image name as __init__ parameter, fail silently if file do not exist"""
def __init__(self, parent, ID, bitmapname,
@@ -124,20 +112,15 @@
- wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID,
+ bitmap = GetBitmap(bitmapname) + bitmap = wx.EmptyBitmap(0, 0) + wx.StaticBitmap.__init__(self, parent, ID,
- def OnPaint(self, event):
- colour = self.GetParent().GetBackgroundColour()
- dc.SetPen(wx.Pen(colour))
- dc.SetBrush(wx.Brush(colour ))
- dc.DrawRectangle(0, 0, *dc.GetSizeTuple())
- dc.DrawBitmap(self._bitmap, 0, 0, True)
class ConfTreeNodeEditor(EditorPanel):
@@ -153,7 +136,6 @@
if tabs_num > 1 or self.SHOW_BASE_PARAMS:
self.Editor = wx.Panel(parent,
style=wx.SUNKEN_BORDER|wx.SP_3D)
- self.Editor.SetBackgroundColour(WINDOW_COLOUR)
self.MainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -186,7 +168,7 @@
updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT)
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,
wx.BOLD, faceName = faces["helv"]))
@@ -228,7 +210,6 @@
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)
--- a/editors/Viewer.py Thu May 16 20:42:48 2013 +0900
+++ b/editors/Viewer.py Fri May 17 20:58:34 2013 +0200
@@ -844,11 +844,13 @@
def GetElementIECPath(self, element):
instance_path = self.GetInstancePath(True)
- if isinstance(element, Wire) and element.EndConnected is not None:
- block = element.EndConnected.GetParentBlock()
+ if isinstance(element, (Wire, Connector)): + if isinstance(element, Wire): + element = element.EndConnected + block = element.GetParentBlock() if isinstance(block, FBD_Block):
blockname = block.GetName()
- connectorname = element.EndConnected.GetName()
+ connectorname = element.GetName() iec_path = "%s.%s.%s"%(instance_path, blockname, connectorname)
@@ -1092,9 +1094,16 @@
for block in self.Blocks.itervalues():
- iec_path = self.GetElementIECPath(block)
- if iec_path is not None:
- self.AddDataConsumer(iec_path.upper(), block)
+ if isinstance(block, FBD_Block): + for output_connector in block.GetConnectors()["outputs"]: + if len(output_connector.GetWires()) == 0: + iec_path = self.GetElementIECPath(output_connector) + if iec_path is not None: + self.AddDataConsumer(iec_path.upper(), output_connector) + iec_path = self.GetElementIECPath(block) + if iec_path is not None: + self.AddDataConsumer(iec_path.upper(), block) self.RefreshVisibleElements()
--- a/graphics/GraphicCommons.py Thu May 16 20:42:48 2013 +0900
+++ b/graphics/GraphicCommons.py Fri May 17 20:58:34 2013 +0200
@@ -1514,10 +1514,11 @@
Class that implements a connector for any type of block
+class Connector(DebugDataConsumer): def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False):
+ DebugDataConsumer.__init__(self) self.ParentBlock = parent
@@ -1534,6 +1535,8 @@
+ self.ComputedValue = None @@ -1557,7 +1560,18 @@
- return wx.Rect(x - abs(movex), y - abs(movey), width + 2 * abs(movex), height + 2 * abs(movey))
+ rect = wx.Rect(x - abs(movex), y - abs(movey), width + 2 * abs(movex), height + 2 * abs(movey)) + if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)): + self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue) + if self.ValueSize is not None: + width, height = self.ValueSize + rect = rect.Union(wx.Rect( + parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \ + width * (self.Direction[0] - 1) / 2, + parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \ + height * (self.Direction[1] - 1), # Change the connector selection
def SetSelected(self, selected):
@@ -1621,6 +1635,31 @@
+ def SetForced(self, forced): + if self.Forced != forced: + self.Parent.ElementNeedRefresh(self) + def SetValue(self, value): + if self.Value != value: + if value is not None and not isinstance(value, BooleanType): + connector_type = self.GetType() + if connector_type == "STRING": + self.ComputedValue = "'%s'"%value + elif connector_type == "WSTRING": + self.ComputedValue = "\"%s\""%value + self.ComputedValue = str(value) + #if self.ToolTip is not None: + # self.ToolTip.SetTip(self.ComputedValue) + if len(self.ComputedValue) > 4: + self.ComputedValue = self.ComputedValue[:4] + "..." + if self.ParentBlock.Visible: + self.ParentBlock.Parent.ElementNeedRefresh(self) for wire, handle in self.Wires:
@@ -1960,6 +1999,21 @@
if not getattr(dc, "printing", False):
DrawHighlightedText(dc, self.Name, self.Highlights, xtext, ytext)
+ if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined": + dc.SetFont(self.ParentBlock.Parent.GetMiniFont()) + dc.SetTextForeground(wx.NamedColour("purple")) + if self.ValueSize is None and isinstance(self.ComputedValue, (StringType, UnicodeType)): + self.ValueSize = self.ParentBlock.Parent.GetMiniTextExtent(self.ComputedValue) + if self.ValueSize is not None: + width, height = self.ValueSize + dc.DrawText(self.ComputedValue, + parent_pos[0] + self.Pos.x + CONNECTOR_SIZE * self.Direction[0] + \ + width * (self.Direction[0] - 1) / 2, + parent_pos[1] + self.Pos.y + CONNECTOR_SIZE * self.Direction[1] + \ + height * (self.Direction[1] - 1)) + dc.SetFont(self.ParentBlock.Parent.GetFont()) + dc.SetTextForeground(wx.BLACK) #-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------