andrej@1571: #!/usr/bin/env python
Laurent@814: # -*- coding: utf-8 -*-
Laurent@814: 
andrej@1571: # This file is part of Beremiz, a Integrated Development Environment for
andrej@1571: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
andrej@1571: #
andrej@1571: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
andrej@1696: # Copyright (C) 2017: Andrey Skvortsov <andrej.skvortzov@gmail.com>
andrej@1571: #
andrej@1571: # See COPYING file for copyrights details.
andrej@1571: #
andrej@1571: # This program is free software; you can redistribute it and/or
andrej@1571: # modify it under the terms of the GNU General Public License
andrej@1571: # as published by the Free Software Foundation; either version 2
andrej@1571: # of the License, or (at your option) any later version.
andrej@1571: #
andrej@1571: # This program is distributed in the hope that it will be useful,
andrej@1571: # but WITHOUT ANY WARRANTY; without even the implied warranty of
andrej@1571: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
andrej@1571: # GNU General Public License for more details.
andrej@1571: #
andrej@1571: # You should have received a copy of the GNU General Public License
andrej@1571: # along with this program; if not, write to the Free Software
andrej@1571: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Laurent@814: 
kinsamanka@3750: 
Laurent@814: import wx
Laurent@814: 
Laurent@1252: from graphics.SFC_Objects import SFC_Transition
andrej@1853: from dialogs.BlockPreviewDialog import BlockPreviewDialog
Laurent@814: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@1252: #                        Set Transition Parameters Dialog
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@1252: 
Laurent@1252: class SFCTransitionDialog(BlockPreviewDialog):
andrej@1736:     """
andrej@1736:     Class that implements a dialog for defining parameters of a transition graphic
andrej@1736:     element
andrej@1736:     """
andrej@1730: 
Laurent@1252:     def __init__(self, parent, controller, tagname, connection=True):
Laurent@1252:         """
Laurent@1252:         Constructor
Laurent@1252:         @param parent: Parent wx.Window of dialog for modal
Laurent@1252:         @param controller: Reference to project controller
Laurent@1252:         @param tagname: Tagname of project POU edited
Laurent@1252:         @param connection: True if transition value can be defined by a
Laurent@1252:         connection (default: True)
Laurent@1252:         """
Laurent@1252:         BlockPreviewDialog.__init__(self, parent, controller, tagname,
andrej@1768:                                     title=_('Edit transition'))
andrej@1730: 
Laurent@1252:         # Init common sizers
Laurent@1252:         self._init_sizers(2, 0, 8, None, 2, 1)
andrej@1730: 
Laurent@1252:         # Create label for transition type
Laurent@814:         type_label = wx.StaticText(self, label=_('Type:'))
edouard@3303:         self.LeftGridSizer.Add(type_label, flag=wx.GROW)
andrej@1730: 
Laurent@1252:         # Create combo box for selecting reference value
Laurent@1252:         reference = wx.ComboBox(self, style=wx.CB_READONLY)
Laurent@1252:         reference.Append("")
Laurent@1252:         for transition in controller.GetEditedElementTransitions(tagname):
Laurent@1252:             reference.Append(transition)
Laurent@1252:         self.Bind(wx.EVT_COMBOBOX, self.OnReferenceChanged, reference)
andrej@1730: 
Laurent@1252:         # Create Text control for defining inline value
Laurent@1252:         inline = wx.TextCtrl(self)
Laurent@1252:         self.Bind(wx.EVT_TEXT, self.OnInlineChanged, inline)
andrej@1730: 
Laurent@1252:         # Create radio buttons for selecting power rail type
Laurent@1252:         self.TypeRadioButtons = {}
Laurent@1252:         first = True
Laurent@1252:         for type, label, control in [('reference', _('Reference'), reference),
Laurent@1252:                                      ('inline', _('Inline'), inline),
Laurent@1252:                                      ('connection', _('Connection'), None)]:
andrej@1730:             radio_button = wx.RadioButton(self, label=label,
andrej@1768:                                           style=(wx.RB_GROUP if first else 0))
Laurent@1252:             radio_button.SetValue(first)
Laurent@1252:             self.Bind(wx.EVT_RADIOBUTTON, self.OnTypeChanged, radio_button)
edouard@3303:             self.LeftGridSizer.Add(radio_button, flag=wx.GROW)
Laurent@1252:             if control is not None:
Laurent@1252:                 control.Enable(first)
edouard@3303:                 self.LeftGridSizer.Add(control, flag=wx.GROW)
Laurent@1252:             self.TypeRadioButtons[type] = (radio_button, control)
Laurent@1252:             first = False
andrej@1730: 
Laurent@1252:         # Create label for transition priority
Laurent@814:         priority_label = wx.StaticText(self, label=_('Priority:'))
edouard@3303:         self.LeftGridSizer.Add(priority_label, flag=wx.GROW)
andrej@1730: 
Laurent@1252:         # Create spin control for defining priority value
Laurent@814:         self.Priority = wx.SpinCtrl(self, min=0, style=wx.SP_ARROW_KEYS)
Laurent@814:         self.Bind(wx.EVT_TEXT, self.OnPriorityChanged, self.Priority)
edouard@3303:         self.LeftGridSizer.Add(self.Priority, flag=wx.GROW)
andrej@1730: 
Laurent@1252:         # Add preview panel and associated label to sizers
edouard@3303:         self.RightGridSizer.Add(self.PreviewLabel, flag=wx.GROW)
edouard@3303:         self.RightGridSizer.Add(self.Preview, flag=wx.GROW)
andrej@1730: 
Laurent@1252:         # Add buttons sizer to sizers
edouard@3303:         self.MainSizer.Add(
andrej@1768:             self.ButtonSizer, border=20,
andrej@1768:             flag=wx.ALIGN_RIGHT | wx.BOTTOM | wx.LEFT | wx.RIGHT)
andrej@1696: 
andrej@1696:         self.Fit()
andrej@1730: 
Laurent@1252:         # Reference radio button is default control having keyboard focus
Laurent@1252:         self.TypeRadioButtons["reference"][0].SetFocus()
andrej@1730: 
Laurent@1252:     def GetTransitionType(self):
Laurent@1252:         """
Laurent@1252:         Return type selected for SFC transition and associated value
Laurent@1252:         @return: Type selected and associated value (None if no value)
Laurent@1252:         """
Laurent@1252:         # Go through radio buttons and return type and value associated to the
Laurent@1252:         # one that is selected
kinsamanka@3750:         for type, (radio, control) in self.TypeRadioButtons.items():
Laurent@1252:             if radio.GetValue():
Laurent@1252:                 if isinstance(control, wx.ComboBox):
Laurent@1252:                     return type, control.GetStringSelection()
Laurent@1252:                 elif isinstance(control, wx.TextCtrl):
Laurent@1252:                     return type, control.GetValue()
Laurent@1252:                 else:
Laurent@1252:                     return type, None
Laurent@1252:         return None, None
andrej@1730: 
Laurent@1252:     def SetValues(self, values):
Laurent@1252:         """
Laurent@1252:         Set default SFC transition parameters
Laurent@1252:         @param values: Transition parameters values
Laurent@1252:         """
Laurent@1252:         # Extract transition value according to type
Laurent@1252:         type_value = values.get("value", None)
andrej@1730: 
Laurent@1252:         # For each parameters defined, set corresponding control value
kinsamanka@3750:         for name, value in list(values.items()):
andrej@1730: 
Laurent@1252:             # Parameter is SFC transition priority
Laurent@1252:             if name == "priority":
Laurent@1252:                 self.Priority.SetValue(values["priority"])
andrej@1730: 
Laurent@1252:             # Parameter is SFC transition type
Laurent@1252:             elif name == "type":
kinsamanka@3750:                 for type, (radio, control) in self.TypeRadioButtons.items():
Laurent@1252:                     radio.SetValue(type == value)
Laurent@1252:                     if control is not None:
Laurent@1252:                         # Enable associated control to type and set value
Laurent@1252:                         control.Enable(type == value)
Laurent@1252:                         if type == value:
Laurent@1252:                             if isinstance(control, wx.ComboBox):
Laurent@1252:                                 control.SetStringSelection(type_value)
Laurent@1252:                             elif isinstance(control, wx.TextCtrl):
Laurent@1252:                                 control.ChangeValue(type_value)
andrej@1730: 
Laurent@1252:         # Refresh preview panel
Edouard@2591:         self.RefreshPreview()
andrej@1730: 
Laurent@1252:     def GetValues(self):
Laurent@1252:         """
Laurent@1252:         Return SFC transition parameters defined in dialog
Laurent@1252:         @return: {parameter_name: parameter_value,...}
Laurent@1252:         """
andrej@1739:         values = {"priority": self.Priority.GetValue()}
Laurent@1252:         values["type"], values["value"] = self.GetTransitionType()
Laurent@1252:         values["width"], values["height"] = self.Element.GetSize()
Laurent@1252:         return values
andrej@1730: 
Laurent@1252:     def OnOK(self, event):
Laurent@1252:         """
Laurent@1252:         Called when dialog OK button is pressed
Laurent@1252:         Test if parameters defined are valid
Laurent@1252:         @param event: wx.Event from OK button
Laurent@1252:         """
Laurent@1252:         message = None
andrej@1730: 
Laurent@1252:         # Get transition type and value associated
Laurent@1252:         type, value = self.GetTransitionType()
andrej@1730: 
Laurent@1252:         # Test that value associated to type is defined
Laurent@1252:         if type != "connection" and value == "":
Laurent@1252:             message = _("Form isn't complete. %s must be filled!") % type
andrej@1730: 
Laurent@1252:         # Show error message if an error is detected
Laurent@1252:         if message is not None:
Laurent@1252:             self.ShowErrorMessage(message)
andrej@1730: 
Laurent@1252:         else:
Laurent@1252:             # Call BlockPreviewDialog function
Laurent@1252:             BlockPreviewDialog.OnOK(self, event)
Laurent@1252: 
Laurent@1252:     def OnTypeChanged(self, event):
Laurent@1252:         """
Laurent@1252:         Called when transition type changed
Laurent@1252:         @param event: wx.RadioButtonEvent
Laurent@1252:         """
Laurent@1252:         # Refresh sensibility of control associated to transition types
kinsamanka@3750:         for _type, (radio, control) in self.TypeRadioButtons.items():
Laurent@1252:             if control is not None:
Laurent@1252:                 control.Enable(radio.GetValue())
andrej@1730: 
Laurent@1252:         # Refresh preview panel
Edouard@2591:         self.RefreshPreview()
Laurent@1252:         event.Skip()
Laurent@1252: 
Laurent@1252:     def OnReferenceChanged(self, event):
Laurent@1252:         """
Laurent@1252:         Called when SFC transition reference value changed
Laurent@1252:         @param event: wx.ComboBoxEvent
Laurent@1252:         """
Edouard@2591:         self.RefreshPreview()
Laurent@1252:         event.Skip()
Laurent@1252: 
Laurent@1252:     def OnInlineChanged(self, event):
Laurent@1252:         """
Laurent@1252:         Called when SFC transition inline value changed
Laurent@1252:         @param event: wx.TextEvent
Laurent@1252:         """
Edouard@2591:         self.RefreshPreview()
Laurent@1252:         event.Skip()
Laurent@1252: 
Laurent@1252:     def OnPriorityChanged(self, event):
Laurent@1252:         """
Laurent@1252:         Called when block inputs number changed
Laurent@1252:         @param event: wx.SpinEvent
Laurent@1252:         """
Edouard@2591:         self.RefreshPreview()
Edouard@2587:         event.Skip()
Edouard@2587: 
Edouard@2587:     def DrawPreview(self):
Laurent@1252:         """
Laurent@1252:         Refresh preview panel of graphic element
Laurent@1252:         Override BlockPreviewDialog function
Laurent@1252:         """
Laurent@1252:         # Set graphic element displayed, creating a SFC transition
Laurent@814:         self.Element = SFC_Transition(self.Preview)
Laurent@1252:         self.Element.SetType(*self.GetTransitionType())
Laurent@1252:         self.Element.SetPriority(self.Priority.GetValue())
andrej@1730: 
Laurent@1252:         # Call BlockPreviewDialog function
Edouard@2587:         BlockPreviewDialog.DrawPreview(self)