Separating ProjectDialog from PLCOpenEditor for integration of panel into Beremiz project window
authorLaurent Bessard
Sun, 03 Jun 2012 23:47:13 +0200
changeset 700 cf3db1775105
parent 699 649399ffdaf0
child 701 25fbbb005a30
Separating ProjectDialog from PLCOpenEditor for integration of panel into Beremiz project window
PLCOpenEditor.py
controls/ProjectPropertiesPanel.py
controls/__init__.py
dialogs/ProjectDialog.py
dialogs/__init__.py
plcopen/plcopen.py
--- a/PLCOpenEditor.py	Wed May 30 12:20:27 2012 +0200
+++ b/PLCOpenEditor.py	Sun Jun 03 23:47:13 2012 +0200
@@ -109,6 +109,7 @@
 from PLCControler import *
 from SearchResultPanel import SearchResultPanel
 from controls import CustomGrid, CustomTable, CustomTree, LibraryPanel, PouInstanceVariablesPanel
+from dialogs import ProjectDialog
 
 # Define PLCOpenEditor controls id
 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
@@ -1798,11 +1799,12 @@
         item_infos = self.ProjectTree.GetPyData(selected)
         if item_infos["type"] == ITEM_PROJECT:
             self.EditProjectSettings()
-        elif item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
+        else:
+            if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
                                     ITEM_CONFIGURATION, ITEM_RESOURCE,
                                     ITEM_TRANSITION, ITEM_ACTION]:
-            self.EditProjectElement(item_infos["type"], item_infos["tagname"])
-        event.Skip()
+                self.EditProjectElement(item_infos["type"], item_infos["tagname"])
+            event.Skip()
     
     def ProjectTreeItemSelect(self, select_item):
         name = self.ProjectTree.GetItemText(select_item)
@@ -2885,453 +2887,6 @@
         dialog.Destroy()
 
 #-------------------------------------------------------------------------------
