46 Class that implements a dialog for defining parameters of a FBD block graphic |
46 Class that implements a dialog for defining parameters of a FBD block graphic |
47 element |
47 element |
48 """ |
48 """ |
49 |
49 |
50 class FBDBlockDialog(BlockPreviewDialog): |
50 class FBDBlockDialog(BlockPreviewDialog): |
51 |
51 |
52 def __init__(self, parent, controller, tagname): |
52 def __init__(self, parent, controller, tagname): |
53 """ |
53 """ |
54 Constructor |
54 Constructor |
55 @param parent: Parent wx.Window of dialog for modal |
55 @param parent: Parent wx.Window of dialog for modal |
56 @param controller: Reference to project controller |
56 @param controller: Reference to project controller |
57 @param tagname: Tagname of project POU edited |
57 @param tagname: Tagname of project POU edited |
58 """ |
58 """ |
59 BlockPreviewDialog.__init__(self, parent, controller, tagname, |
59 BlockPreviewDialog.__init__(self, parent, controller, tagname, |
60 title=_('Block Properties')) |
60 title=_('Block Properties')) |
61 |
61 |
62 # Init common sizers |
62 # Init common sizers |
63 self._init_sizers(2, 0, 1, 0, 3, 2) |
63 self._init_sizers(2, 0, 1, 0, 3, 2) |
64 |
64 |
65 # Create static box around library panel |
65 # Create static box around library panel |
66 type_staticbox = wx.StaticBox(self, label=_('Type:')) |
66 type_staticbox = wx.StaticBox(self, label=_('Type:')) |
67 left_staticboxsizer = wx.StaticBoxSizer(type_staticbox, wx.VERTICAL) |
67 left_staticboxsizer = wx.StaticBoxSizer(type_staticbox, wx.VERTICAL) |
68 self.LeftGridSizer.AddSizer(left_staticboxsizer, border=5, flag=wx.GROW) |
68 self.LeftGridSizer.AddSizer(left_staticboxsizer, border=5, flag=wx.GROW) |
69 |
69 |
70 # Create Library panel and add it to static box |
70 # Create Library panel and add it to static box |
71 self.LibraryPanel = LibraryPanel(self) |
71 self.LibraryPanel = LibraryPanel(self) |
72 self.LibraryPanel.SetInitialSize(wx.Size(-1, 400)) |
72 self.LibraryPanel.SetInitialSize(wx.Size(-1, 400)) |
73 |
73 |
74 # Set function to call when selection in Library panel changed |
74 # Set function to call when selection in Library panel changed |
75 setattr(self.LibraryPanel, "_OnTreeItemSelected", |
75 setattr(self.LibraryPanel, "_OnTreeItemSelected", |
76 self.OnLibraryTreeItemSelected) |
76 self.OnLibraryTreeItemSelected) |
77 left_staticboxsizer.AddWindow(self.LibraryPanel, 1, border=5, |
77 left_staticboxsizer.AddWindow(self.LibraryPanel, 1, border=5, |
78 flag=wx.GROW|wx.TOP) |
78 flag=wx.GROW|wx.TOP) |
79 |
79 |
80 # Create sizer for other block parameters |
80 # Create sizer for other block parameters |
81 top_right_gridsizer = wx.FlexGridSizer(cols=2, hgap=0, rows=4, vgap=5) |
81 top_right_gridsizer = wx.FlexGridSizer(cols=2, hgap=0, rows=4, vgap=5) |
82 top_right_gridsizer.AddGrowableCol(1) |
82 top_right_gridsizer.AddGrowableCol(1) |
83 self.RightGridSizer.AddSizer(top_right_gridsizer, flag=wx.GROW) |
83 self.RightGridSizer.AddSizer(top_right_gridsizer, flag=wx.GROW) |
84 |
84 |
85 # Create label for block name |
85 # Create label for block name |
86 name_label = wx.StaticText(self, label=_('Name:')) |
86 name_label = wx.StaticText(self, label=_('Name:')) |
87 top_right_gridsizer.AddWindow(name_label, |
87 top_right_gridsizer.AddWindow(name_label, |
88 flag=wx.ALIGN_CENTER_VERTICAL) |
88 flag=wx.ALIGN_CENTER_VERTICAL) |
89 |
89 |
90 # Create text control for defining block name |
90 # Create text control for defining block name |
91 self.BlockName = wx.TextCtrl(self) |
91 self.BlockName = wx.TextCtrl(self) |
92 self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.BlockName) |
92 self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.BlockName) |
93 top_right_gridsizer.AddWindow(self.BlockName, flag=wx.GROW) |
93 top_right_gridsizer.AddWindow(self.BlockName, flag=wx.GROW) |
94 |
94 |
95 # Create label for extended block input number |
95 # Create label for extended block input number |
96 inputs_label = wx.StaticText(self, label=_('Inputs:')) |
96 inputs_label = wx.StaticText(self, label=_('Inputs:')) |
97 top_right_gridsizer.AddWindow(inputs_label, |
97 top_right_gridsizer.AddWindow(inputs_label, |
98 flag=wx.ALIGN_CENTER_VERTICAL) |
98 flag=wx.ALIGN_CENTER_VERTICAL) |
99 |
99 |
100 # Create spin control for defining extended block input number |
100 # Create spin control for defining extended block input number |
101 self.Inputs = wx.SpinCtrl(self, min=2, max=20, |
101 self.Inputs = wx.SpinCtrl(self, min=2, max=20, |
102 style=wx.SP_ARROW_KEYS) |
102 style=wx.SP_ARROW_KEYS) |
103 self.Bind(wx.EVT_SPINCTRL, self.OnInputsChanged, self.Inputs) |
103 self.Bind(wx.EVT_SPINCTRL, self.OnInputsChanged, self.Inputs) |
104 top_right_gridsizer.AddWindow(self.Inputs, flag=wx.GROW) |
104 top_right_gridsizer.AddWindow(self.Inputs, flag=wx.GROW) |
105 |
105 |
106 # Create label for block execution order |
106 # Create label for block execution order |
107 execution_order_label = wx.StaticText(self, |
107 execution_order_label = wx.StaticText(self, |
108 label=_('Execution Order:')) |
108 label=_('Execution Order:')) |
109 top_right_gridsizer.AddWindow(execution_order_label, |
109 top_right_gridsizer.AddWindow(execution_order_label, |
110 flag=wx.ALIGN_CENTER_VERTICAL) |
110 flag=wx.ALIGN_CENTER_VERTICAL) |
111 |
111 |
112 # Create spin control for defining block execution order |
112 # Create spin control for defining block execution order |
113 self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS) |
113 self.ExecutionOrder = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS) |
114 self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, |
114 self.Bind(wx.EVT_SPINCTRL, self.OnExecutionOrderChanged, |
115 self.ExecutionOrder) |
115 self.ExecutionOrder) |
116 top_right_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW) |
116 top_right_gridsizer.AddWindow(self.ExecutionOrder, flag=wx.GROW) |
117 |
117 |
118 # Create label for block execution control |
118 # Create label for block execution control |
119 execution_control_label = wx.StaticText(self, |
119 execution_control_label = wx.StaticText(self, |
120 label=_('Execution Control:')) |
120 label=_('Execution Control:')) |
121 top_right_gridsizer.AddWindow(execution_control_label, |
121 top_right_gridsizer.AddWindow(execution_control_label, |
122 flag=wx.ALIGN_CENTER_VERTICAL) |
122 flag=wx.ALIGN_CENTER_VERTICAL) |
123 |
123 |
124 # Create check box to enable block execution control |
124 # Create check box to enable block execution control |
125 self.ExecutionControl = wx.CheckBox(self) |
125 self.ExecutionControl = wx.CheckBox(self) |
126 self.Bind(wx.EVT_CHECKBOX, self.OnExecutionOrderChanged, |
126 self.Bind(wx.EVT_CHECKBOX, self.OnExecutionOrderChanged, |
127 self.ExecutionControl) |
127 self.ExecutionControl) |
128 top_right_gridsizer.AddWindow(self.ExecutionControl, flag=wx.GROW) |
128 top_right_gridsizer.AddWindow(self.ExecutionControl, flag=wx.GROW) |
129 |
129 |
130 # Add preview panel and associated label to sizers |
130 # Add preview panel and associated label to sizers |
131 self.RightGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW) |
131 self.RightGridSizer.AddWindow(self.PreviewLabel, flag=wx.GROW) |
132 self.RightGridSizer.AddWindow(self.Preview, flag=wx.GROW) |
132 self.RightGridSizer.AddWindow(self.Preview, flag=wx.GROW) |
133 |
133 |
134 # Add buttons sizer to sizers |
134 # Add buttons sizer to sizers |
135 self.MainSizer.AddSizer(self.ButtonSizer, border=20, |
135 self.MainSizer.AddSizer(self.ButtonSizer, border=20, |
136 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
136 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
137 |
137 |
138 # Dictionary containing correspondence between parameter exchanged and |
138 # Dictionary containing correspondence between parameter exchanged and |
139 # control to fill with parameter value |
139 # control to fill with parameter value |
140 self.ParamsControl = { |
140 self.ParamsControl = { |
141 "extension": self.Inputs, |
141 "extension": self.Inputs, |
142 "executionOrder": self.ExecutionOrder, |
142 "executionOrder": self.ExecutionOrder, |
143 "executionControl": self.ExecutionControl |
143 "executionControl": self.ExecutionControl |
144 } |
144 } |
145 |
145 |
146 # Init controls value and sensibility |
146 # Init controls value and sensibility |
147 self.BlockName.SetValue("") |
147 self.BlockName.SetValue("") |
148 self.BlockName.Enable(False) |
148 self.BlockName.Enable(False) |
149 self.Inputs.Enable(False) |
149 self.Inputs.Enable(False) |
150 |
150 |
151 # Variable containing last name typed |
151 # Variable containing last name typed |
152 self.CurrentBlockName = None |
152 self.CurrentBlockName = None |
153 |
153 |
154 # Refresh Library panel values |
154 # Refresh Library panel values |
155 self.LibraryPanel.SetBlockList(controller.GetBlockTypes(tagname)) |
155 self.LibraryPanel.SetBlockList(controller.GetBlockTypes(tagname)) |
156 self.Fit() |
156 self.Fit() |
157 self.LibraryPanel.SetFocus() |
157 self.LibraryPanel.SetFocus() |
158 |
158 |
159 def SetValues(self, values): |
159 def SetValues(self, values): |
160 """ |
160 """ |
161 Set default block parameters |
161 Set default block parameters |
162 @param values: Block parameters values |
162 @param values: Block parameters values |
163 """ |
163 """ |
164 # Extract block type defined in parameters |
164 # Extract block type defined in parameters |
165 blocktype = values.get("type", None) |
165 blocktype = values.get("type", None) |
166 |
166 |
167 # Select block type in library panel |
167 # Select block type in library panel |
168 if blocktype is not None: |
168 if blocktype is not None: |
169 self.LibraryPanel.SelectTreeItem(blocktype, |
169 self.LibraryPanel.SelectTreeItem(blocktype, |
170 values.get("inputs", None)) |
170 values.get("inputs", None)) |
171 |
171 |
172 # Define regular expression for determine if block name is block |
172 # Define regular expression for determine if block name is block |
173 # default name |
173 # default name |
174 default_name_model = GetBlockTypeDefaultNameModel(blocktype) |
174 default_name_model = GetBlockTypeDefaultNameModel(blocktype) |
175 |
175 |
176 # For each parameters defined, set corresponding control value |
176 # For each parameters defined, set corresponding control value |
177 for name, value in values.items(): |
177 for name, value in values.items(): |
178 |
178 |
179 # Parameter is block name |
179 # Parameter is block name |
180 if name == "name": |
180 if name == "name": |
181 if value != "": |
181 if value != "": |
182 # Set default graphic element name for testing |
182 # Set default graphic element name for testing |
183 self.DefaultElementName = value |
183 self.DefaultElementName = value |
184 |
184 |
185 # Test if block name is type default block name and save |
185 # Test if block name is type default block name and save |
186 # block name if not (name have been typed by user) |
186 # block name if not (name have been typed by user) |
187 if default_name_model.match(value) is None: |
187 if default_name_model.match(value) is None: |
188 self.CurrentBlockName = value |
188 self.CurrentBlockName = value |
189 |
189 |
190 self.BlockName.ChangeValue(value) |
190 self.BlockName.ChangeValue(value) |
191 |
191 |
192 # Set value of other controls |
192 # Set value of other controls |
193 else: |
193 else: |
194 control = self.ParamsControl.get(name, None) |
194 control = self.ParamsControl.get(name, None) |
195 if control is not None: |
195 if control is not None: |
196 control.SetValue(value) |
196 control.SetValue(value) |
197 |
197 |
198 # Refresh preview panel |
198 # Refresh preview panel |
199 self.RefreshPreview() |
199 self.RefreshPreview() |
200 |
200 |
201 def GetValues(self): |
201 def GetValues(self): |
202 """ |
202 """ |
209 values["width"], values["height"] = self.Element.GetSize() |
209 values["width"], values["height"] = self.Element.GetSize() |
210 values.update({ |
210 values.update({ |
211 name: control.GetValue() |
211 name: control.GetValue() |
212 for name, control in self.ParamsControl.iteritems()}) |
212 for name, control in self.ParamsControl.iteritems()}) |
213 return values |
213 return values |
214 |
214 |
215 def OnOK(self, event): |
215 def OnOK(self, event): |
216 """ |
216 """ |
217 Called when dialog OK button is pressed |
217 Called when dialog OK button is pressed |
218 Test if parameters defined are valid |
218 Test if parameters defined are valid |
219 @param event: wx.Event from OK button |
219 @param event: wx.Event from OK button |
220 """ |
220 """ |
221 message = None |
221 message = None |
222 |
222 |
223 # Get block type selected |
223 # Get block type selected |
224 selected = self.LibraryPanel.GetSelectedBlock() |
224 selected = self.LibraryPanel.GetSelectedBlock() |
225 |
225 |
226 # Get block type name and if block is a function block |
226 # Get block type name and if block is a function block |
227 block_name = self.BlockName.GetValue() |
227 block_name = self.BlockName.GetValue() |
228 name_enabled = self.BlockName.IsEnabled() |
228 name_enabled = self.BlockName.IsEnabled() |
229 |
229 |
230 # Test that a type has been selected for block |
230 # Test that a type has been selected for block |
231 if selected is None: |
231 if selected is None: |
232 message = _("Form isn't complete. Valid block type must be selected!") |
232 message = _("Form isn't complete. Valid block type must be selected!") |
233 |
233 |
234 # Test, if block is a function block, that a name have been defined |
234 # Test, if block is a function block, that a name have been defined |
235 elif name_enabled and block_name == "": |
235 elif name_enabled and block_name == "": |
236 message = _("Form isn't complete. Name must be filled!") |
236 message = _("Form isn't complete. Name must be filled!") |
237 |
237 |
238 # Show error message if an error is detected |
238 # Show error message if an error is detected |
239 if message is not None: |
239 if message is not None: |
240 self.ShowErrorMessage(message) |
240 self.ShowErrorMessage(message) |
241 |
241 |
242 # Test block name validity if necessary |
242 # Test block name validity if necessary |
243 elif not name_enabled or self.TestElementName(block_name): |
243 elif not name_enabled or self.TestElementName(block_name): |
244 # Call BlockPreviewDialog function |
244 # Call BlockPreviewDialog function |
245 BlockPreviewDialog.OnOK(self, event) |
245 BlockPreviewDialog.OnOK(self, event) |
246 |
246 |
247 def OnLibraryTreeItemSelected(self, event): |
247 def OnLibraryTreeItemSelected(self, event): |
248 """ |
248 """ |
249 Called when block type selected in library panel |
249 Called when block type selected in library panel |
250 @param event: wx.TreeEvent |
250 @param event: wx.TreeEvent |
251 """ |
251 """ |
252 # Get type selected in library panel |
252 # Get type selected in library panel |
253 values = self.LibraryPanel.GetSelectedBlock() |
253 values = self.LibraryPanel.GetSelectedBlock() |
254 |
254 |
255 # Get block type informations |
255 # Get block type informations |
256 blocktype = (self.Controller.GetBlockType(values["type"], |
256 blocktype = (self.Controller.GetBlockType(values["type"], |
257 values["inputs"]) |
257 values["inputs"]) |
258 if values is not None else None) |
258 if values is not None else None) |
259 |
259 |
260 # Set input number spin control according to block type informations |
260 # Set input number spin control according to block type informations |
261 if blocktype is not None: |
261 if blocktype is not None: |
262 self.Inputs.SetValue(len(blocktype["inputs"])) |
262 self.Inputs.SetValue(len(blocktype["inputs"])) |
263 self.Inputs.Enable(blocktype["extensible"]) |
263 self.Inputs.Enable(blocktype["extensible"]) |
264 else: |
264 else: |
265 self.Inputs.SetValue(2) |
265 self.Inputs.SetValue(2) |
266 self.Inputs.Enable(False) |
266 self.Inputs.Enable(False) |
267 |
267 |
268 # Update block name with default value if block type is a function and |
268 # Update block name with default value if block type is a function and |
269 # current block name wasn't typed by user |
269 # current block name wasn't typed by user |
270 if blocktype is not None and blocktype["type"] != "function": |
270 if blocktype is not None and blocktype["type"] != "function": |
271 self.BlockName.Enable(True) |
271 self.BlockName.Enable(True) |
272 |
272 |
273 if self.CurrentBlockName is None: |
273 if self.CurrentBlockName is None: |
274 # Generate new block name according to block type, taking |
274 # Generate new block name according to block type, taking |
275 # default element name if it was already a default name for this |
275 # default element name if it was already a default name for this |
276 # block type |
276 # block type |
277 default_name_model = GetBlockTypeDefaultNameModel(values["type"]) |
277 default_name_model = GetBlockTypeDefaultNameModel(values["type"]) |
278 block_name = ( |
278 block_name = ( |
279 self.DefaultElementName |
279 self.DefaultElementName |
280 if (self.DefaultElementName is not None and |
280 if (self.DefaultElementName is not None and |
281 default_name_model.match(self.DefaultElementName)) |
281 default_name_model.match(self.DefaultElementName)) |
282 else self.Controller.GenerateNewName( |
282 else self.Controller.GenerateNewName( |
283 self.TagName, None, values["type"]+"%d", 0)) |
283 self.TagName, None, values["type"]+"%d", 0)) |
284 else: |
284 else: |
285 block_name = self.CurrentBlockName |
285 block_name = self.CurrentBlockName |
286 |
286 |
287 self.BlockName.ChangeValue(block_name) |
287 self.BlockName.ChangeValue(block_name) |
288 else: |
288 else: |
289 self.BlockName.Enable(False) |
289 self.BlockName.Enable(False) |
290 self.BlockName.ChangeValue("") |
290 self.BlockName.ChangeValue("") |
291 |
291 |
292 # Refresh preview panel |
292 # Refresh preview panel |
293 self.RefreshPreview() |
293 self.RefreshPreview() |
294 |
294 |
295 def OnNameChanged(self, event): |
295 def OnNameChanged(self, event): |
296 """ |
296 """ |
297 Called when block name value changed |
297 Called when block name value changed |
298 @param event: wx.TextEvent |
298 @param event: wx.TextEvent |
299 """ |
299 """ |
300 if self.BlockName.IsEnabled(): |
300 if self.BlockName.IsEnabled(): |
301 # Save block name typed by user |
301 # Save block name typed by user |
302 self.CurrentBlockName = self.BlockName.GetValue() |
302 self.CurrentBlockName = self.BlockName.GetValue() |
303 self.RefreshPreview() |
303 self.RefreshPreview() |
304 event.Skip() |
304 event.Skip() |
305 |
305 |
306 def OnInputsChanged(self, event): |
306 def OnInputsChanged(self, event): |
307 """ |
307 """ |
308 Called when block inputs number changed |
308 Called when block inputs number changed |
309 @param event: wx.SpinEvent |
309 @param event: wx.SpinEvent |
310 """ |
310 """ |
311 if self.Inputs.IsEnabled(): |
311 if self.Inputs.IsEnabled(): |
312 self.RefreshPreview() |
312 self.RefreshPreview() |
313 event.Skip() |
313 event.Skip() |
314 |
314 |
315 def OnExecutionOrderChanged(self, event): |
315 def OnExecutionOrderChanged(self, event): |
316 """ |
316 """ |
317 Called when block execution order value changed |
317 Called when block execution order value changed |
318 @param event: wx.SpinEvent |
318 @param event: wx.SpinEvent |
319 """ |
319 """ |
320 self.RefreshPreview() |
320 self.RefreshPreview() |
321 event.Skip() |
321 event.Skip() |
322 |
322 |
323 def OnExecutionControlChanged(self, event): |
323 def OnExecutionControlChanged(self, event): |
324 """ |
324 """ |
325 Called when block execution control value changed |
325 Called when block execution control value changed |
326 @param event: wx.SpinEvent |
326 @param event: wx.SpinEvent |
327 """ |
327 """ |
328 self.RefreshPreview() |
328 self.RefreshPreview() |
329 event.Skip() |
329 event.Skip() |
330 |
330 |
331 def RefreshPreview(self): |
331 def RefreshPreview(self): |
332 """ |
332 """ |
333 Refresh preview panel of graphic element |
333 Refresh preview panel of graphic element |
334 Override BlockPreviewDialog function |
334 Override BlockPreviewDialog function |
335 """ |
335 """ |
336 # Get type selected in library panel |
336 # Get type selected in library panel |
337 values = self.LibraryPanel.GetSelectedBlock() |
337 values = self.LibraryPanel.GetSelectedBlock() |
338 |
338 |
339 # If a block type is selected in library panel |
339 # If a block type is selected in library panel |
340 if values is not None: |
340 if values is not None: |
341 # Set graphic element displayed, creating a FBD block element |
341 # Set graphic element displayed, creating a FBD block element |
342 self.Element = FBD_Block(self.Preview, values["type"], |
342 self.Element = FBD_Block(self.Preview, values["type"], |
343 (self.BlockName.GetValue() |
343 (self.BlockName.GetValue() |
344 if self.BlockName.IsEnabled() |
344 if self.BlockName.IsEnabled() |
345 else ""), |
345 else ""), |
346 extension = self.Inputs.GetValue(), |
346 extension = self.Inputs.GetValue(), |
347 inputs = values["inputs"], |
347 inputs = values["inputs"], |
348 executionControl = self.ExecutionControl.GetValue(), |
348 executionControl = self.ExecutionControl.GetValue(), |
349 executionOrder = self.ExecutionOrder.GetValue()) |
349 executionOrder = self.ExecutionOrder.GetValue()) |
350 |
350 |
351 # Reset graphic element displayed |
351 # Reset graphic element displayed |
352 else: |
352 else: |
353 self.Element = None |
353 self.Element = None |
354 |
354 |
355 # Call BlockPreviewDialog function |
355 # Call BlockPreviewDialog function |
356 BlockPreviewDialog.RefreshPreview(self) |
356 BlockPreviewDialog.RefreshPreview(self) |