|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
|
4 #based on the plcopen standard. |
|
5 # |
|
6 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
7 # |
|
8 #See COPYING file for copyrights details. |
|
9 # |
|
10 #This library is free software; you can redistribute it and/or |
|
11 #modify it under the terms of the GNU General Public |
|
12 #License as published by the Free Software Foundation; either |
|
13 #version 2.1 of the License, or (at your option) any later version. |
|
14 # |
|
15 #This library is distributed in the hope that it will be useful, |
|
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
18 #General Public License for more details. |
|
19 # |
|
20 #You should have received a copy of the GNU General Public |
|
21 #License along with this library; if not, write to the Free Software |
|
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
|
24 import wx |
|
25 import wx.grid |
|
26 import wx.lib.buttons |
|
27 |
|
28 from controls import CustomGrid, CustomTable |
|
29 from util.BitmapLibrary import GetBitmap |
|
30 |
|
31 #------------------------------------------------------------------------------- |
|
32 # Helpers |
|
33 #------------------------------------------------------------------------------- |
|
34 |
|
35 def GetActionTableColnames(): |
|
36 _ = lambda x: x |
|
37 return [_("Qualifier"), _("Duration"), _("Type"), _("Value"), _("Indicator")] |
|
38 |
|
39 def GetTypeList(): |
|
40 _ = lambda x: x |
|
41 return [_("Action"), _("Variable"), _("Inline")] |
|
42 |
|
43 #------------------------------------------------------------------------------- |
|
44 # Action Table |
|
45 #------------------------------------------------------------------------------- |
|
46 |
|
47 class ActionTable(CustomTable): |
|
48 |
|
49 def GetValue(self, row, col): |
|
50 if row < self.GetNumberRows(): |
|
51 colname = self.GetColLabelValue(col, False) |
|
52 name = str(self.data[row].get(colname, "")) |
|
53 if colname == "Type": |
|
54 return _(name) |
|
55 return name |
|
56 |
|
57 def SetValue(self, row, col, value): |
|
58 if col < len(self.colnames): |
|
59 colname = self.GetColLabelValue(col, False) |
|
60 if colname == "Type": |
|
61 value = self.Parent.TranslateType[value] |
|
62 self.data[row][colname] = value |
|
63 |
|
64 def _updateColAttrs(self, grid): |
|
65 """ |
|
66 wx.Grid -> update the column attributes to add the |
|
67 appropriate renderer given the column name. |
|
68 |
|
69 Otherwise default to the default renderer. |
|
70 """ |
|
71 |
|
72 for row in range(self.GetNumberRows()): |
|
73 for col in range(self.GetNumberCols()): |
|
74 editor = None |
|
75 renderer = None |
|
76 readonly = False |
|
77 colname = self.GetColLabelValue(col, False) |
|
78 if colname == "Qualifier": |
|
79 editor = wx.grid.GridCellChoiceEditor() |
|
80 editor.SetParameters(self.Parent.QualifierList) |
|
81 if colname == "Duration": |
|
82 editor = wx.grid.GridCellTextEditor() |
|
83 renderer = wx.grid.GridCellStringRenderer() |
|
84 if self.Parent.DurationList[self.data[row]["Qualifier"]]: |
|
85 readonly = False |
|
86 else: |
|
87 readonly = True |
|
88 self.data[row]["Duration"] = "" |
|
89 elif colname == "Type": |
|
90 editor = wx.grid.GridCellChoiceEditor() |
|
91 editor.SetParameters(self.Parent.TypeList) |
|
92 elif colname == "Value": |
|
93 type = self.data[row]["Type"] |
|
94 if type == "Action": |
|
95 editor = wx.grid.GridCellChoiceEditor() |
|
96 editor.SetParameters(self.Parent.ActionList) |
|
97 elif type == "Variable": |
|
98 editor = wx.grid.GridCellChoiceEditor() |
|
99 editor.SetParameters(self.Parent.VariableList) |
|
100 elif type == "Inline": |
|
101 editor = wx.grid.GridCellTextEditor() |
|
102 renderer = wx.grid.GridCellStringRenderer() |
|
103 elif colname == "Indicator": |
|
104 editor = wx.grid.GridCellChoiceEditor() |
|
105 editor.SetParameters(self.Parent.VariableList) |
|
106 |
|
107 grid.SetCellEditor(row, col, editor) |
|
108 grid.SetCellRenderer(row, col, renderer) |
|
109 grid.SetReadOnly(row, col, readonly) |
|
110 |
|
111 grid.SetCellBackgroundColour(row, col, wx.WHITE) |
|
112 self.ResizeRow(grid, row) |
|
113 |
|
114 #------------------------------------------------------------------------------- |
|
115 # Action Block Dialog |
|
116 #------------------------------------------------------------------------------- |
|
117 |
|
118 class ActionBlockDialog(wx.Dialog): |
|
119 |
|
120 def __init__(self, parent): |
|
121 wx.Dialog.__init__(self, parent, |
|
122 size=wx.Size(500, 300), title=_('Edit action block properties')) |
|
123 |
|
124 main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10) |
|
125 main_sizer.AddGrowableCol(0) |
|
126 main_sizer.AddGrowableRow(1) |
|
127 |
|
128 top_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) |
|
129 top_sizer.AddGrowableCol(0) |
|
130 top_sizer.AddGrowableRow(0) |
|
131 main_sizer.AddSizer(top_sizer, border=20, |
|
132 flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
|
133 |
|
134 actions_label = wx.StaticText(self, label=_('Actions:')) |
|
135 top_sizer.AddWindow(actions_label, flag=wx.ALIGN_BOTTOM) |
|
136 |
|
137 for name, bitmap, help in [ |
|
138 ("AddButton", "add_element", _("Add action")), |
|
139 ("DeleteButton", "remove_element", _("Remove action")), |
|
140 ("UpButton", "up", _("Move action up")), |
|
141 ("DownButton", "down", _("Move action down"))]: |
|
142 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
|
143 size=wx.Size(28, 28), style=wx.NO_BORDER) |
|
144 button.SetToolTipString(help) |
|
145 setattr(self, name, button) |
|
146 top_sizer.AddWindow(button) |
|
147 |
|
148 self.ActionsGrid = CustomGrid(self, size=wx.Size(0, 0), style=wx.VSCROLL) |
|
149 self.ActionsGrid.DisableDragGridSize() |
|
150 self.ActionsGrid.EnableScrolling(False, True) |
|
151 self.ActionsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, |
|
152 self.OnActionsGridCellChange) |
|
153 main_sizer.AddSizer(self.ActionsGrid, border=20, |
|
154 flag=wx.GROW|wx.LEFT|wx.RIGHT) |
|
155 |
|
156 button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
|
157 self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton()) |
|
158 main_sizer.AddSizer(button_sizer, border=20, |
|
159 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
160 |
|
161 self.SetSizer(main_sizer) |
|
162 |
|
163 self.Table = ActionTable(self, [], GetActionTableColnames()) |
|
164 typelist = GetTypeList() |
|
165 self.TypeList = ",".join(map(_,typelist)) |
|
166 self.TranslateType = dict([(_(value), value) for value in typelist]) |
|
167 self.ColSizes = [60, 90, 80, 110, 80] |
|
168 self.ColAlignements = [wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT] |
|
169 |
|
170 self.ActionsGrid.SetTable(self.Table) |
|
171 self.ActionsGrid.SetDefaultValue({"Qualifier" : "N", |
|
172 "Duration" : "", |
|
173 "Type" : "Action", |
|
174 "Value" : "", |
|
175 "Indicator" : ""}) |
|
176 self.ActionsGrid.SetButtons({"Add": self.AddButton, |
|
177 "Delete": self.DeleteButton, |
|
178 "Up": self.UpButton, |
|
179 "Down": self.DownButton}) |
|
180 self.ActionsGrid.SetRowLabelSize(0) |
|
181 |
|
182 for col in range(self.Table.GetNumberCols()): |
|
183 attr = wx.grid.GridCellAttr() |
|
184 attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE) |
|
185 self.ActionsGrid.SetColAttr(col, attr) |
|
186 self.ActionsGrid.SetColMinimalWidth(col, self.ColSizes[col]) |
|
187 self.ActionsGrid.AutoSizeColumn(col, False) |
|
188 |
|
189 self.Table.ResetView(self.ActionsGrid) |
|
190 self.ActionsGrid.SetFocus() |
|
191 self.ActionsGrid.RefreshButtons() |
|
192 |
|
193 def OnOK(self, event): |
|
194 self.ActionsGrid.CloseEditControl() |
|
195 self.EndModal(wx.ID_OK) |
|
196 |
|
197 def OnActionsGridCellChange(self, event): |
|
198 wx.CallAfter(self.Table.ResetView, self.ActionsGrid) |
|
199 event.Skip() |
|
200 |
|
201 def SetQualifierList(self, list): |
|
202 self.QualifierList = "," + ",".join(list) |
|
203 self.DurationList = list |
|
204 |
|
205 def SetVariableList(self, list): |
|
206 self.VariableList = "," + ",".join([variable["Name"] for variable in list]) |
|
207 |
|
208 def SetActionList(self, list): |
|
209 self.ActionList = "," + ",".join(list) |
|
210 |
|
211 def SetValues(self, actions): |
|
212 for action in actions: |
|
213 row = {"Qualifier" : action["qualifier"], "Value" : action["value"]} |
|
214 if action["type"] == "reference": |
|
215 if action["value"] in self.ActionList: |
|
216 row["Type"] = "Action" |
|
217 elif action["value"] in self.VariableList: |
|
218 row["Type"] = "Variable" |
|
219 else: |
|
220 row["Type"] = "Inline" |
|
221 else: |
|
222 row["Type"] = "Inline" |
|
223 if "duration" in action: |
|
224 row["Duration"] = action["duration"] |
|
225 else: |
|
226 row["Duration"] = "" |
|
227 if "indicator" in action: |
|
228 row["Indicator"] = action["indicator"] |
|
229 else: |
|
230 row["Indicator"] = "" |
|
231 self.Table.AppendRow(row) |
|
232 self.Table.ResetView(self.ActionsGrid) |
|
233 if len(actions) > 0: |
|
234 self.ActionsGrid.SetGridCursor(0, 0) |
|
235 self.ActionsGrid.RefreshButtons() |
|
236 |
|
237 def GetValues(self): |
|
238 values = [] |
|
239 for data in self.Table.GetData(): |
|
240 action = {"qualifier" : data["Qualifier"], "value" : data["Value"]} |
|
241 if data["Type"] in ["Action", "Variable"]: |
|
242 action["type"] = "reference" |
|
243 else: |
|
244 action["type"] = "inline" |
|
245 if data["Duration"] != "": |
|
246 action["duration"] = data["Duration"] |
|
247 if data["Indicator"] != "": |
|
248 action["indicator"] = data["Indicator"] |
|
249 values.append(action) |
|
250 return values |