-#                            Create Project Dialog
-#-------------------------------------------------------------------------------
-
-[ID_SCALINGPANEL, ID_SCALINGPANELXSCALE, 
- ID_SCALINGPANELYSCALE, ID_SCALINGPANELSTATICTEXT1, 
- ID_SCALINGPANELSTATICTEXT2, 
-] = [wx.NewId() for _init_ctrls in range(5)]
-
-class ScalingPanel(wx.Panel):
-    
-    def _init_coll_ScalingPanelSizer_Items(self, parent):
-        parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
-        parent.AddWindow(self.XScale, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT)
-        parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT)
-        parent.AddWindow(self.YScale, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
-
-    def _init_coll_ScalingPanelSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-
-    def _init_sizers(self):
-        self.ScalingPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
-        
-        self._init_coll_ScalingPanelSizer_Items(self.ScalingPanelSizer)
-        self._init_coll_ScalingPanelSizer_Growables(self.ScalingPanelSizer)
-
-        self.SetSizer(self.ScalingPanelSizer)
-
-    def _init_ctrls(self, prnt):
-        wx.Panel.__init__(self, id=ID_SCALINGPANEL,
-              name='ScalingPanel', parent=prnt, pos=wx.Point(0, 0),
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
-        self.staticText1 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT1,
-              label=_('Horizontal:'), name='staticText1', parent=self,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.XScale = wx.SpinCtrl(id=ID_SCALINGPANELXSCALE,
-              name='XScale', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0, min=0, max=2**16)
-        
-        self.staticText2 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT2,
-              label=_('Vertical:'), name='staticText2', parent=self,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.YScale = wx.SpinCtrl(id=ID_SCALINGPANELYSCALE,
-              name='YScale', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0, min=0, max=2**16)
-        
-        self._init_sizers()
-        
-    def __init__(self, parent):
-        self._init_ctrls(parent)
-
-    def SetScaling(self, x, y):
-        self.XScale.SetValue(x)
-        self.YScale.SetValue(y)
-        
-    def GetScaling(self):
-        return self.XScale.GetValue(), self.YScale.GetValue()
-
-[ID_PROJECTDIALOG, ID_PROJECTDIALOGMAINNOTEBOOK, 
- ID_PROJECTDIALOGPROJECTPANEL, ID_PROJECTDIALOGAUTHORPANEL, 
- ID_PROJECTDIALOGGRAPHICSPANEL, ID_PROJECTDIALOGMISCELLANEOUSPANEL, 
- ID_PROJECTDIALOGPROJECTNAME, ID_PROJECTDIALOGPROJECTVERSION, 
- ID_PROJECTDIALOGPRODUCTNAME, ID_PROJECTDIALOGPRODUCTVERSION, 
- ID_PROJECTDIALOGPRODUCTRELEASE, ID_PROJECTDIALOGCOMPANYNAME, 
- ID_PROJECTDIALOGCOMPANYURL, ID_PROJECTDIALOGAUTHORNAME, 
- ID_PROJECTDIALOGORGANIZATION, ID_PROJECTDIALOGLANGUAGE, 
- ID_PROJECTDIALOGCONTENTDESCRIPTION, ID_PROJECTDIALOGSCALINGNOTEBOOK, 
- ID_PROJECTDIALOGPAGEWIDTH, ID_PROJECTDIALOGPAGEHEIGHT, 
- ID_PROJECTDIALOGSTATICTEXT1, ID_PROJECTDIALOGSTATICTEXT2, 
- ID_PROJECTDIALOGSTATICTEXT3, ID_PROJECTDIALOGSTATICTEXT4, 
- ID_PROJECTDIALOGSTATICTEXT5, ID_PROJECTDIALOGSTATICTEXT6, 
- ID_PROJECTDIALOGSTATICTEXT7, ID_PROJECTDIALOGSTATICTEXT8, 
- ID_PROJECTDIALOGSTATICTEXT9, ID_PROJECTDIALOGSTATICTEXT10, 
- ID_PROJECTDIALOGSTATICTEXT11, ID_PROJECTDIALOGSTATICTEXT12, 
- ID_PROJECTDIALOGSTATICTEXT13, ID_PROJECTDIALOGSTATICTEXT14, 
- ID_PROJECTDIALOGSTATICTEXT15, 
-] = [wx.NewId() for _init_ctrls in range(35)]
-
-class ProjectDialog(wx.Dialog):
-    if wx.VERSION < (2, 6, 0):
-        def Bind(self, event, function, id = None):
-            if id is not None:
-                event(self, id, function)
-            else:
-                event(self, function)
-                
-    def _init_coll_flexGridSizer1_Items(self, parent):
-        parent.AddSizer(self.MainNotebook, 0, border=0, flag=wx.GROW)
-        parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
-    def _init_coll_flexGridSizer1_Growables(self, parent):
-        parent.AddGrowableCol(0)
-        parent.AddGrowableRow(0)
-    
-    def _init_coll_ProjectPanelSizer_Items(self, parent):
-        parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
-        parent.AddWindow(self.ProjectName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT)
-        parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.ProjectVersion, 0, border=10, flag=wx.GROW|wx.RIGHT)
-        parent.AddWindow(self.staticText3, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.ProductName, 0, border=10, flag=wx.GROW|wx.RIGHT)
-        parent.AddWindow(self.staticText4, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.ProductVersion, 0, border=10, flag=wx.GROW|wx.RIGHT)
-        parent.AddWindow(self.staticText5, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT)
-        parent.AddWindow(self.ProductRelease, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
-        
-    def _init_coll_ProjectPanelSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-
-    def _init_coll_AuthorPanelSizer_Items(self, parent):
-        parent.AddWindow(self.staticText6, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
-        parent.AddWindow(self.CompanyName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT)
-        parent.AddWindow(self.staticText7, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.CompanyURL, 0, border=10, flag=wx.GROW|wx.RIGHT)
-        parent.AddWindow(self.staticText8, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.AuthorName, 0, border=10, flag=wx.GROW|wx.RIGHT)
-        parent.AddWindow(self.staticText9, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT)
-        parent.AddWindow(self.Organization, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
-    
-    def _init_coll_AuthorPanelSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-    
-    def _init_coll_GraphicsPanelSizer_Items(self, parent):
-        parent.AddWindow(self.staticText12, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT)
-        parent.AddSizer(self.GraphicsPageSizeSizer, 0, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT)
-        parent.AddWindow(self.staticText15, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT)
-        parent.AddWindow(self.ScalingNotebook, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
-        
-    def _init_coll_GraphicsPanelSizer_Growables(self, parent):
-        parent.AddGrowableCol(0)
-        parent.AddGrowableRow(3)
-    
-    def _init_coll_GraphicsPageSizeSizer_Items(self, parent):
-        parent.AddWindow(self.staticText13, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.PageWidth, 0, border=0, flag=wx.GROW)
-        parent.AddWindow(self.staticText14, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
-        parent.AddWindow(self.PageHeight, 0, border=0, flag=wx.GROW)
-    
-    def _init_coll_GraphicsPageSizeSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-    
-    def _init_coll_MiscellaneousPanelSizer_Items(self, parent):
-        parent.AddWindow(self.staticText10, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
-        parent.AddWindow(self.Language, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT)
-        parent.AddWindow(self.staticText11, 0, border=10, flag=wx.BOTTOM|wx.LEFT)
-        parent.AddWindow(self.ContentDescription, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
-        
-    def _init_coll_MiscellaneousPanelSizer_Growables(self, parent):
-        parent.AddGrowableCol(1)
-        parent.AddGrowableRow(1)
-        
-    def _init_sizers(self):
-        self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
-        self.ProjectPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15)
-        self.AuthorPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15)
-        self.GraphicsPanelSizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5)
-        self.GraphicsPageSizeSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
-        self.MiscellaneousPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15)
-
-        self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
-        self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
-        self._init_coll_ProjectPanelSizer_Items(self.ProjectPanelSizer)
-        self._init_coll_ProjectPanelSizer_Growables(self.ProjectPanelSizer)
-        self._init_coll_AuthorPanelSizer_Items(self.AuthorPanelSizer)
-        self._init_coll_AuthorPanelSizer_Growables(self.AuthorPanelSizer)
-        self._init_coll_GraphicsPanelSizer_Items(self.GraphicsPanelSizer)
-        self._init_coll_GraphicsPanelSizer_Growables(self.GraphicsPanelSizer)
-        self._init_coll_GraphicsPageSizeSizer_Items(self.GraphicsPageSizeSizer)
-        self._init_coll_GraphicsPageSizeSizer_Growables(self.GraphicsPageSizeSizer)
-        self._init_coll_MiscellaneousPanelSizer_Items(self.MiscellaneousPanelSizer)
-        self._init_coll_MiscellaneousPanelSizer_Growables(self.MiscellaneousPanelSizer)
-
-        self.SetSizer(self.flexGridSizer1)
-        self.ProjectPanel.SetSizer(self.ProjectPanelSizer)
-        self.AuthorPanel.SetSizer(self.AuthorPanelSizer)
-        self.GraphicsPanel.SetSizer(self.GraphicsPanelSizer)
-        self.MiscellaneousPanel.SetSizer(self.MiscellaneousPanelSizer)
-
-    def _init_ctrls(self, prnt):
-        wx.Dialog.__init__(self, id=ID_PROJECTDIALOG,
-              name='ProjectDialog', parent=prnt,
-              size=wx.Size(500, 350), style=wx.DEFAULT_DIALOG_STYLE,
-              title=_('Project properties'))
-        self.SetClientSize(wx.Size(500, 350))
-
-        self.MainNotebook = wx.Notebook(id=ID_PROJECTDIALOGMAINNOTEBOOK,
-                  name='MainNotebook', parent=self, pos=wx.Point(0,
-                  0), size=wx.Size(0, 0), style=0)
-
-        # Project Panel elements
-
-        self.ProjectPanel = wx.Panel(id=ID_PROJECTDIALOGPROJECTPANEL,
-              name='ProjectPanel', parent=self.MainNotebook, pos=wx.Point(0, 0),
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
-        self.staticText1 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT1,
-              label=_('Project Name (required):'), name='staticText1', parent=self.ProjectPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ProjectName = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTNAME,
-              name='ProjectName', parent=self.ProjectPanel, pos=wx.Point(0, 0), 
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText2 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT2,
-              label=_('Project Version (optional):'), name='staticText2', parent=self.ProjectPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ProjectVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTVERSION,
-              name='ProjectVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0), 
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText3 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT3,
-              label=_('Product Name (required):'), name='staticText3', parent=self.ProjectPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ProductName = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTNAME,
-              name='ProductName', parent=self.ProjectPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText4 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT4,
-              label=_('Product Version (required):'), name='staticText4', parent=self.ProjectPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ProductVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTVERSION,
-              name='ProductVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText5 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT5,
-              label=_('Product Release (optional):'), name='staticText5', parent=self.ProjectPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ProductRelease = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTRELEASE,
-              name='ProductRelease', parent=self.ProjectPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.MainNotebook.AddPage(self.ProjectPanel, _("Project"))
-        
-        # Author Panel elements
-
-        self.AuthorPanel = wx.Panel(id=ID_PROJECTDIALOGAUTHORPANEL,
-              name='AuthorPanel', parent=self.MainNotebook, pos=wx.Point(0, 0),
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
-        self.staticText6 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT6,
-              label=_('Company Name (required):'), name='staticText6', parent=self.AuthorPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.CompanyName = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYNAME,
-              name='CompanyName', parent=self.AuthorPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText7 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT7,
-              label=_('Company URL (optional):'), name='staticText7', parent=self.AuthorPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.CompanyURL = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYURL,
-              name='CompanyURL', parent=self.AuthorPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText8 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT8,
-              label=_('Author Name (optional):'), name='staticText8', parent=self.AuthorPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.AuthorName = wx.TextCtrl(id=ID_PROJECTDIALOGAUTHORNAME,
-              name='AuthorName', parent=self.AuthorPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.staticText9 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT9,
-              label=_('Organization (optional):'), name='staticText9', parent=self.AuthorPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.Organization = wx.TextCtrl(id=ID_PROJECTDIALOGORGANIZATION,
-              name='Organization', parent=self.AuthorPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0)
-
-        self.MainNotebook.AddPage(self.AuthorPanel, _("Author"))
-
-        # Graphics Panel elements
-
-        self.GraphicsPanel = wx.Panel(id=ID_PROJECTDIALOGGRAPHICSPANEL,
-              name='GraphicsPanel', parent=self.MainNotebook, pos=wx.Point(0, 0),
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
-        self.staticText12 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT12,
-              label=_('Page Size (optional):'), name='staticText12', parent=self.GraphicsPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.staticText13 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT13,
-              label=_('Width:'), name='staticText13', parent=self.GraphicsPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.PageWidth = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEWIDTH,
-              name='PageWidth', parent=self.GraphicsPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0, min=0, max=2**16)
-
-        self.staticText14 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT14,
-              label=_('Height:'), name='staticText14', parent=self.GraphicsPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.PageHeight = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEHEIGHT,
-              name='PageHeight', parent=self.GraphicsPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0, min=0, max=2**16)
-        
-        self.staticText15 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT15,
-              label=_('Grid Resolution:'), name='staticText15', parent=self.GraphicsPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-        
-        self.ScalingNotebook = wx.Notebook(id=ID_PROJECTDIALOGSCALINGNOTEBOOK,
-              name='ScalingNotebook', parent=self.GraphicsPanel, pos=wx.Point(0,
-              0), size=wx.Size(0, 0), style=0)
-        
-        self.Scalings = {}
-        for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]:
-            window = ScalingPanel(self.ScalingNotebook)
-            self.Scalings[language] = window
-            self.ScalingNotebook.AddPage(window, translation)
-        
-        self.MainNotebook.AddPage(self.GraphicsPanel, _("Graphics"))
-
-        # Miscellaneous Panel elements
-
-        self.MiscellaneousPanel = wx.Panel(id=ID_PROJECTDIALOGMISCELLANEOUSPANEL,
-              name='MiscellaneousPanel', parent=self.MainNotebook, pos=wx.Point(0, 0),
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
-        self.staticText10 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT10,
-              label=_('Language (optional):'), name='staticText10', parent=self.MiscellaneousPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.Language = wx.ComboBox(id=ID_PROJECTDIALOGLANGUAGE,
-              name='Language', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 28), style=wx.CB_READONLY)
-
-        self.staticText11 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT11,
-              label=_('Content Description (optional):'), name='staticText11', parent=self.MiscellaneousPanel,
-              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
-
-        self.ContentDescription = wx.TextCtrl(id=ID_PROJECTDIALOGCONTENTDESCRIPTION,
-              name='ContentDescription', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=wx.TE_MULTILINE)
-
-        self.MainNotebook.AddPage(self.MiscellaneousPanel, _("Miscellaneous"))
-
-        self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
-        self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
-        
-        self._init_sizers()
-
-    def __init__(self, parent, enable_required=True):
-        self._init_ctrls(parent)
-        
-        self.ProjectName.Enable(enable_required)
-        self.ProductName.Enable(enable_required)
-        self.ProductVersion.Enable(enable_required)
-        self.CompanyName.Enable(enable_required)
-            
-        languages = ["", "en-US", "fr-FR", "zh-CN"]
-        
-        for language in languages:
-            self.Language.Append(language)
-        
-    def OnOK(self, event):
-        error = []
-        if self.ProjectName.GetValue() == "":
-            error.append("Project Name")
-        if self.CompanyName.GetValue() == "":
-            error.append("Company Name")
-        if self.ProductName.GetValue() == "":
-            error.append("Product Name")
-        if self.ProductVersion.GetValue() == "":
-            error.append("Product Version")
-        if len(error) > 0:
-            text = ""
-            for i, item in enumerate(error):
-                if i == 0:
-                    text += item
-                elif i == len(error) - 1:
-                    text += " and %s"%item
-                else:
-                    text += ", %s"%item
-            message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR)
-            message.ShowModal()
-            message.Destroy()
-        else:
-            self.EndModal(wx.ID_OK)
-
-    def SetValues(self, values):
-        for item, value in values.items():
-            if item == "projectName":
-                self.ProjectName.SetValue(value)
-            elif item == "projectVersion":
-                self.ProjectVersion.SetValue(value)
-            elif item == "productName":
-                self.ProductName.SetValue(value)
-            elif item == "productVersion":
-                self.ProductVersion.SetValue(value)
-            elif item == "productRelease":
-                self.ProductRelease.SetValue(value)
-            elif item == "companyName":
-                self.CompanyName.SetValue(value)
-            elif item == "companyURL":
-                self.CompanyURL.SetValue(value)
-            elif item == "authorName":
-                self.AuthorName.SetValue(value)
-            elif item == "organization":
-                self.Organization.SetValue(value)
-            elif item == "language":
-                self.Language.SetStringSelection(value)
-            elif item == "contentDescription":
-                self.ContentDescription.SetValue(value)
-            elif item == "pageSize":
-                self.PageWidth.SetValue(value[0])
-                self.PageHeight.SetValue(value[1])
-            elif item == "scaling":
-                for language, (x, y) in value.items():
-                    if language in self.Scalings:
-                        self.Scalings[language].SetScaling(x, y)
-    
-    def GetValues(self):
-        values = {}
-        values["projectName"] = self.ProjectName.GetValue()
-        if self.ProjectVersion.GetValue() != "":
-            values["projectVersion"] = self.ProjectVersion.GetValue()
-        values["productName"] = self.ProductName.GetValue()
-        values["productVersion"] = self.ProductVersion.GetValue()
-        if self.ProductRelease.GetValue() != "":
-            values["productRelease"] = self.ProductRelease.GetValue()
-        values["companyName"] = self.CompanyName.GetValue()
-        if self.CompanyURL.GetValue() != "":
-            values["companyURL"] = self.CompanyURL.GetValue()
-        if self.AuthorName.GetValue() != "":
-            values["authorName"] = self.AuthorName.GetValue()
-        if self.Organization.GetValue() != "":
-            values["organization"] = self.Organization.GetValue()
-        if self.Language.GetStringSelection() != "":
-            values["language"] = self.Language.GetStringSelection()
-        if self.ProductRelease.GetValue() != "":
-            values["contentDescription"] = self.ContentDescription.GetValue()
-        values["pageSize"] = (self.PageWidth.GetValue(), self.PageHeight.GetValue())
-        values["scaling"] = {}
-        for language in ["FBD", "LD", "SFC"]:
-            values["scaling"][language] = self.Scalings[language].GetScaling()
-        return values
-
-#-------------------------------------------------------------------------------
 #                          Edit Step Name Dialog
 #-------------------------------------------------------------------------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controls/ProjectPropertiesPanel.py	Sun Jun 03 23:47:13 2012 +0200
@@ -0,0 +1,367 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2012: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx
+
+REQUIRED_PARAMS = ["projectName", "productName", "productVersion", "companyName"]
+
+class ProjectPropertiesPanel(wx.Notebook):
+    
+    def AddSizerParams(self, parent, sizer, params):
+        for idx, (name, label) in enumerate(params):
+            border = 0
+            if idx == 0:
+                border |= wx.TOP
+            elif idx == len(params) - 1:
+                border |= wx.BOTTOM
+            
+            st = wx.StaticText(id=-1, parent=parent, 
+                  label=label, name=name + '_label',
+                  pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+            sizer.AddWindow(st, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
+            
+            tc_id = wx.NewId()
+            tc = wx.TextCtrl(id=tc_id, parent=parent, 
+                  name=name, pos=wx.Point(0, 0), 
+                  size=wx.Size(0, 24), style=wx.TE_PROCESS_ENTER)
+            setattr(self, name, tc)
+            callback = self.GetTextCtrlChangedFunction(tc, name)
+            self.Bind(wx.EVT_TEXT_ENTER, callback, id=tc_id)
+            tc.Bind(wx.EVT_KILL_FOCUS, callback)
+            sizer.AddWindow(tc, 0, border=10, flag=wx.GROW|border|wx.RIGHT)
+
+    def __init__(self, parent, controller=None, window=None, enable_required=True):
+        wx.Notebook.__init__(self, id=-1, parent=parent, 
+              name='ProjectPropertiesPanel', style=0, 
+              pos=wx.Point(0, 0), size=wx.Size(500, 300))
+
+        self.Controller = controller
+        self.ParentWindow = window
+        self.Values = None
+        
+        # Project Panel elements
+
+        self.ProjectPanel = wx.Panel(id=-1, parent=self, 
+              name='ProjectPanel', pos=wx.Point(0, 0),
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        projectpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15)
+        projectpanel_sizer.AddGrowableCol(1)
+        self.ProjectPanel.SetSizer(projectpanel_sizer)
+        
+        self.AddSizerParams(self.ProjectPanel, projectpanel_sizer,
+              [("projectName", _('Project Name (required):')),
+               ("projectVersion", _('Project Version (optional):')),
+               ("productName", _('Product Name (required):')),
+               ("productVersion", _('Product Version (required):')),
+               ("productRelease", _('Product Release (optional):'))])
+        
+        self.AddPage(self.ProjectPanel, _("Project"))
+        
+        # Author Panel elements
+
+        self.AuthorPanel = wx.Panel(id=-1, parent=self,
+              name='AuthorPanel', pos=wx.Point(0, 0),
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        authorpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15)
+        authorpanel_sizer.AddGrowableCol(1)
+        self.AuthorPanel.SetSizer(authorpanel_sizer)
+        
+        self.AddSizerParams(self.AuthorPanel, authorpanel_sizer,
+              [("companyName", _('Company Name (required):')),
+               ("companyURL", _('Company URL (optional):')),
+               ("authorName", _('Author Name (optional):')),
+               ("organization", _('Organization (optional):'))])
+        
+        self.AddPage(self.AuthorPanel, _("Author"))
+
+        # Graphics Panel elements
+
+        self.GraphicsPanel = wx.Panel(id=-1, parent=self, 
+              name='GraphicsPanel', pos=wx.Point(0, 0),
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        graphicpanel_sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5)
+        graphicpanel_sizer.AddGrowableCol(0)
+        graphicpanel_sizer.AddGrowableRow(3)
+        self.GraphicsPanel.SetSizer(graphicpanel_sizer)
+        
+        pageSize_st = wx.StaticText(id=-1, parent=self.GraphicsPanel,
+              label=_('Page Size (optional):'), name='pageSize_label', 
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        graphicpanel_sizer.AddWindow(pageSize_st, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT)
+        
+        pageSize_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
+        pageSize_sizer.AddGrowableCol(1)
+        graphicpanel_sizer.AddSizer(pageSize_sizer, 0, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT)
+        
+        for name, label in [('PageWidth', _('Width:')),
+                            ('PageHeight', _('Height:'))]:
+            st = wx.StaticText(id=-1, parent=self.GraphicsPanel,
+                  label=label, name=name + "_label",
+                  pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+            pageSize_sizer.AddWindow(st, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT)
+            
+            sp_id = wx.NewId()
+            sp = wx.SpinCtrl(id=sp_id, parent=self.GraphicsPanel, 
+                  name=name, pos=wx.Point(0, 0),
+                  size=wx.Size(0, 24), style=wx.TE_PROCESS_ENTER, 
+                  min=0, max=2**16)
+            setattr(self, name, sp)
+            callback = self.GetPageSizeChangedFunction(sp, name)
+            self.Bind(wx.EVT_TEXT_ENTER, callback, id=sp_id)
+            sp.Bind(wx.EVT_KILL_FOCUS, callback)
+            pageSize_sizer.AddWindow(sp, 0, border=0, flag=wx.GROW)
+        
+        scaling_st = wx.StaticText(id=-1, parent=self.GraphicsPanel,
+              label=_('Grid Resolution:'), name='scaling_label', 
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        graphicpanel_sizer.AddWindow(scaling_st, 0, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT)
+        
+        scaling_nb = wx.Notebook(id=-1, parent=self.GraphicsPanel, 
+              name='ScalingNotebook', pos=wx.Point(0, 0), 
+              size=wx.Size(0, 0), style=0)
+        graphicpanel_sizer.AddWindow(scaling_nb, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
+        
+        self.Scalings = {}
+        for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]:
+            scaling_panel = wx.Panel(id=-1, parent=scaling_nb, 
+                  name=language + '_panel', pos=wx.Point(0, 0),
+                  size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+            scalingpanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
+            scalingpanel_sizer.AddGrowableCol(1)
+            scaling_panel.SetSizer(scalingpanel_sizer)
+            
+            scaling_controls = []
+            for idx, (name, label) in enumerate([('XScale', _('Horizontal:')),
+                                                 ('YScale', _('Vertical:'))]):
+                if idx == 0:
+                    border = wx.TOP
+                else:
+                    border = wx.BOTTOM
+                
+                st = wx.StaticText(id=-1, parent=scaling_panel,
+                      label=label, name=name + '_label', 
+                      pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+                scalingpanel_sizer.AddWindow(st, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|border|wx.LEFT)
+                
+                sp_id = wx.NewId()
+                sp = wx.SpinCtrl(id=sp_id, parent=scaling_panel, 
+                      name=name, pos=wx.Point(0, 0),
+                      size=wx.Size(0, 24), style=wx.TE_PROCESS_ENTER, 
+                      min=0, max=2**16)
+                scaling_controls.append(sp)
+                callback = self.GetScalingChangedFunction(sp, language, name)
+                self.Bind(wx.EVT_TEXT_ENTER, callback, id=sp_id)
+                sp.Bind(wx.EVT_KILL_FOCUS, callback)
+                scalingpanel_sizer.AddWindow(sp, 0, border=10, flag=wx.GROW|border|wx.RIGHT)
+        
+            self.Scalings[language] = scaling_controls
+            scaling_nb.AddPage(scaling_panel, translation)
+        
+        self.AddPage(self.GraphicsPanel, _("Graphics"))
+
+        # Miscellaneous Panel elements
+
+        self.MiscellaneousPanel = wx.Panel(id=-1, parent=self, 
+              name='MiscellaneousPanel', pos=wx.Point(0, 0),
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        miscellaneouspanel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15)
+        miscellaneouspanel_sizer.AddGrowableCol(1)
+        miscellaneouspanel_sizer.AddGrowableRow(1)
+        self.MiscellaneousPanel.SetSizer(miscellaneouspanel_sizer)
+        
+        language_label = wx.StaticText(id=-1, parent=self.MiscellaneousPanel,
+              label=_('Language (optional):'), name='language_label', 
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        miscellaneouspanel_sizer.AddWindow(language_label, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT)
+        
+        language_id = wx.NewId()
+        self.Language = wx.ComboBox(id=language_id, parent=self.MiscellaneousPanel, 
+              name='Language', pos=wx.Point(0, 0),
+              size=wx.Size(0, 28), style=wx.CB_READONLY)
+        self.Bind(wx.EVT_COMBOBOX, self.OnLanguageChanged, id=language_id)
+        miscellaneouspanel_sizer.AddWindow(self.Language, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT)
+        
+        description_label = wx.StaticText(id=-1, parent=self.MiscellaneousPanel,
+              label=_('Content Description (optional):'), name='description_label', 
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        miscellaneouspanel_sizer.AddWindow(description_label, 0, border=10, flag=wx.BOTTOM|wx.LEFT)
+        
+        description_id = wx.NewId()
+        self.ContentDescription = wx.TextCtrl(id=description_id, parent=self.MiscellaneousPanel, 
+              name='ContentDescription', pos=wx.Point(0, 0),
+              size=wx.Size(0, 24), style=wx.TE_MULTILINE|wx.TE_PROCESS_ENTER)
+        self.Bind(wx.EVT_TEXT_ENTER, self.OnContentDescriptionChanged, id=description_id)
+        self.ContentDescription.Bind(wx.EVT_KILL_FOCUS, self.OnContentDescriptionChanged)
+        miscellaneouspanel_sizer.AddWindow(self.ContentDescription, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT)
+        
+        self.AddPage(self.MiscellaneousPanel, _("Miscellaneous"))
+        
+        for param in REQUIRED_PARAMS:
+            getattr(self, param).Enable(enable_required)
+           
+        languages = ["", "en-US", "fr-FR", "zh-CN"]
+        
+        for language in languages:
+            self.Language.Append(language)
+
+    def RefreshView(self):
+        if self.Controller is not None:
+            self.SetValues(self.Controller.GetProjectProperties())
+
+    def SetValues(self, values):
+        self.Values = values
+        for item, value in values.items():
+            if item == "language":
+                self.Language.SetStringSelection(value)
+            elif item == "contentDescription":
+                self.ContentDescription.SetValue(value)
+            elif item == "pageSize":
+                self.PageWidth.SetValue(value[0])
+                self.PageHeight.SetValue(value[1])
+            elif item == "scaling":
+                for language, (x, y) in value.items():
+                    if language in self.Scalings:
+                        self.Scalings[language][0].SetValue(x)
+                        self.Scalings[language][1].SetValue(y)
+            else:
+                tc = getattr(self, item, None)
+                if tc is not None:
+                    tc.SetValue(value)
+        
+    def GetValues(self):
+        values = {}
+        for param in ["projectName", "projectVersion",
+                      "productName", "productVersion",
+                      "productRelease", "companyName",
+                      "companyURL", "authorName", 
+                      "organization"]:
+            value = getattr(self, param).GetValue()
+            if param in REQUIRED_PARAMS or value != "":
+                values[param] = value
+        if self.Language.GetStringSelection() != "":
+            values["language"] = self.Language.GetStringSelection()
+        if self.ContentDescription.GetValue() != "":
+            values["contentDescription"] = self.ContentDescription.GetValue()
+        values["pageSize"] = (self.PageWidth.GetValue(), self.PageHeight.GetValue())
+        values["scaling"] = {}
+        for language in ["FBD", "LD", "SFC"]:
+            values["scaling"][language] = (self.Scalings[language][0].GetValue(),
+                                           self.Scalings[language][1].GetValue())
+        return values
+    
+    def GetTextCtrlChangedFunction(self, textctrl, name):
+        def TextCtrlChangedFunction(event):
+            if self.Controller is not None:
+                if self.Values is not None:
+                    old_value = self.Values.get(name)
+                else:
+                    old_value = None
+                new_value = textctrl.GetValue()
+                if old_value != new_value:
+                    self.Controller.SetProjectProperties(properties={name: new_value})
+                    self.ParentWindow.RefreshTitle()
+                    self.ParentWindow.RefreshFileMenu()
+                    self.ParentWindow.RefreshEditMenu()
+                    self.ParentWindow.RefreshProjectTree()
+                    self.ParentWindow.RefreshPageTitles()
+                    wx.CallAfter(self.RefreshView)
+            event.Skip()
+        return TextCtrlChangedFunction
+
+    def GetPageSizeChangedFunction(self, spinctrl, name):
+        def PageSizeChangedFunction(event):
+            if self.Controller is not None:
+                if self.Values is not None:
+                    old_value = self.Values.get("pageSize")
+                else:
+                    old_value = (0, 0)
+                if name == 'PageWidth':
+                    new_value = (spinctrl.GetValue(), old_value[1])
+                else:
+                    new_value = (old_value[0], spinctrl.GetValue())
+                if old_value != new_value:
+                    self.Controller.SetProjectProperties(properties={"pageSize": new_value})
+                    self.ParentWindow.RefreshTitle()
+                    self.ParentWindow.RefreshFileMenu()
+                    self.ParentWindow.RefreshEditMenu()
+                    self.ParentWindow.RefreshPageTitles()
+                    self.ParentWindow.RefreshScaling()
+                    wx.CallAfter(self.RefreshView)
+            event.Skip()
+        return PageSizeChangedFunction
+    
+    def GetScalingChangedFunction(self, spinctrl, language, name):
+        def ScalingChangedFunction(event):
+            if self.Controller is not None:
+                old_value = (0, 0)
+                if self.Values is not None:
+                    scaling = self.Values.get("scaling")
+                    if scaling is not None:
+                        old_value = scaling.get(language)
+                if name == 'XScale':
+                    new_value = (spinctrl.GetValue(), old_value[1])
+                else:
+                    new_value = (old_value[0], spinctrl.GetValue())
+                if old_value != new_value:
+                    self.Controller.SetProjectProperties(properties={"scaling": {language: new_value}})
+                    self.ParentWindow.RefreshTitle()
+                    self.ParentWindow.RefreshFileMenu()
+                    self.ParentWindow.RefreshEditMenu()
+                    self.ParentWindow.RefreshPageTitles()
+                    self.ParentWindow.RefreshScaling()
+                    wx.CallAfter(self.RefreshView)
+            event.Skip()
+        return ScalingChangedFunction
+    
+    def OnLanguageChanged(self, event):
+        if self.Controller is not None:
+            if self.Values is not None:
+                old_value = self.Values.get("language")
+            else:
+                old_value = None
+            new_value = self.Language.GetStringSelection()
+            if old_value != new_value:
+                self.Controller.SetProjectProperties(properties={"language": new_value})
+                self.ParentWindow.RefreshTitle()
+                self.ParentWindow.RefreshFileMenu()
+                self.ParentWindow.RefreshEditMenu()
+                self.ParentWindow.RefreshPageTitles()
+                wx.CallAfter(self.RefreshView)
+        event.Skip()
+        
+    def OnContentDescriptionChanged(self, event):
+        if self.Controller is not None:
+            if self.Values is not None:
+                old_value = self.Values.get("contentDescription")
+            else:
+                old_value = None
+            new_value = self.ContentDescription.GetValue()
+            if old_value != new_value:
+                self.Controller.SetProjectProperties(properties={"contentDescription": new_value})
+                self.ParentWindow.RefreshTitle()
+                self.ParentWindow.RefreshFileMenu()
+                self.ParentWindow.RefreshEditMenu()
+                self.ParentWindow.RefreshPageTitles()
+                wx.CallAfter(self.RefreshView)
+        event.Skip()
--- a/controls/__init__.py	Wed May 30 12:20:27 2012 +0200
+++ b/controls/__init__.py	Sun Jun 03 23:47:13 2012 +0200
@@ -27,10 +27,11 @@
 from CustomEditableListBox import CustomEditableListBox
 from CustomGrid import CustomGrid
 from CustomTable import CustomTable
+from CustomTree import CustomTree
+from DurationCellEditor import DurationCellEditor
 from EditorPanel import EditorPanel
-from DurationCellEditor import DurationCellEditor
+from LibraryPanel import LibraryPanel
 from LocationCellEditor import LocationCellEditor
+from PouInstanceVariablesPanel import PouInstanceVariablesPanel
+from ProjectPropertiesPanel import ProjectPropertiesPanel
 from VariablePanel import VariablePanel
-from LibraryPanel import LibraryPanel
-from PouInstanceVariablesPanel import PouInstanceVariablesPanel
-from CustomTree import CustomTree
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dialogs/ProjectDialog.py	Sun Jun 03 23:47:13 2012 +0200
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2012: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx
+
+from controls import ProjectPropertiesPanel
+
+class ProjectDialog(wx.Dialog):
+    
+    def __init__(self, parent, enable_required=True):
+        wx.Dialog.__init__(self, id=-1, parent=parent,
+              name='ProjectDialog', title=_('Project properties'), 
+              size=wx.Size(500, 350), style=wx.DEFAULT_DIALOG_STYLE)
+        self.SetClientSize(wx.Size(500, 350))
+        
+        main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
+        main_sizer.AddGrowableCol(0)
+        main_sizer.AddGrowableRow(0)
+        
+        self.ProjectProperties = ProjectPropertiesPanel(self, enable_required=enable_required)
+        main_sizer.AddWindow(self.ProjectProperties, 0, border=0, flag=wx.GROW)
+        
+        self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
+        main_sizer.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
+        
+        self.SetSizer(main_sizer)
+        
+    def OnOK(self, event):
+        values = self.ProjectProperties.GetValues()
+        error = []
+        for param, name in [("projectName", "Project Name"),
+                            ("productName", "Product Name"),
+                            ("productVersion", "Product Version"),
+                            ("companyName", "Company Name")]:
+            if values[param] == "":
+                error.append(name)
+        if len(error) > 0:
+            text = ""
+            for i, item in enumerate(error):
+                if i == 0:
+                    text += item
+                elif i == len(error) - 1:
+                    text += " and %s"%item
+                else:
+                    text += ", %s"%item
+            message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        else:
+            self.EndModal(wx.ID_OK)
+
+    def SetValues(self, values):
+        self.ProjectProperties.SetValues(values)
+        
+    def GetValues(self):
+        return self.ProjectProperties.GetValues()
--- a/dialogs/__init__.py	Wed May 30 12:20:27 2012 +0200
+++ b/dialogs/__init__.py	Sun Jun 03 23:47:13 2012 +0200
@@ -39,3 +39,4 @@
 from DurationEditorDialog import DurationEditorDialog
 from SearchInProjectDialog import SearchInProjectDialog
 from BrowseLocationsDialog import BrowseLocationsDialog
+from ProjectDialog import ProjectDialog
--- a/plcopen/plcopen.py	Wed May 30 12:20:27 2012 +0200
+++ b/plcopen/plcopen.py	Sun Jun 03 23:47:13 2012 +0200
@@ -178,52 +178,57 @@
     
     def getfileHeader(self):
         fileheader = {}
-        fileheader["companyName"] = self.fileHeader.getcompanyName()
-        if self.fileHeader.getcompanyURL():
-            fileheader["companyURL"] = self.fileHeader.getcompanyURL()
-        fileheader["productName"] = self.fileHeader.getproductName()
-        fileheader["productVersion"] = self.fileHeader.getproductVersion()
-        if self.fileHeader.getproductRelease():
-            fileheader["productRelease"] = self.fileHeader.getproductRelease()
-        fileheader["creationDateTime"] = self.fileHeader.getcreationDateTime()
-        if self.fileHeader.getcontentDescription():
-            fileheader["contentDescription"] = self.fileHeader.getcontentDescription()
+        for name, value in [("companyName", self.fileHeader.getcompanyName()),
+                            ("companyURL", self.fileHeader.getcompanyURL()),
+                            ("productName", self.fileHeader.getproductName()),
+                            ("productVersion", self.fileHeader.getproductVersion()),
+                            ("productRelease", self.fileHeader.getproductRelease()),
+                            ("creationDateTime", self.fileHeader.getcreationDateTime()),
+                            ("contentDescription", self.fileHeader.getcontentDescription())]:
+            if value is not None:
+                fileheader[name] = value
+            else:
+                fileheader[name] = ""
         return fileheader
     setattr(cls, "getfileHeader", getfileHeader)
     
     def setfileHeader(self, fileheader):
-        self.fileHeader.setcompanyName(fileheader["companyName"])
+        if fileheader.has_key("companyName"):
+            self.fileHeader.setcompanyName(fileheader["companyName"])
         if fileheader.has_key("companyURL"):
             self.fileHeader.setcompanyURL(fileheader["companyURL"])
-        self.fileHeader.setproductName(fileheader["productName"])
-        self.fileHeader.setproductVersion(fileheader["productVersion"])
+        if fileheader.has_key("productName"):
+            self.fileHeader.setproductName(fileheader["productName"])
+        if fileheader.has_key("productVersion"):
+            self.fileHeader.setproductVersion(fileheader["productVersion"])
         if fileheader.has_key("productRelease"):
             self.fileHeader.setproductRelease(fileheader["productRelease"])
-        self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
+        if fileheader.has_key("creationDateTime"):
+            self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
         if fileheader.has_key("contentDescription"):
             self.fileHeader.setcontentDescription(fileheader["contentDescription"])
     setattr(cls, "setfileHeader", setfileHeader)
     
     def getcontentHeader(self):
         contentheader = {}
-        contentheader["projectName"] = self.contentHeader.getname()
-        if self.contentHeader.getversion():
-            contentheader["projectVersion"] = self.contentHeader.getversion()
-        if self.contentHeader.getmodificationDateTime():
-            contentheader["modificationDateTime"] = self.contentHeader.getmodificationDateTime()
-        if self.contentHeader.getorganization():
-            contentheader["organization"] = self.contentHeader.getorganization()
-        if self.contentHeader.getauthor():
-            contentheader["authorName"] = self.contentHeader.getauthor()
-        if self.contentHeader.getlanguage():
-            contentheader["language"] = self.contentHeader.getlanguage()
+        for name, value in [("projectName", self.contentHeader.getname()),
+                            ("projectVersion", self.contentHeader.getversion()),
+                            ("modificationDateTime", self.contentHeader.getmodificationDateTime()),
+                            ("organization", self.contentHeader.getorganization()),
+                            ("authorName", self.contentHeader.getauthor()),
+                            ("language", self.contentHeader.getlanguage())]:
+            if value is not None:
+                contentheader[name] = value
+            else:
+                contentheader[name] = ""
         contentheader["pageSize"] = self.contentHeader.getpageSize()
         contentheader["scaling"] = self.contentHeader.getscaling()
         return contentheader
     setattr(cls, "getcontentHeader", getcontentHeader)
     
     def setcontentHeader(self, contentheader):
-        self.contentHeader.setname(contentheader["projectName"])
+        if contentheader.has_key("projectName"):
+            self.contentHeader.setname(contentheader["projectName"])
         if contentheader.has_key("projectVersion"):
             self.contentHeader.setversion(contentheader["projectVersion"])
         if contentheader.has_key("modificationDateTime"):