controls/ProjectPropertiesPanel.py
changeset 814 5743cbdff669
child 1537 e8629f0cc93b
equal deleted inserted replaced
813:1460273f40ed 814:5743cbdff669
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2012: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    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
       
    24 
       
    25 import wx
       
    26 
       
    27 #-------------------------------------------------------------------------------
       
    28 #                                 Helpers
       
    29 #-------------------------------------------------------------------------------
       
    30 
       
    31 REQUIRED_PARAMS = ["projectName", "productName", "productVersion", "companyName"]
       
    32 
       
    33 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
       
    34  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
       
    35 ] = range(10)
       
    36 
       
    37 #-------------------------------------------------------------------------------
       
    38 #                       Project Properties Panel
       
    39 #-------------------------------------------------------------------------------
       
    40 
       
    41 class ProjectPropertiesPanel(wx.Notebook):
       
    42     
       
    43     def AddSizerParams(self, parent, sizer, params):
       
    44         for idx, (name, label) in enumerate(params):
       
    45             border = 0
       
    46             if idx == 0:
       
    47                 border |= wx.TOP
       
    48             elif idx == len(params) - 1:
       
    49                 border |= wx.BOTTOM
       
    50             
       
    51             st = wx.StaticText(parent, label=label)
       
    52             sizer.AddWindow(st, border=10, 
       
    53                   flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
       
    54             
       
    55             tc = wx.TextCtrl(parent, style=wx.TE_PROCESS_ENTER)
       
    56             setattr(self, name, tc)
       
    57             callback = self.GetTextCtrlChangedFunction(tc, name)
       
    58             self.Bind(wx.EVT_TEXT_ENTER, callback, tc)
       
    59             tc.Bind(wx.EVT_KILL_FOCUS, callback)
       
    60             sizer.AddWindow(tc, border=10, 
       
    61                   flag=wx.GROW|border|wx.RIGHT)
       
    62 
       
    63     def __init__(self, parent, controller=None, window=None, enable_required=True):
       
    64         wx.Notebook.__init__(self, parent, size=wx.Size(500, 300))
       
    65 
       
    66         self.Controller = controller
       
    67         self.ParentWindow = window
       
    68         self.Values = None
       
    69         
       
    70         # Project Panel elements
       
    71 
       
    72         self.ProjectPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
       
    73         projectpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15)
       
    74         projectpanel_sizer.AddGrowableCol(1)
       
    75         self.ProjectPanel.SetSizer(projectpanel_sizer)
       
    76         
       
    77         self.AddSizerParams(self.ProjectPanel, projectpanel_sizer,
       
    78               [("projectName", _('Project Name (required):')),
       
    79                ("projectVersion", _('Project Version (optional):')),
       
    80                ("productName", _('Product Name (required):')),
       
    81                ("productVersion", _('Product Version (required):')),
       
    82                ("productRelease", _('Product Release (optional):'))])
       
    83         
       
    84         self.AddPage(self.ProjectPanel, _("Project"))
       
    85         
       
    86         # Author Panel elements
       
    87 
       
    88         self.AuthorPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
       
    89         authorpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15)
       
    90         authorpanel_sizer.AddGrowableCol(1)
       
    91         self.AuthorPanel.SetSizer(authorpanel_sizer)
       
    92         
       
    93         self.AddSizerParams(self.AuthorPanel, authorpanel_sizer,
       
    94               [("companyName", _('Company Name (required):')),
       
    95                ("companyURL", _('Company URL (optional):')),
       
    96                ("authorName", _('Author Name (optional):')),
       
    97                ("organization", _('Organization (optional):'))])
       
    98         
       
    99         self.AddPage(self.AuthorPanel, _("Author"))
       
   100 
       
   101         # Graphics Panel elements
       
   102 
       
   103         self.GraphicsPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
       
   104         graphicpanel_sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5)
       
   105         graphicpanel_sizer.AddGrowableCol(0)
       
   106         graphicpanel_sizer.AddGrowableRow(3)
       
   107         self.GraphicsPanel.SetSizer(graphicpanel_sizer)
       
   108         
       
   109         pageSize_st = wx.StaticText(self.GraphicsPanel,
       
   110               label=_('Page Size (optional):'))
       
   111         graphicpanel_sizer.AddWindow(pageSize_st, border=10, 
       
   112               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT)
       
   113         
       
   114         pageSize_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
       
   115         pageSize_sizer.AddGrowableCol(1)
       
   116         graphicpanel_sizer.AddSizer(pageSize_sizer, border=10, 
       
   117               flag=wx.GROW|wx.LEFT|wx.RIGHT)
       
   118         
       
   119         for name, label in [('PageWidth', _('Width:')),
       
   120                             ('PageHeight', _('Height:'))]:
       
   121             st = wx.StaticText(self.GraphicsPanel, label=label)
       
   122             pageSize_sizer.AddWindow(st, border=12, 
       
   123                   flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
       
   124             
       
   125             sp = wx.SpinCtrl(self.GraphicsPanel, 
       
   126                   min=0, max=2**16, style=wx.TE_PROCESS_ENTER)
       
   127             setattr(self, name, sp)
       
   128             callback = self.GetPageSizeChangedFunction(sp, name)
       
   129             self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
       
   130             sp.Bind(wx.EVT_KILL_FOCUS, callback)
       
   131             pageSize_sizer.AddWindow(sp, flag=wx.GROW)
       
   132         
       
   133         scaling_st = wx.StaticText(self.GraphicsPanel,
       
   134               label=_('Grid Resolution:'))
       
   135         graphicpanel_sizer.AddWindow(scaling_st, border=10, 
       
   136               flag=wx.GROW|wx.LEFT|wx.RIGHT)
       
   137         
       
   138         scaling_nb = wx.Notebook(self.GraphicsPanel)
       
   139         graphicpanel_sizer.AddWindow(scaling_nb, border=10, 
       
   140               flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   141         
       
   142         self.Scalings = {}
       
   143         for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]:
       
   144             scaling_panel = wx.Panel(scaling_nb, style=wx.TAB_TRAVERSAL)
       
   145             scalingpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
       
   146             scalingpanel_sizer.AddGrowableCol(1)
       
   147             scaling_panel.SetSizer(scalingpanel_sizer)
       
   148             
       
   149             scaling_controls = []
       
   150             for idx, (name, label) in enumerate([('XScale', _('Horizontal:')),
       
   151                                                  ('YScale', _('Vertical:'))]):
       
   152                 if idx == 0:
       
   153                     border = wx.TOP
       
   154                 else:
       
   155                     border = wx.BOTTOM
       
   156                 
       
   157                 st = wx.StaticText(scaling_panel, label=label)
       
   158                 scalingpanel_sizer.AddWindow(st, border=10, 
       
   159                       flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
       
   160                 
       
   161                 sp = wx.SpinCtrl(scaling_panel, 
       
   162                       min=0, max=2**16, style=wx.TE_PROCESS_ENTER)
       
   163                 scaling_controls.append(sp)
       
   164                 callback = self.GetScalingChangedFunction(sp, language, name)
       
   165                 self.Bind(wx.EVT_TEXT_ENTER, callback, sp)
       
   166                 sp.Bind(wx.EVT_KILL_FOCUS, callback)
       
   167                 scalingpanel_sizer.AddWindow(sp, border=10, 
       
   168                       flag=wx.GROW|border|wx.RIGHT)
       
   169         
       
   170             self.Scalings[language] = scaling_controls
       
   171             scaling_nb.AddPage(scaling_panel, translation)
       
   172         
       
   173         self.AddPage(self.GraphicsPanel, _("Graphics"))
       
   174 
       
   175         # Miscellaneous Panel elements
       
   176 
       
   177         self.MiscellaneousPanel = wx.Panel(id=-1, parent=self, 
       
   178               name='MiscellaneousPanel', pos=wx.Point(0, 0),
       
   179               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
   180         miscellaneouspanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15)
       
   181         miscellaneouspanel_sizer.AddGrowableCol(1)
       
   182         miscellaneouspanel_sizer.AddGrowableRow(1)
       
   183         self.MiscellaneousPanel.SetSizer(miscellaneouspanel_sizer)
       
   184         
       
   185         language_label = wx.StaticText(self.MiscellaneousPanel,
       
   186               label=_('Language (optional):'))
       
   187         miscellaneouspanel_sizer.AddWindow(language_label, border=10, 
       
   188               flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
       
   189         
       
   190         self.Language = wx.ComboBox(self.MiscellaneousPanel, 
       
   191               style=wx.CB_READONLY)
       
   192         self.Bind(wx.EVT_COMBOBOX, self.OnLanguageChanged, self.Language)
       
   193         miscellaneouspanel_sizer.AddWindow(self.Language, border=10, 
       
   194               flag=wx.GROW|wx.TOP|wx.RIGHT)
       
   195         
       
   196         description_label = wx.StaticText(self.MiscellaneousPanel,
       
   197               label=_('Content Description (optional):'))
       
   198         miscellaneouspanel_sizer.AddWindow(description_label, border=10, 
       
   199               flag=wx.BOTTOM|wx.LEFT)
       
   200         
       
   201         self.ContentDescription = wx.TextCtrl(self.MiscellaneousPanel, 
       
   202               style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER)
       
   203         self.Bind(wx.EVT_TEXT_ENTER, self.OnContentDescriptionChanged, 
       
   204               self.ContentDescription)
       
   205         self.ContentDescription.Bind(wx.EVT_KILL_FOCUS, 
       
   206               self.OnContentDescriptionChanged)
       
   207         miscellaneouspanel_sizer.AddWindow(self.ContentDescription, border=10, 
       
   208               flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
       
   209         
       
   210         self.AddPage(self.MiscellaneousPanel, _("Miscellaneous"))
       
   211         
       
   212         for param in REQUIRED_PARAMS:
       
   213             getattr(self, param).Enable(enable_required)
       
   214            
       
   215         languages = ["", "en-US", "fr-FR", "zh-CN"]
       
   216         
       
   217         for language in languages:
       
   218             self.Language.Append(language)
       
   219 
       
   220     def RefreshView(self):
       
   221         if self.Controller is not None:
       
   222             self.SetValues(self.Controller.GetProjectProperties())
       
   223 
       
   224     def SetValues(self, values):
       
   225         self.Values = values
       
   226         for item, value in values.items():
       
   227             if item == "language":
       
   228                 self.Language.SetStringSelection(value)
       
   229             elif item == "contentDescription":
       
   230                 self.ContentDescription.SetValue(value)
       
   231             elif item == "pageSize":
       
   232                 self.PageWidth.SetValue(value[0])
       
   233                 self.PageHeight.SetValue(value[1])
       
   234             elif item == "scaling":
       
   235                 for language, (x, y) in value.items():
       
   236                     if language in self.Scalings:
       
   237                         self.Scalings[language][0].SetValue(x)
       
   238                         self.Scalings[language][1].SetValue(y)
       
   239             else:
       
   240                 tc = getattr(self, item, None)
       
   241                 if tc is not None:
       
   242                     tc.SetValue(value)
       
   243         
       
   244     def GetValues(self):
       
   245         values = {}
       
   246         for param in ["projectName", "projectVersion",
       
   247                       "productName", "productVersion",
       
   248                       "productRelease", "companyName",
       
   249                       "companyURL", "authorName", 
       
   250                       "organization"]:
       
   251             value = getattr(self, param).GetValue()
       
   252             if param in REQUIRED_PARAMS or value != "":
       
   253                 values[param] = value
       
   254             else:
       
   255                 values[param] = None
       
   256         language = self.Language.GetStringSelection()
       
   257         if language != "":
       
   258             values["language"] = language
       
   259         else:
       
   260             values["language"] = None
       
   261         content_description = self.ContentDescription.GetValue()
       
   262         if content_description != "":
       
   263             values["contentDescription"] = content_description
       
   264         else:
       
   265             values["contentDescription"] = None
       
   266         values["pageSize"] = (self.PageWidth.GetValue(), self.PageHeight.GetValue())
       
   267         values["scaling"] = {}
       
   268         for language in ["FBD", "LD", "SFC"]:
       
   269             values["scaling"][language] = (self.Scalings[language][0].GetValue(),
       
   270                                            self.Scalings[language][1].GetValue())
       
   271         return values
       
   272     
       
   273     def GetTextCtrlChangedFunction(self, textctrl, name):
       
   274         def TextCtrlChangedFunction(event):
       
   275             if self.Controller is not None:
       
   276                 if self.Values is not None:
       
   277                     old_value = self.Values.get(name)
       
   278                 else:
       
   279                     old_value = None
       
   280                 new_value = textctrl.GetValue()
       
   281                 if name not in REQUIRED_PARAMS and new_value == "":
       
   282                     new_value = None
       
   283                 if old_value != new_value:
       
   284                     self.Controller.SetProjectProperties(properties={name: new_value})
       
   285                     self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU,
       
   286                             PROJECTTREE, PAGETITLES)
       
   287                     wx.CallAfter(self.RefreshView)
       
   288             event.Skip()
       
   289         return TextCtrlChangedFunction
       
   290 
       
   291     def GetPageSizeChangedFunction(self, spinctrl, name):
       
   292         def PageSizeChangedFunction(event):
       
   293             if self.Controller is not None:
       
   294                 if self.Values is not None:
       
   295                     old_value = self.Values.get("pageSize")
       
   296                 else:
       
   297                     old_value = (0, 0)
       
   298                 if name == 'PageWidth':
       
   299                     new_value = (spinctrl.GetValue(), old_value[1])
       
   300                 else:
       
   301                     new_value = (old_value[0], spinctrl.GetValue())
       
   302                 if old_value != new_value:
       
   303                     self.Controller.SetProjectProperties(properties={"pageSize": new_value})
       
   304                     self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU,
       
   305                           PAGETITLES, SCALING)
       
   306                     wx.CallAfter(self.RefreshView)
       
   307             event.Skip()
       
   308         return PageSizeChangedFunction
       
   309     
       
   310     def GetScalingChangedFunction(self, spinctrl, language, name):
       
   311         def ScalingChangedFunction(event):
       
   312             if self.Controller is not None:
       
   313                 old_value = (0, 0)
       
   314                 if self.Values is not None:
       
   315                     scaling = self.Values.get("scaling")
       
   316                     if scaling is not None:
       
   317                         old_value = scaling.get(language)
       
   318                 if name == 'XScale':
       
   319                     new_value = (spinctrl.GetValue(), old_value[1])
       
   320                 else:
       
   321                     new_value = (old_value[0], spinctrl.GetValue())
       
   322                 if old_value != new_value:
       
   323                     self.Controller.SetProjectProperties(properties={"scaling": {language: new_value}})
       
   324                     self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU,
       
   325                           PAGETITLES, SCALING)
       
   326                     wx.CallAfter(self.RefreshView)
       
   327             event.Skip()
       
   328         return ScalingChangedFunction
       
   329     
       
   330     def OnLanguageChanged(self, event):
       
   331         if self.Controller is not None:
       
   332             if self.Values is not None:
       
   333                 old_value = self.Values.get("language")
       
   334             else:
       
   335                 old_value = None
       
   336             new_value = self.Language.GetStringSelection()
       
   337             if new_value == "":
       
   338                 new_value = None
       
   339             if old_value != new_value:
       
   340                 self.Controller.SetProjectProperties(properties={"language": new_value})
       
   341                 self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
       
   342                 wx.CallAfter(self.RefreshView)
       
   343         event.Skip()
       
   344         
       
   345     def OnContentDescriptionChanged(self, event):
       
   346         if self.Controller is not None:
       
   347             if self.Values is not None:
       
   348                 old_value = self.Values.get("contentDescription")
       
   349             else:
       
   350                 old_value = None
       
   351             new_value = self.ContentDescription.GetValue()
       
   352             if new_value == "":
       
   353                 new_value = None
       
   354             if old_value != new_value:
       
   355                 self.Controller.SetProjectProperties(properties={"contentDescription": new_value})
       
   356                 self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
       
   357                 wx.CallAfter(self.RefreshView)
       
   358         event.Skip()