22 #License along with this library; if not, write to the Free Software |
22 #License along with this library; if not, write to the Free Software |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 |
24 |
25 import wx |
25 import wx |
26 |
26 |
27 from graphics import * |
27 from graphics.GraphicCommons import CONNECTOR, CONTINUATION |
|
28 from graphics.FBD_Objects import FBD_Connector |
|
29 from BlockPreviewDialog import BlockPreviewDialog |
28 |
30 |
29 #------------------------------------------------------------------------------- |
31 #------------------------------------------------------------------------------- |
30 # Create New Connection Dialog |
32 # Set Connection Parameters Dialog |
31 #------------------------------------------------------------------------------- |
33 #------------------------------------------------------------------------------- |
32 |
34 |
33 class ConnectionDialog(wx.Dialog): |
35 class ConnectionDialog(BlockPreviewDialog): |
34 |
36 |
35 def __init__(self, parent, controller, apply_button=False): |
37 def __init__(self, parent, controller, tagname, apply_button=False): |
36 wx.Dialog.__init__(self, parent, |
38 """ |
|
39 Constructor |
|
40 @param parent: Parent wx.Window of dialog for modal |
|
41 @param controller: Reference to project controller |
|
42 @param tagname: Tagname of project POU edited |
|
43 @param apply_button: Enable button for applying connector modification |
|
44 to all connector having the same name in POU (default: False) |
|
45 """ |
|
46 BlockPreviewDialog.__init__(self, parent, controller, tagname, |
37 size=wx.Size(350, 220), title=_('Connection Properties')) |
47 size=wx.Size(350, 220), title=_('Connection Properties')) |
38 |
48 |
|
49 # Create dialog main sizer |
39 main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
50 main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
40 main_sizer.AddGrowableCol(0) |
51 main_sizer.AddGrowableCol(0) |
41 main_sizer.AddGrowableRow(0) |
52 main_sizer.AddGrowableRow(0) |
42 |
53 |
|
54 # Create a sizer for dividing FBD connection parameters in two columns |
43 column_sizer = wx.BoxSizer(wx.HORIZONTAL) |
55 column_sizer = wx.BoxSizer(wx.HORIZONTAL) |
44 main_sizer.AddSizer(column_sizer, border=20, |
56 main_sizer.AddSizer(column_sizer, border=20, |
45 flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
57 flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
46 |
58 |
|
59 # Create a sizer for left column |
47 left_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5) |
60 left_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=5, vgap=5) |
48 left_gridsizer.AddGrowableCol(0) |
61 left_gridsizer.AddGrowableCol(0) |
49 column_sizer.AddSizer(left_gridsizer, 1, border=5, |
62 column_sizer.AddSizer(left_gridsizer, 1, border=5, |
50 flag=wx.GROW|wx.RIGHT) |
63 flag=wx.GROW|wx.RIGHT) |
51 |
64 |
|
65 # Create label for connection type |
52 type_label = wx.StaticText(self, label=_('Type:')) |
66 type_label = wx.StaticText(self, label=_('Type:')) |
53 left_gridsizer.AddWindow(type_label, flag=wx.GROW) |
67 left_gridsizer.AddWindow(type_label, flag=wx.GROW) |
54 |
68 |
55 self.ConnectorRadioButton = wx.RadioButton(self, |
69 # Create radio buttons for selecting connection type |
56 label=_('Connector'), style=wx.RB_GROUP) |
70 self.ConnectionRadioButtons = {} |
57 self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, self.ConnectorRadioButton) |
71 first = True |
58 self.ConnectorRadioButton.SetValue(True) |
72 for type, label in [(CONNECTOR, _('Connector')), |
59 left_gridsizer.AddWindow(self.ConnectorRadioButton, flag=wx.GROW) |
73 (CONTINUATION, _('Continuation'))]: |
60 |
74 radio_button = wx.RadioButton(self, label=label, |
61 self.ConnectionRadioButton = wx.RadioButton(self, label=_('Continuation')) |
75 style=(wx.RB_GROUP if first else wx.RB_SINGLE)) |
62 self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, self.ConnectionRadioButton) |
76 radio_button.SetValue(first) |
63 left_gridsizer.AddWindow(self.ConnectionRadioButton, flag=wx.GROW) |
77 self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, radio_button) |
64 |
78 left_gridsizer.AddWindow(radio_button, flag=wx.GROW) |
|
79 self.ConnectionRadioButtons[type] = radio_button |
|
80 first = False |
|
81 |
|
82 # Create label for connection name |
65 name_label = wx.StaticText(self, label=_('Name:')) |
83 name_label = wx.StaticText(self, label=_('Name:')) |
66 left_gridsizer.AddWindow(name_label, flag=wx.GROW) |
84 left_gridsizer.AddWindow(name_label, flag=wx.GROW) |
67 |
85 |
|
86 # Create text control for defining connection name |
68 self.ConnectionName = wx.TextCtrl(self) |
87 self.ConnectionName = wx.TextCtrl(self) |
69 self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.ConnectionName) |
88 self.Bind(wx.EVT_TEXT, self.OnNameChanged, self.ConnectionName) |
70 left_gridsizer.AddWindow(self.ConnectionName, flag=wx.GROW) |
89 left_gridsizer.AddWindow(self.ConnectionName, flag=wx.GROW) |
71 |
90 |
|
91 # Create a sizer for right column |
72 right_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) |
92 right_gridsizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) |
73 right_gridsizer.AddGrowableCol(0) |
93 right_gridsizer.AddGrowableCol(0) |
74 right_gridsizer.AddGrowableRow(1) |
94 right_gridsizer.AddGrowableRow(1) |
75 column_sizer.AddSizer(right_gridsizer, 1, border=5, |
95 column_sizer.AddSizer(right_gridsizer, 1, border=5, |
76 flag=wx.GROW|wx.LEFT) |
96 flag=wx.GROW|wx.LEFT) |
77 |
97 |
78 preview_label = wx.StaticText(self, label=_('Preview:')) |
98 # Add preview panel and associated label to sizers |
79 right_gridsizer.AddWindow(preview_label, flag=wx.GROW) |
99 right_gridsizer.AddWindow(self.PreviewLabel, flag=wx.GROW) |
80 |
|
81 self.Preview = wx.Panel(self, |
|
82 style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
83 self.Preview.SetBackgroundColour(wx.Colour(255,255,255)) |
|
84 setattr(self.Preview, "GetDrawingMode", lambda:FREEDRAWING_MODE) |
|
85 setattr(self.Preview, "GetScaling", lambda:None) |
|
86 setattr(self.Preview, "IsOfType", controller.IsOfType) |
|
87 self.Preview.Bind(wx.EVT_PAINT, self.OnPaint) |
|
88 right_gridsizer.AddWindow(self.Preview, flag=wx.GROW) |
100 right_gridsizer.AddWindow(self.Preview, flag=wx.GROW) |
89 |
101 |
90 button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
102 # Add buttons sizer to sizers |
91 self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton()) |
103 main_sizer.AddSizer(self.ButtonSizer, border=20, |
92 main_sizer.AddSizer(button_sizer, border=20, |
|
93 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
104 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
94 |
105 |
|
106 # Add button for applying connection name modification to all connection |
|
107 # of POU |
95 if apply_button: |
108 if apply_button: |
96 self.ApplyToAllButton = wx.Button(self, label=_("Propagate Name")) |
109 self.ApplyToAllButton = wx.Button(self, label=_("Propagate Name")) |
97 self.ApplyToAllButton.SetToolTipString( |
110 self.ApplyToAllButton.SetToolTipString( |
98 _("Apply name modification to all continuations with the same name")) |
111 _("Apply name modification to all continuations with the same name")) |
99 self.Bind(wx.EVT_BUTTON, self.OnApplyToAll, self.ApplyToAllButton) |
112 self.Bind(wx.EVT_BUTTON, self.OnApplyToAll, self.ApplyToAllButton) |
100 button_sizer.AddWindow(self.ApplyToAllButton) |
113 self.ButtonSizer.AddWindow(self.ApplyToAllButton, border=10, |
|
114 flag=wx.LEFT) |
|
115 else: |
|
116 self.ConnectionName.ChangeValue( |
|
117 controller.GenerateNewName( |
|
118 tagname, None, "Connection%d", 0)) |
101 |
119 |
102 self.SetSizer(main_sizer) |
120 self.SetSizer(main_sizer) |
103 |
121 |
104 self.Connection = None |
122 # Connector radio button is default control having keyboard focus |
105 self.MinConnectionSize = None |
123 self.ConnectionRadioButtons[CONNECTOR].SetFocus() |
106 |
|
107 self.PouNames = [] |
|
108 self.PouElementNames = [] |
|
109 |
|
110 self.ConnectorRadioButton.SetFocus() |
|
111 |
|
112 def SetPreviewFont(self, font): |
|
113 self.Preview.SetFont(font) |
|
114 |
|
115 def SetMinConnectionSize(self, size): |
|
116 self.MinConnectionSize = size |
|
117 |
124 |
118 def SetValues(self, values): |
125 def SetValues(self, values): |
|
126 """ |
|
127 Set default connection parameters |
|
128 @param values: Connection parameters values |
|
129 """ |
|
130 # For each parameters defined, set corresponding control value |
119 for name, value in values.items(): |
131 for name, value in values.items(): |
|
132 |
|
133 # Parameter is connection type |
120 if name == "type": |
134 if name == "type": |
121 if value == CONNECTOR: |
135 self.ConnectionRadioButtons[value].SetValue(True) |
122 self.ConnectorRadioButton.SetValue(True) |
136 |
123 elif value == CONTINUATION: |
137 # Parameter is connection name |
124 self.ConnectionRadioButton.SetValue(True) |
|
125 elif name == "name": |
138 elif name == "name": |
126 self.ConnectionName.SetValue(value) |
139 self.ConnectionName.SetValue(value) |
|
140 |
|
141 # Refresh preview panel |
127 self.RefreshPreview() |
142 self.RefreshPreview() |
128 |
143 |
129 def GetValues(self): |
144 def GetValues(self): |
130 values = {} |
145 """ |
131 if self.ConnectorRadioButton.GetValue(): |
146 Return connection parameters defined in dialog |
132 values["type"] = CONNECTOR |
147 @return: {parameter_name: parameter_value,...} |
133 else: |
148 """ |
134 values["type"] = CONTINUATION |
149 values = { |
135 values["name"] = self.ConnectionName.GetValue() |
150 "type": (CONNECTOR |
136 values["width"], values["height"] = self.Connection.GetSize() |
151 if self.ConnectionRadioButtons[CONNECTOR].GetValue() |
|
152 else CONTINUATION), |
|
153 "name": self.ConnectionName.GetValue()} |
|
154 values["width"], values["height"] = self.Element.GetSize() |
137 return values |
155 return values |
138 |
156 |
139 def SetPouNames(self, pou_names): |
157 def TestConnectionName(self): |
140 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
158 """ |
141 |
159 Test that connection name is valid |
142 def SetPouElementNames(self, element_names): |
160 @return: True if connection name is valid |
143 self.PouElementNames = [element_name.upper() for element_name in element_names] |
161 """ |
144 |
|
145 def TestName(self): |
|
146 message = None |
162 message = None |
|
163 |
|
164 # Get connection name typed by user |
147 connection_name = self.ConnectionName.GetValue() |
165 connection_name = self.ConnectionName.GetValue() |
|
166 |
|
167 # Test that a name have been defined |
148 if connection_name == "": |
168 if connection_name == "": |
149 message = _("Form isn't complete. Name must be filled!") |
169 message = _("Form isn't complete. Name must be filled!") |
150 elif not TestIdentifier(connection_name): |
170 |
151 message = _("\"%s\" is not a valid identifier!") % connection_name |
171 # If an error have been identify, show error message dialog |
152 elif connection_name.upper() in IEC_KEYWORDS: |
|
153 message = _("\"%s\" is a keyword. It can't be used!") % connection_name |
|
154 elif connection_name.upper() in self.PouNames: |
|
155 message = _("\"%s\" pou already exists!") % connection_name |
|
156 elif connection_name.upper() in self.PouElementNames: |
|
157 message = _("\"%s\" element for this pou already exists!") % connection_name |
|
158 if message is not None: |
172 if message is not None: |
159 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) |
173 self.ShowErrorMessage(message) |
160 dialog.ShowModal() |
174 # Test failed |
161 dialog.Destroy() |
|
162 return False |
175 return False |
163 return True |
176 |
|
177 # Return result of element name test |
|
178 return self.TestElementName(connection_name) |
164 |
179 |
165 def OnOK(self, event): |
180 def OnOK(self, event): |
166 if self.TestName(): |
181 """ |
|
182 Called when dialog OK button is pressed |
|
183 Test if connection name is valid |
|
184 @param event: wx.Event from OK button |
|
185 """ |
|
186 # Close dialog if connection name is valid |
|
187 if self.TestConnectionName(): |
167 self.EndModal(wx.ID_OK) |
188 self.EndModal(wx.ID_OK) |
168 |
189 |
169 def OnApplyToAll(self, event): |
190 def OnApplyToAll(self, event): |
170 if self.TestName(): |
191 """ |
|
192 Called when Apply To All button is pressed |
|
193 Test if connection name is valid |
|
194 @param event: wx.Event from OK button |
|
195 """ |
|
196 # Close dialog if connection name is valid |
|
197 if self.TestConnectionName(): |
171 self.EndModal(wx.ID_YESTOALL) |
198 self.EndModal(wx.ID_YESTOALL) |
172 |
199 |
173 def OnTypeChanged(self, event): |
200 def OnTypeChanged(self, event): |
|
201 """ |
|
202 Called when connection type changed |
|
203 @param event: wx.RadioButtonEvent |
|
204 """ |
174 self.RefreshPreview() |
205 self.RefreshPreview() |
175 event.Skip() |
206 event.Skip() |
176 |
207 |
177 def OnNameChanged(self, event): |
208 def OnNameChanged(self, event): |
|
209 """ |
|
210 Called when connection name value changed |
|
211 @param event: wx.TextEvent |
|
212 """ |
178 self.RefreshPreview() |
213 self.RefreshPreview() |
179 event.Skip() |
214 event.Skip() |
180 |
215 |
181 def RefreshPreview(self): |
216 def RefreshPreview(self): |
182 dc = wx.ClientDC(self.Preview) |
217 """ |
183 dc.SetFont(self.Preview.GetFont()) |
218 Refresh preview panel of graphic element |
184 dc.Clear() |
219 Override BlockPreviewDialog function |
185 if self.ConnectorRadioButton.GetValue(): |
220 """ |
186 self.Connection = FBD_Connector(self.Preview, CONNECTOR, self.ConnectionName.GetValue()) |
221 # Set graphic element displayed, creating a FBD connection element |
187 else: |
222 self.Element = FBD_Connector(self.Preview, |
188 self.Connection = FBD_Connector(self.Preview, CONTINUATION, self.ConnectionName.GetValue()) |
223 (CONNECTOR |
189 width, height = self.MinConnectionSize |
224 if self.ConnectionRadioButtons[CONNECTOR].GetValue() |
190 min_width, min_height = self.Connection.GetMinSize() |
225 else CONTINUATION), |
191 width, height = max(min_width, width), max(min_height, height) |
226 self.ConnectionName.GetValue()) |
192 self.Connection.SetSize(width, height) |
227 |
193 clientsize = self.Preview.GetClientSize() |
228 # Call BlockPreviewDialog function |
194 x = (clientsize.width - width) / 2 |
229 BlockPreviewDialog.RefreshPreview(self) |
195 y = (clientsize.height - height) / 2 |
230 |
196 self.Connection.SetPosition(x, y) |
|
197 self.Connection.Draw(dc) |
|
198 |
|
199 def OnPaint(self, event): |
|
200 self.RefreshPreview() |
|
201 event.Skip() |
|