IDEFrame.py
branch1.1 Korean release
changeset 968 eee7625de1f7
parent 930 4be515ac635e
child 970 0dd89c8eeef5
equal deleted inserted replaced
808:6e205c1f05a0 968:eee7625de1f7
       
     1 
       
     2 import os, sys
       
     3 import cPickle
       
     4 from types import TupleType
       
     5 
       
     6 import wx, wx.grid
       
     7 import wx.aui
       
     8 
       
     9 try:
       
    10     import matplotlib
       
    11     matplotlib.use('WX')
       
    12     USE_MPL = True
       
    13 except:
       
    14     USE_MPL = False
       
    15 
       
    16 from editors.EditorPanel import EditorPanel
       
    17 from editors.SFCViewer import SFC_Viewer
       
    18 from editors.LDViewer import LD_Viewer
       
    19 from editors.TextViewer import TextViewer
       
    20 from editors.Viewer import Viewer, ZOOM_FACTORS
       
    21 from editors.GraphicViewer import GraphicViewer
       
    22 from editors.ResourceEditor import ConfigurationEditor, ResourceEditor
       
    23 from editors.DataTypeEditor import DataTypeEditor
       
    24 from PLCControler import *
       
    25 from controls import CustomTree, LibraryPanel, PouInstanceVariablesPanel, DebugVariablePanel, SearchResultPanel
       
    26 from dialogs import ProjectDialog, PouDialog, PouTransitionDialog, PouActionDialog, FindInPouDialog, SearchInProjectDialog
       
    27 from util.BitmapLibrary import GetBitmap
       
    28 
       
    29 # Define PLCOpenEditor controls id
       
    30 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
       
    31  ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, 
       
    32  ID_PLCOPENEDITORPROJECTTREE, ID_PLCOPENEDITORMAINSPLITTER, 
       
    33  ID_PLCOPENEDITORSECONDSPLITTER, ID_PLCOPENEDITORTHIRDSPLITTER, 
       
    34  ID_PLCOPENEDITORLIBRARYPANEL, ID_PLCOPENEDITORLIBRARYSEARCHCTRL, 
       
    35  ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT, 
       
    36  ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED, 
       
    37  ID_PLCOPENEDITOREDITORMENUTOOLBAR, ID_PLCOPENEDITOREDITORTOOLBAR, 
       
    38  ID_PLCOPENEDITORPROJECTPANEL, 
       
    39 ] = [wx.NewId() for _init_ctrls in range(17)]
       
    40 
       
    41 # Define PLCOpenEditor EditMenu extra items id
       
    42 [ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE, 
       
    43  ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, 
       
    44  ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
       
    45  ID_PLCOPENEDITOREDITMENUFINDNEXT, ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
       
    46  ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, 
       
    47 ] = [wx.NewId() for _init_coll_EditMenu_Items in range(9)]
       
    48 
       
    49 # Define PLCOpenEditor DisplayMenu extra items id
       
    50 [ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE, 
       
    51 ] = [wx.NewId() for _init_coll_DisplayMenu_Items in range(1)]
       
    52 
       
    53 #-------------------------------------------------------------------------------
       
    54 #                            EditorToolBar definitions
       
    55 #-------------------------------------------------------------------------------
       
    56 
       
    57 # Define PLCOpenEditor Toolbar items id
       
    58 [ID_PLCOPENEDITOREDITORTOOLBARSELECTION, ID_PLCOPENEDITOREDITORTOOLBARCOMMENT,
       
    59  ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, ID_PLCOPENEDITOREDITORTOOLBARBLOCK,
       
    60  ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, ID_PLCOPENEDITOREDITORTOOLBARWIRE,
       
    61  ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, ID_PLCOPENEDITOREDITORTOOLBARRUNG,
       
    62  ID_PLCOPENEDITOREDITORTOOLBARCOIL, ID_PLCOPENEDITOREDITORTOOLBARCONTACT,
       
    63  ID_PLCOPENEDITOREDITORTOOLBARBRANCH, ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP,
       
    64  ID_PLCOPENEDITOREDITORTOOLBARSTEP, ID_PLCOPENEDITOREDITORTOOLBARTRANSITION,
       
    65  ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE,
       
    66  ID_PLCOPENEDITOREDITORTOOLBARJUMP, ID_PLCOPENEDITOREDITORTOOLBARMOTION, 
       
    67 ] = [wx.NewId() for _init_coll_DefaultEditorToolBar_Items in range(18)]
       
    68 
       
    69 
       
    70 
       
    71 # Define behaviour of each Toolbar item according to current POU body type 
       
    72 # Informations meaning are in this order:
       
    73 #  - Item is toggled
       
    74 #  - PLCOpenEditor mode where item is displayed (could be more then one)
       
    75 #  - Item id
       
    76 #  - Item callback function name
       
    77 #  - Item icon filename
       
    78 #  - Item tooltip text
       
    79 EditorToolBarItems = {
       
    80     "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
    81               ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
       
    82               "move", _("Move the view")),
       
    83              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
    84               ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool",
       
    85               "add_comment", _("Create a new comment")),
       
    86              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
    87               ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool",
       
    88               "add_variable", _("Create a new variable")),
       
    89              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
    90               ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool",
       
    91               "add_block", _("Create a new block")),
       
    92              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
    93               ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
       
    94               "add_connection", _("Create a new connection"))],
       
    95     "LD"  : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
    96               ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
       
    97               "move", _("Move the view")),
       
    98              (True, FREEDRAWING_MODE, 
       
    99               ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool", 
       
   100               "add_comment", _("Create a new comment")),
       
   101              (True, FREEDRAWING_MODE, 
       
   102               ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool", 
       
   103               "add_powerrail", _("Create a new power rail")),
       
   104              (False, DRIVENDRAWING_MODE, 
       
   105               ID_PLCOPENEDITOREDITORTOOLBARRUNG, "OnRungTool", 
       
   106               "add_rung", _("Create a new rung")),
       
   107              (True, FREEDRAWING_MODE, 
       
   108               ID_PLCOPENEDITOREDITORTOOLBARCOIL, "OnCoilTool", 
       
   109               "add_coil", _("Create a new coil")),
       
   110              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   111               ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool", 
       
   112               "add_contact", _("Create a new contact")),
       
   113              (False, DRIVENDRAWING_MODE, 
       
   114               ID_PLCOPENEDITOREDITORTOOLBARBRANCH, "OnBranchTool", 
       
   115               "add_branch", _("Create a new branch")),
       
   116              (True, FREEDRAWING_MODE, 
       
   117               ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool", 
       
   118               "add_variable", _("Create a new variable")),
       
   119              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   120               ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool", 
       
   121               "add_block", _("Create a new block")),
       
   122              (True, FREEDRAWING_MODE, 
       
   123               ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
       
   124               "add_connection", _("Create a new connection"))],
       
   125     "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
   126               ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
       
   127               "move", _("Move the view")),
       
   128              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   129               ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool", 
       
   130               "add_comment", _("Create a new comment")),
       
   131              (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   132               ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP, "OnInitialStepTool", 
       
   133               "add_initial_step", _("Create a new initial step")),
       
   134              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   135               ID_PLCOPENEDITOREDITORTOOLBARSTEP, "OnStepTool", 
       
   136               "add_step", _("Create a new step")),
       
   137              (True, FREEDRAWING_MODE, 
       
   138               ID_PLCOPENEDITOREDITORTOOLBARTRANSITION, "OnTransitionTool", 
       
   139               "add_transition", _("Create a new transition")),
       
   140              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   141               ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, "OnActionBlockTool", 
       
   142               "add_action", _("Create a new action block")),
       
   143              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   144               ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE, "OnDivergenceTool", 
       
   145               "add_divergence", _("Create a new divergence")),
       
   146              (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
       
   147               ID_PLCOPENEDITOREDITORTOOLBARJUMP, "OnJumpTool", 
       
   148               "add_jump", _("Create a new jump")),
       
   149              (True, FREEDRAWING_MODE, 
       
   150               ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool", 
       
   151               "add_variable", _("Create a new variable")),
       
   152              (True, FREEDRAWING_MODE, 
       
   153               ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool", 
       
   154               "add_block", _("Create a new block")),
       
   155              (True, FREEDRAWING_MODE, 
       
   156               ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
       
   157               "add_connection", _("Create a new connection")),
       
   158              (True, FREEDRAWING_MODE, 
       
   159               ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool", 
       
   160               "add_powerrail", _("Create a new power rail")),
       
   161              (True, FREEDRAWING_MODE, 
       
   162               ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool", 
       
   163               "add_contact", _("Create a new contact"))],
       
   164     "ST"  : [],
       
   165     "IL"  : [],
       
   166     "debug": [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
       
   167               ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
       
   168               "move", _("Move the view"))],
       
   169 }
       
   170 
       
   171 #-------------------------------------------------------------------------------
       
   172 #                               Helper Functions
       
   173 #-------------------------------------------------------------------------------
       
   174 
       
   175 import base64
       
   176 
       
   177 def EncodeFileSystemPath(path, use_base64=True):
       
   178     path = path.encode(sys.getfilesystemencoding())
       
   179     if use_base64:
       
   180         return base64.encodestring(path)
       
   181     return path
       
   182 
       
   183 def DecodeFileSystemPath(path, is_base64=True):
       
   184     if is_base64:
       
   185         path = base64.decodestring(path)
       
   186     return unicode(path, sys.getfilesystemencoding())
       
   187 
       
   188 # Compatibility function for wx versions < 2.6
       
   189 def AppendMenu(parent, help, id, kind, text):
       
   190     if wx.VERSION >= (2, 6, 0):
       
   191         parent.Append(help=help, id=id, kind=kind, text=text)
       
   192     else:
       
   193         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
   194 
       
   195 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
       
   196  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
       
   197 ] = range(10)
       
   198 
       
   199 def GetShortcutKeyCallbackFunction(viewer_function):
       
   200     def ShortcutKeyFunction(self, event):
       
   201         control = self.FindFocus()
       
   202         if control is not None and control.GetName() in ["Viewer", "TextViewer"]:
       
   203             getattr(control.ParentWindow, viewer_function)()
       
   204         elif isinstance(control, wx.stc.StyledTextCtrl):
       
   205             getattr(control, viewer_function)()
       
   206         elif isinstance(control, wx.TextCtrl):
       
   207             control.ProcessEvent(event)
       
   208     return ShortcutKeyFunction
       
   209 
       
   210 def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None):
       
   211     def DeleteElementFunction(self, selected):
       
   212         name = self.ProjectTree.GetItemText(selected)
       
   213         if check_function is None or not check_function(self.Controler, name):
       
   214             if parent_type is not None:
       
   215                 item_infos = self.ProjectTree.GetPyData(selected)
       
   216                 parent_name = item_infos["tagname"].split("::")[1]
       
   217                 remove_function(self.Controler, parent_name, name)
       
   218             else:
       
   219                 remove_function(self.Controler, name)
       
   220         else:
       
   221             self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")%name)
       
   222     return DeleteElementFunction
       
   223 
       
   224 if wx.Platform == '__WXMSW__':
       
   225     TAB_BORDER = 6
       
   226     NOTEBOOK_BORDER = 6
       
   227 else:
       
   228     TAB_BORDER = 7
       
   229     NOTEBOOK_BORDER = 2
       
   230 
       
   231 def SimplifyTabLayout(tabs, rect):
       
   232     for tab in tabs:
       
   233         if tab["pos"][0] == rect.x:
       
   234             others = [t for t in tabs if t != tab]
       
   235             others.sort(lambda x,y: cmp(x["pos"][0], y["pos"][0]))
       
   236             for other in others:
       
   237                 if (other["pos"][1] == tab["pos"][1] and 
       
   238                     other["size"][1] == tab["size"][1] and
       
   239                     other["pos"][0] == tab["pos"][0] + tab["size"][0] + TAB_BORDER):
       
   240                     
       
   241                     tab["size"] = (tab["size"][0] + other["size"][0] + TAB_BORDER, tab["size"][1])
       
   242                     tab["pages"].extend(other["pages"])
       
   243                     tabs.remove(other)
       
   244                     
       
   245                     if tab["size"][0] == rect.width:
       
   246                         return True
       
   247                     
       
   248         elif tab["pos"][1] == rect.y:
       
   249             others = [t for t in tabs if t != tab]
       
   250             others.sort(lambda x,y: cmp(x["pos"][1], y["pos"][1]))
       
   251             for other in others:
       
   252                 if (other["pos"][0] == tab["pos"][0] and 
       
   253                     other["size"][0] == tab["size"][0] and
       
   254                     other["pos"][1] == tab["pos"][1] + tab["size"][1] + TAB_BORDER):
       
   255                     
       
   256                     tab["size"] = (tab["size"][0], tab["size"][1] + other["size"][1] + TAB_BORDER)
       
   257                     tab["pages"].extend(other["pages"])
       
   258                     tabs.remove(other)
       
   259                     
       
   260                     if tab["size"][1] == rect.height:
       
   261                         return True
       
   262     return False
       
   263     
       
   264 def ComputeTabsLayout(tabs, rect):
       
   265     if len(tabs) == 0:
       
   266         return tabs
       
   267     if len(tabs) == 1:
       
   268         return tabs[0]
       
   269     split = None
       
   270     for idx, tab in enumerate(tabs):
       
   271         if len(tab["pages"]) == 0:
       
   272             raise ValueError, "Not possible"
       
   273         if tab["size"][0] == rect.width:
       
   274             if tab["pos"][1] == rect.y:
       
   275                 split = (wx.TOP, float(tab["size"][1]) / float(rect.height))
       
   276                 split_rect = wx.Rect(rect.x, rect.y + tab["size"][1] + TAB_BORDER, 
       
   277                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
       
   278             elif tab["pos"][1] == rect.height + 1 - tab["size"][1]:
       
   279                 split = (wx.BOTTOM, 1.0 - float(tab["size"][1]) / float(rect.height))
       
   280                 split_rect = wx.Rect(rect.x, rect.y, 
       
   281                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
       
   282             break
       
   283         elif tab["size"][1] == rect.height:
       
   284             if tab["pos"][0] == rect.x:
       
   285                 split = (wx.LEFT, float(tab["size"][0]) / float(rect.width))
       
   286                 split_rect = wx.Rect(rect.x + tab["size"][0] + TAB_BORDER, rect.y, 
       
   287                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
       
   288             elif tab["pos"][0] == rect.width + 1 - tab["size"][0]:
       
   289                 split = (wx.RIGHT, 1.0 - float(tab["size"][0]) / float(rect.width))
       
   290                 split_rect = wx.Rect(rect.x, rect.y, 
       
   291                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
       
   292             break
       
   293     if split != None:
       
   294         split_tab = tabs.pop(idx)
       
   295         return {"split": split,
       
   296                 "tab": split_tab, 
       
   297                 "others": ComputeTabsLayout(tabs, split_rect)}
       
   298     else:
       
   299         if SimplifyTabLayout(tabs, rect):
       
   300             return ComputeTabsLayout(tabs, rect)
       
   301     return tabs
       
   302 
       
   303 #-------------------------------------------------------------------------------
       
   304 #                              IDEFrame Base Class
       
   305 #-------------------------------------------------------------------------------
       
   306 
       
   307 UNEDITABLE_NAMES_DICT = dict([(_(name), name) for name in UNEDITABLE_NAMES])
       
   308 
       
   309 class IDEFrame(wx.Frame):
       
   310     
       
   311     Starting = False
       
   312     
       
   313     # Compatibility function for wx versions < 2.6
       
   314     if wx.VERSION < (2, 6, 0):
       
   315         def Bind(self, event, function, id = None):
       
   316             if id is not None:
       
   317                 event(self, id, function)
       
   318             else:
       
   319                 event(self, function)
       
   320     
       
   321     def _init_coll_MenuBar_Menus(self, parent):
       
   322         parent.Append(menu=self.FileMenu, title=_(u'&File'))
       
   323         parent.Append(menu=self.EditMenu, title=_(u'&Edit'))
       
   324         parent.Append(menu=self.DisplayMenu, title=_(u'&Display'))
       
   325         parent.Append(menu=self.HelpMenu, title=_(u'&Help'))
       
   326 
       
   327     def _init_coll_FileMenu_Items(self, parent):
       
   328         pass
       
   329     
       
   330     def _init_coll_AddMenu_Items(self, parent, add_config=True):
       
   331         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE,
       
   332               kind=wx.ITEM_NORMAL, text=_(u'&Data Type'))
       
   333         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION,
       
   334               kind=wx.ITEM_NORMAL, text=_(u'&Function'))
       
   335         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK,
       
   336               kind=wx.ITEM_NORMAL, text=_(u'Function &Block'))
       
   337         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM,
       
   338               kind=wx.ITEM_NORMAL, text=_(u'&Program'))
       
   339         if add_config:
       
   340             AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
       
   341                   kind=wx.ITEM_NORMAL, text=_(u'&Configuration'))
       
   342     
       
   343     def _init_coll_EditMenu_Items(self, parent):
       
   344         AppendMenu(parent, help='', id=wx.ID_UNDO,
       
   345               kind=wx.ITEM_NORMAL, text=_(u'Undo') + '\tCTRL+Z')
       
   346         AppendMenu(parent, help='', id=wx.ID_REDO,
       
   347               kind=wx.ITEM_NORMAL, text=_(u'Redo') + '\tCTRL+Y')
       
   348         #AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO,
       
   349         #      kind=wx.ITEM_CHECK, text=_(u'Enable Undo/Redo'))
       
   350         enable_undo_redo = _(u'Enable Undo/Redo') # Keeping text in translations for possible menu reactivation
       
   351         parent.AppendSeparator()
       
   352         AppendMenu(parent, help='', id=wx.ID_CUT,
       
   353               kind=wx.ITEM_NORMAL, text=_(u'Cut') + '\tCTRL+X')
       
   354         AppendMenu(parent, help='', id=wx.ID_COPY,
       
   355               kind=wx.ITEM_NORMAL, text=_(u'Copy') + '\tCTRL+C')
       
   356         AppendMenu(parent, help='', id=wx.ID_PASTE,
       
   357               kind=wx.ITEM_NORMAL, text=_(u'Paste') + '\tCTRL+V')
       
   358         parent.AppendSeparator()
       
   359         AppendMenu(parent, help='', id=wx.ID_FIND,
       
   360               kind=wx.ITEM_NORMAL, text=_(u'Find') + '\tCTRL+F')
       
   361         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDNEXT,
       
   362               kind=wx.ITEM_NORMAL, text=_(u'Find Next') + '\tCTRL+K')
       
   363         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
       
   364               kind=wx.ITEM_NORMAL, text=_(u'Find Previous') + '\tCTRL+SHIFT+K')
       
   365         parent.AppendSeparator()
       
   366         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT,
       
   367               kind=wx.ITEM_NORMAL, text=_(u'Search in Project') + '\tCTRL+SHIFT+F')
       
   368         parent.AppendSeparator()
       
   369         add_menu = wx.Menu(title='')
       
   370         self._init_coll_AddMenu_Items(add_menu)
       
   371         parent.AppendMenu(wx.ID_ADD, _(u"&Add Element"), add_menu)
       
   372         AppendMenu(parent, help='', id=wx.ID_SELECTALL,
       
   373               kind=wx.ITEM_NORMAL, text=_(u'Select All') + '\tCTRL+A')
       
   374         AppendMenu(parent, help='', id=wx.ID_DELETE,
       
   375               kind=wx.ITEM_NORMAL, text=_(u'&Delete'))
       
   376         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
       
   377         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
       
   378         #self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO)
       
   379         self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT)
       
   380         self.Bind(wx.EVT_MENU, self.OnCopyMenu, id=wx.ID_COPY)
       
   381         self.Bind(wx.EVT_MENU, self.OnPasteMenu, id=wx.ID_PASTE)
       
   382         self.Bind(wx.EVT_MENU, self.OnFindMenu, id=wx.ID_FIND)
       
   383         self.Bind(wx.EVT_MENU, self.OnFindNextMenu, 
       
   384               id=ID_PLCOPENEDITOREDITMENUFINDNEXT)
       
   385         self.Bind(wx.EVT_MENU, self.OnFindPreviousMenu, 
       
   386               id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS)
       
   387         self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu, 
       
   388               id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT)
       
   389         self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu, 
       
   390               id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT)
       
   391         self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu,
       
   392               id=ID_PLCOPENEDITOREDITMENUADDDATATYPE)
       
   393         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("function"),
       
   394               id=ID_PLCOPENEDITOREDITMENUADDFUNCTION)
       
   395         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("functionBlock"),
       
   396               id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK)
       
   397         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("program"),
       
   398               id=ID_PLCOPENEDITOREDITMENUADDPROGRAM)
       
   399         self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu,
       
   400               id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION)
       
   401         self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL)
       
   402         self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE)
       
   403         
       
   404         self.AddToMenuToolBar([(wx.ID_UNDO, "undo", _(u'Undo'), None),
       
   405                                (wx.ID_REDO, "redo", _(u'Redo'), None),
       
   406                                None,
       
   407                                (wx.ID_CUT, "cut", _(u'Cut'), None),
       
   408                                (wx.ID_COPY, "copy", _(u'Copy'), None),
       
   409                                (wx.ID_PASTE, "paste", _(u'Paste'), None),
       
   410                                None,
       
   411                                (ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, "find", _(u'Search in Project'), None)])
       
   412 
       
   413     def _init_coll_DisplayMenu_Items(self, parent):
       
   414         AppendMenu(parent, help='', id=wx.ID_REFRESH,
       
   415               kind=wx.ITEM_NORMAL, text=_(u'Refresh') + '\tCTRL+R')
       
   416         if self.EnableDebug:
       
   417             AppendMenu(parent, help='', id=wx.ID_CLEAR,
       
   418                   kind=wx.ITEM_NORMAL, text=_(u'Clear Errors') + '\tCTRL+K')
       
   419         parent.AppendSeparator()
       
   420         zoommenu = wx.Menu(title='')
       
   421         parent.AppendMenu(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu)
       
   422         for idx, value in enumerate(ZOOM_FACTORS):
       
   423             new_id = wx.NewId()
       
   424             AppendMenu(zoommenu, help='', id=new_id,
       
   425                   kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%")
       
   426             self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), id=new_id)
       
   427         
       
   428         parent.AppendSeparator()
       
   429         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE,
       
   430               kind=wx.ITEM_NORMAL, text=_(u'Reset Perspective'))
       
   431         self.Bind(wx.EVT_MENU, self.OnResetPerspective, id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE)
       
   432         
       
   433         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
       
   434         if self.EnableDebug:
       
   435             self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR)
       
   436             
       
   437     def _init_coll_HelpMenu_Items(self, parent):
       
   438         pass
       
   439 
       
   440     def _init_utils(self):
       
   441         self.MenuBar = wx.MenuBar()
       
   442 
       
   443         self.FileMenu = wx.Menu(title='')
       
   444         self.EditMenu = wx.Menu(title='')
       
   445         self.DisplayMenu = wx.Menu(title='')
       
   446         self.HelpMenu = wx.Menu(title='')
       
   447         
       
   448         self._init_coll_MenuBar_Menus(self.MenuBar)
       
   449         self._init_coll_FileMenu_Items(self.FileMenu)
       
   450         self._init_coll_EditMenu_Items(self.EditMenu)
       
   451         self._init_coll_DisplayMenu_Items(self.DisplayMenu)
       
   452         self._init_coll_HelpMenu_Items(self.HelpMenu)
       
   453 
       
   454     def _init_ctrls(self, prnt):
       
   455         wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame',
       
   456               parent=prnt, pos=wx.DefaultPosition, size=wx.Size(1000, 600),
       
   457               style=wx.DEFAULT_FRAME_STYLE)
       
   458         self.SetClientSize(wx.Size(1000, 600))
       
   459         self.Bind(wx.EVT_ACTIVATE, self.OnActivated)
       
   460         self.Bind(wx.EVT_SIZE, self.OnResize)
       
   461         
       
   462         self.TabsImageList = wx.ImageList(31, 16)
       
   463         self.TabsImageListIndexes = {}
       
   464         
       
   465         #-----------------------------------------------------------------------
       
   466         #                          Creating main structure
       
   467         #-----------------------------------------------------------------------
       
   468         
       
   469         self.AUIManager = wx.aui.AuiManager(self)
       
   470         self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
       
   471         self.Panes = {}
       
   472         
       
   473         self.LeftNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORLEFTNOTEBOOK,
       
   474               style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
       
   475                     wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
       
   476         self.LeftNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
       
   477                 self.OnAllowNotebookDnD)
       
   478         self.AUIManager.AddPane(self.LeftNoteBook, 
       
   479               wx.aui.AuiPaneInfo().Name("ProjectPane").
       
   480               Left().Layer(1).
       
   481               BestSize(wx.Size(300, 500)).CloseButton(False))
       
   482         
       
   483         self.BottomNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORBOTTOMNOTEBOOK,
       
   484               style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
       
   485                     wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
       
   486         self.BottomNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
       
   487                 self.OnAllowNotebookDnD)
       
   488         self.AUIManager.AddPane(self.BottomNoteBook, 
       
   489               wx.aui.AuiPaneInfo().Name("ResultPane").
       
   490               Bottom().Layer(0).
       
   491               BestSize(wx.Size(800, 300)).CloseButton(False))
       
   492         
       
   493         self.RightNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORRIGHTNOTEBOOK,
       
   494               style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
       
   495                     wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
       
   496         self.RightNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
       
   497                 self.OnAllowNotebookDnD)
       
   498         self.AUIManager.AddPane(self.RightNoteBook, 
       
   499               wx.aui.AuiPaneInfo().Name("LibraryPane").
       
   500               Right().Layer(0).
       
   501               BestSize(wx.Size(250, 400)).CloseButton(False))
       
   502         
       
   503         self.TabsOpened = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORTABSOPENED, 
       
   504               style=wx.aui.AUI_NB_DEFAULT_STYLE|wx.aui.AUI_NB_WINDOWLIST_BUTTON)
       
   505         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGING,
       
   506               self.OnPouSelectedChanging)
       
   507         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED,
       
   508               self.OnPouSelectedChanged)
       
   509         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE,
       
   510               self.OnPageClose)
       
   511         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_END_DRAG,
       
   512               self.OnPageDragged)
       
   513         self.AUIManager.AddPane(self.TabsOpened, 
       
   514               wx.aui.AuiPaneInfo().CentrePane().Name("TabsPane"))
       
   515         
       
   516         #-----------------------------------------------------------------------
       
   517         #                    Creating PLCopen Project Types Tree
       
   518         #-----------------------------------------------------------------------
       
   519         
       
   520         self.MainTabs = {}
       
   521         
       
   522         self.ProjectPanel = wx.SplitterWindow(id=ID_PLCOPENEDITORPROJECTPANEL,
       
   523                   name='ProjectPanel', parent=self.LeftNoteBook, point=wx.Point(0, 0),
       
   524                   size=wx.Size(0, 0), style=wx.SP_3D)
       
   525         
       
   526         self.ProjectTree = CustomTree(id=ID_PLCOPENEDITORPROJECTTREE,
       
   527                   name='ProjectTree', parent=self.ProjectPanel, 
       
   528                   pos=wx.Point(0, 0), size=wx.Size(0, 0),
       
   529                   style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_EDIT_LABELS)
       
   530         self.ProjectTree.SetBackgroundBitmap(GetBitmap("custom_tree_background"),
       
   531                                              wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM)
       
   532         add_menu = wx.Menu()
       
   533         self._init_coll_AddMenu_Items(add_menu)
       
   534         self.ProjectTree.SetAddMenu(add_menu)
       
   535         if wx.Platform == '__WXMSW__':
       
   536             self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnProjectTreeRightUp,
       
   537                   id=ID_PLCOPENEDITORPROJECTTREE)
       
   538             self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnProjectTreeItemSelected,
       
   539                   id=ID_PLCOPENEDITORPROJECTTREE)
       
   540         else:
       
   541             self.ProjectTree.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp)
       
   542             self.ProjectTree.Bind(wx.EVT_LEFT_UP, self.OnProjectTreeLeftUp)
       
   543             self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnProjectTreeItemChanging,
       
   544                   id=ID_PLCOPENEDITORPROJECTTREE)
       
   545         self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnProjectTreeBeginDrag,
       
   546               id=ID_PLCOPENEDITORPROJECTTREE)
       
   547         self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnProjectTreeItemBeginEdit,
       
   548               id=ID_PLCOPENEDITORPROJECTTREE)
       
   549         self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnProjectTreeItemEndEdit,
       
   550               id=ID_PLCOPENEDITORPROJECTTREE)
       
   551         self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnProjectTreeItemActivated,
       
   552               id=ID_PLCOPENEDITORPROJECTTREE)
       
   553         
       
   554         #-----------------------------------------------------------------------
       
   555         #        Creating PLCopen Project POU Instance Variables Panel
       
   556         #-----------------------------------------------------------------------
       
   557         
       
   558         self.PouInstanceVariablesPanel = PouInstanceVariablesPanel(self.ProjectPanel, self, self.Controler, self.EnableDebug)
       
   559         
       
   560         self.MainTabs["ProjectPanel"] = (self.ProjectPanel, _("Project"))
       
   561         self.LeftNoteBook.AddPage(*self.MainTabs["ProjectPanel"])
       
   562         
       
   563         self.ProjectPanel.SplitHorizontally(self.ProjectTree, self.PouInstanceVariablesPanel, 300)
       
   564         
       
   565         #-----------------------------------------------------------------------
       
   566         #                            Creating Tool Bar
       
   567         #-----------------------------------------------------------------------
       
   568         
       
   569         MenuToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORMENUTOOLBAR, wx.DefaultPosition, wx.DefaultSize,
       
   570                 wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
       
   571         MenuToolBar.SetToolBitmapSize(wx.Size(25, 25))
       
   572         MenuToolBar.Realize()
       
   573         self.Panes["MenuToolBar"] = MenuToolBar
       
   574         self.AUIManager.AddPane(MenuToolBar, wx.aui.AuiPaneInfo().
       
   575                   Name("MenuToolBar").Caption(_("Menu ToolBar")).
       
   576                   ToolbarPane().Top().
       
   577                   LeftDockable(False).RightDockable(False))
       
   578         
       
   579         EditorToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORTOOLBAR, wx.DefaultPosition, wx.DefaultSize,
       
   580                 wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
       
   581         EditorToolBar.SetToolBitmapSize(wx.Size(25, 25))
       
   582         EditorToolBar.AddRadioTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, 
       
   583               GetBitmap("select"), wx.NullBitmap, _("Select an object"))
       
   584         EditorToolBar.Realize()
       
   585         self.Panes["EditorToolBar"] = EditorToolBar
       
   586         self.AUIManager.AddPane(EditorToolBar, wx.aui.AuiPaneInfo().
       
   587                   Name("EditorToolBar").Caption(_("Editor ToolBar")).
       
   588                   ToolbarPane().Top().Position(1).
       
   589                   LeftDockable(False).RightDockable(False))
       
   590             
       
   591         self.Bind(wx.EVT_MENU, self.OnSelectionTool, 
       
   592               id=ID_PLCOPENEDITOREDITORTOOLBARSELECTION)
       
   593         
       
   594         #-----------------------------------------------------------------------
       
   595         #                            Creating Search Panel
       
   596         #-----------------------------------------------------------------------
       
   597         
       
   598         self.SearchResultPanel = SearchResultPanel(self.BottomNoteBook, self)
       
   599         self.MainTabs["SearchResultPanel"] = (self.SearchResultPanel, _("Search"))
       
   600         self.BottomNoteBook.AddPage(*self.MainTabs["SearchResultPanel"])
       
   601         
       
   602         #-----------------------------------------------------------------------
       
   603         #                            Creating Library Panel
       
   604         #-----------------------------------------------------------------------
       
   605         
       
   606         self.LibraryPanel = LibraryPanel(self, True)
       
   607         self.MainTabs["LibraryPanel"] = (self.LibraryPanel, _("Library"))
       
   608         self.RightNoteBook.AddPage(*self.MainTabs["LibraryPanel"])
       
   609                 
       
   610         self._init_utils()
       
   611         self.SetMenuBar(self.MenuBar)
       
   612                 
       
   613         if self.EnableDebug:
       
   614             self.DebugVariablePanel = DebugVariablePanel(self.RightNoteBook, self.Controler, self)
       
   615             self.MainTabs["DebugVariablePanel"] = (self.DebugVariablePanel, _("Debugger"))
       
   616             self.RightNoteBook.AddPage(*self.MainTabs["DebugVariablePanel"])
       
   617         
       
   618         self.AUIManager.Update()
       
   619     
       
   620         self.FindDialog = FindInPouDialog(self)
       
   621         self.FindDialog.Hide()
       
   622     
       
   623     ## Constructor of the PLCOpenEditor class.
       
   624     #  @param parent The parent window.
       
   625     #  @param controler The controler been used by PLCOpenEditor (default: None).
       
   626     #  @param fileOpen The filepath to open if no controler defined (default: None).
       
   627     #  @param debug The filepath to open if no controler defined (default: False).
       
   628     def __init__(self, parent, enable_debug = False):
       
   629         self.Controler = None
       
   630         self.Config = wx.ConfigBase.Get()
       
   631         self.EnableDebug = enable_debug
       
   632         
       
   633         self._init_ctrls(parent)
       
   634         
       
   635         # Define Tree item icon list
       
   636         self.TreeImageList = wx.ImageList(16, 16)
       
   637         self.TreeImageDict = {}
       
   638         
       
   639         # Icons for languages
       
   640         for language in LANGUAGES:
       
   641             self.TreeImageDict[language] = self.TreeImageList.Add(GetBitmap(language))
       
   642             
       
   643         # Icons for other items
       
   644         for imgname, itemtype in [
       
   645             #editables
       
   646             ("PROJECT",        ITEM_PROJECT),
       
   647             #("POU",            ITEM_POU),
       
   648             #("VARIABLE",       ITEM_VARIABLE),
       
   649             ("TRANSITION",     ITEM_TRANSITION),
       
   650             ("ACTION",         ITEM_ACTION),
       
   651             ("CONFIGURATION",  ITEM_CONFIGURATION),
       
   652             ("RESOURCE",       ITEM_RESOURCE),
       
   653             ("DATATYPE",       ITEM_DATATYPE),
       
   654             # uneditables
       
   655             ("DATATYPES",      ITEM_DATATYPES),
       
   656             ("FUNCTION",       ITEM_FUNCTION),
       
   657             ("FUNCTIONBLOCK",  ITEM_FUNCTIONBLOCK),
       
   658             ("PROGRAM",        ITEM_PROGRAM),
       
   659             ("VAR_LOCAL",      ITEM_VAR_LOCAL),
       
   660             ("VAR_LOCAL",      ITEM_VAR_GLOBAL),
       
   661             ("VAR_LOCAL",      ITEM_VAR_EXTERNAL),
       
   662             ("VAR_LOCAL",      ITEM_VAR_TEMP),
       
   663             ("VAR_INPUT",      ITEM_VAR_INPUT),
       
   664             ("VAR_OUTPUT",     ITEM_VAR_OUTPUT),
       
   665             ("VAR_INOUT",      ITEM_VAR_INOUT),
       
   666             ("TRANSITIONS",    ITEM_TRANSITIONS),
       
   667             ("ACTIONS",        ITEM_ACTIONS),
       
   668             ("CONFIGURATIONS", ITEM_CONFIGURATIONS),
       
   669             ("RESOURCES",      ITEM_RESOURCES),
       
   670             ("PROPERTIES",     ITEM_PROPERTIES)]:
       
   671             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
       
   672         
       
   673         # Assign icon list to TreeCtrls
       
   674         self.ProjectTree.SetImageList(self.TreeImageList)
       
   675         self.PouInstanceVariablesPanel.SetTreeImageList(self.TreeImageList)
       
   676         
       
   677         self.CurrentEditorToolBar = []
       
   678         self.CurrentMenu = None
       
   679         self.SelectedItem = None
       
   680         self.SearchParams = None
       
   681         self.Highlights = {}
       
   682         self.DrawingMode = FREEDRAWING_MODE
       
   683         #self.DrawingMode = DRIVENDRAWING_MODE
       
   684         self.AuiTabCtrl = []
       
   685         self.DefaultPerspective = None
       
   686         
       
   687         # Initialize Printing configuring elements
       
   688         self.PrintData = wx.PrintData()
       
   689         self.PrintData.SetPaperId(wx.PAPER_A4)
       
   690         self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER)
       
   691         self.PageSetupData = wx.PageSetupDialogData(self.PrintData)
       
   692         self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15))
       
   693         self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20))
       
   694         
       
   695         self.SetRefreshFunctions()
       
   696     
       
   697     def __del__(self):
       
   698         self.FindDialog.Destroy()
       
   699     
       
   700     def ResetStarting(self):
       
   701         self.Starting = False
       
   702     
       
   703     def Show(self):
       
   704         wx.Frame.Show(self)
       
   705         wx.CallAfter(self.RestoreLastState)
       
   706     
       
   707     def OnActivated(self, event):
       
   708         if event.GetActive():
       
   709             wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
       
   710         event.Skip()
       
   711 
       
   712 #-------------------------------------------------------------------------------
       
   713 #                Saving and restoring frame organization functions
       
   714 #-------------------------------------------------------------------------------
       
   715 
       
   716     def OnResize(self, event):
       
   717         if self.Starting:
       
   718             self.RestoreLastLayout()
       
   719         event.Skip()
       
   720     
       
   721     def GetProjectConfiguration(self):
       
   722         projects = {}
       
   723         try:
       
   724             if self.Config.HasEntry("projects"):
       
   725                 projects = cPickle.loads(str(self.Config.Read("projects")))
       
   726         except:
       
   727             pass
       
   728         
       
   729         return projects.get(
       
   730             EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
       
   731     
       
   732     def SavePageState(self, page):
       
   733         state = page.GetState()
       
   734         if state is not None:
       
   735             if self.Config.HasEntry("projects"):
       
   736                 projects = cPickle.loads(str(self.Config.Read("projects")))
       
   737             else:
       
   738                 projects = {}
       
   739             
       
   740             project_infos = projects.setdefault(
       
   741                  EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
       
   742             editors_state = project_infos.setdefault("editors_state", {})
       
   743             
       
   744             if page.IsDebugging():
       
   745                 editors_state[page.GetInstancePath()] = state
       
   746             else:
       
   747                 editors_state[page.GetTagName()] = state
       
   748             
       
   749             self.Config.Write("projects", cPickle.dumps(projects))
       
   750             self.Config.Flush()
       
   751     
       
   752     def GetTabInfos(self, tab):
       
   753         if isinstance(tab, EditorPanel):
       
   754             if tab.IsDebugging():
       
   755                 return ("debug", tab.GetInstancePath())
       
   756             else:
       
   757                 return ("editor", tab.GetTagName())
       
   758         else:
       
   759             for page_name, (page_ref, page_title) in self.MainTabs.iteritems():
       
   760                 if page_ref == tab:
       
   761                     return ("main", page_name)
       
   762         return None
       
   763     
       
   764     def SaveTabLayout(self, notebook):
       
   765         tabs = []
       
   766         for child in notebook.GetChildren():
       
   767             if isinstance(child, wx.aui.AuiTabCtrl):
       
   768                 if child.GetPageCount() > 0:
       
   769                     pos = child.GetPosition()
       
   770                     tab = {"pos": (pos.x, pos.y), "pages": []}
       
   771                     tab_size = child.GetSize()
       
   772                     for page_idx in xrange(child.GetPageCount()):
       
   773                         page = child.GetWindowFromIdx(page_idx)
       
   774                         if not tab.has_key("size"):
       
   775                             tab["size"] = (tab_size[0], tab_size[1] + page.GetSize()[1])
       
   776                         tab_infos = self.GetTabInfos(page)
       
   777                         if tab_infos is not None:
       
   778                             tab["pages"].append((tab_infos, page_idx == child.GetActivePage()))
       
   779                     tabs.append(tab)
       
   780         tabs.sort(lambda x, y: cmp(x["pos"], y["pos"]))
       
   781         size = notebook.GetSize()
       
   782         return ComputeTabsLayout(tabs, wx.Rect(1, 1, size[0] - NOTEBOOK_BORDER, size[1] - NOTEBOOK_BORDER))
       
   783     
       
   784     def LoadTab(self, notebook, page_infos):
       
   785         if page_infos[0] == "main":
       
   786             infos = self.MainTabs.get(page_infos[1])
       
   787             if infos is not None:
       
   788                 page_ref, page_title = infos
       
   789                 notebook.AddPage(page_ref, page_title)
       
   790                 return notebook.GetPageIndex(page_ref)
       
   791         elif page_infos[0] == "editor":
       
   792             tagname = page_infos[1]
       
   793             page_ref = self.EditProjectElement(self.Controler.GetElementType(tagname), tagname)
       
   794             if page_ref is not None:
       
   795                 page_ref.RefreshView()
       
   796                 return notebook.GetPageIndex(page_ref)
       
   797         elif page_infos[0] == "debug":
       
   798             instance_path = page_infos[1]
       
   799             instance_infos = self.Controler.GetInstanceInfos(instance_path, self.EnableDebug)
       
   800             if instance_infos is not None:
       
   801                 return notebook.GetPageIndex(self.OpenDebugViewer(instance_infos["class"], instance_path, instance_infos["type"]))
       
   802         return None
       
   803             
       
   804     def LoadTabLayout(self, notebook, tabs, mode="all", first_index=None):
       
   805         if isinstance(tabs, ListType):
       
   806             if len(tabs) == 0:
       
   807                 return
       
   808             raise ValueError, "Not supported"
       
   809         
       
   810         if tabs.has_key("split"):
       
   811             self.LoadTabLayout(notebook, tabs["others"])
       
   812             
       
   813             split_dir, split_ratio = tabs["split"]
       
   814             first_index = self.LoadTabLayout(notebook, tabs["tab"], mode="first")
       
   815             notebook.Split(first_index, split_dir)
       
   816             self.LoadTabLayout(notebook, tabs["tab"], mode="others", first_index=first_index)
       
   817             
       
   818         elif mode == "first":
       
   819             return self.LoadTab(notebook, tabs["pages"][0][0])
       
   820         else:
       
   821             selected = first_index
       
   822             if mode == "others":
       
   823                 add_tabs = tabs["pages"][1:]
       
   824             else:
       
   825                 add_tabs = tabs["pages"]
       
   826             for page_infos, page_selected in add_tabs:
       
   827                 page_idx = self.LoadTab(notebook, page_infos)
       
   828                 if page_selected:
       
   829                     selected = page_idx
       
   830             if selected is not None:
       
   831                 wx.CallAfter(notebook.SetSelection, selected)
       
   832     
       
   833     def ResetPerspective(self):
       
   834         if self.DefaultPerspective is not None:
       
   835             self.AUIManager.LoadPerspective(self.DefaultPerspective["perspective"])
       
   836         
       
   837             for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
       
   838                 for idx in xrange(notebook.GetPageCount()):
       
   839                     notebook.RemovePage(0)
       
   840                         
       
   841             notebooks = self.DefaultPerspective["notebooks"]
       
   842             for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
       
   843                                          (self.BottomNoteBook, "bottomnotebook"),
       
   844                                          (self.RightNoteBook, "rightnotebook")]:
       
   845                 self.LoadTabLayout(notebook, notebooks.get(entry_name))
       
   846     
       
   847             self._Refresh(EDITORTOOLBAR)
       
   848     
       
   849     def RestoreLastState(self):
       
   850         frame_size = None
       
   851         if self.Config.HasEntry("framesize"):
       
   852             frame_size = cPickle.loads(str(self.Config.Read("framesize")))
       
   853         
       
   854         self.Starting = True
       
   855         if frame_size is None:
       
   856             self.Maximize()
       
   857         else:
       
   858             self.SetClientSize(frame_size)
       
   859             wx.CallAfter(self.RestoreLastLayout)
       
   860         
       
   861     def RestoreLastLayout(self):
       
   862         notebooks = {}
       
   863         for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
       
   864                                      (self.BottomNoteBook, "bottomnotebook"),
       
   865                                      (self.RightNoteBook, "rightnotebook")]:
       
   866             notebooks[entry_name] = self.SaveTabLayout(notebook)
       
   867         self.DefaultPerspective = {
       
   868             "perspective": self.AUIManager.SavePerspective(),
       
   869             "notebooks": notebooks,
       
   870         }
       
   871         
       
   872         try:
       
   873             if self.Config.HasEntry("perspective"):
       
   874                 self.AUIManager.LoadPerspective(unicode(self.Config.Read("perspective")))
       
   875         
       
   876             if self.Config.HasEntry("notebooks"):
       
   877                 notebooks = cPickle.loads(str(self.Config.Read("notebooks")))
       
   878                 
       
   879                 for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
       
   880                     for idx in xrange(notebook.GetPageCount()):
       
   881                         notebook.RemovePage(0)
       
   882                         
       
   883                 for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
       
   884                                              (self.BottomNoteBook, "bottomnotebook"),
       
   885                                              (self.RightNoteBook, "rightnotebook")]:
       
   886                     self.LoadTabLayout(notebook, notebooks.get(entry_name))
       
   887         except:
       
   888             self.ResetPerspective()
       
   889         
       
   890         self.LoadProjectLayout()
       
   891         
       
   892         self._Refresh(EDITORTOOLBAR)
       
   893         
       
   894         if wx.Platform == '__WXMSW__':
       
   895             wx.CallAfter(self.ResetStarting)
       
   896         else:
       
   897             self.ResetStarting()
       
   898         wx.CallAfter(self.RefreshEditor)
       
   899     
       
   900     def SaveLastState(self):
       
   901         if not self.IsMaximized():
       
   902             self.Config.Write("framesize", cPickle.dumps(self.GetClientSize()))
       
   903         elif self.Config.HasEntry("framesize"):
       
   904             self.Config.DeleteEntry("framesize")
       
   905         
       
   906         notebooks = {}
       
   907         for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
       
   908                                      (self.BottomNoteBook, "bottomnotebook"),
       
   909                                      (self.RightNoteBook, "rightnotebook")]:
       
   910             notebooks[entry_name] = self.SaveTabLayout(notebook)
       
   911         self.Config.Write("notebooks", cPickle.dumps(notebooks))
       
   912         
       
   913         pane = self.AUIManager.GetPane(self.TabsOpened)
       
   914         if pane.IsMaximized():
       
   915             self.AUIManager.RestorePane(pane)
       
   916         self.Config.Write("perspective", self.AUIManager.SavePerspective())
       
   917     
       
   918         self.SaveProjectLayout()
       
   919         
       
   920         for i in xrange(self.TabsOpened.GetPageCount()):
       
   921             self.SavePageState(self.TabsOpened.GetPage(i))
       
   922         
       
   923         self.Config.Flush()
       
   924 
       
   925     def SaveProjectLayout(self):
       
   926         if self.Controler is not None:
       
   927             tabs = []
       
   928             
       
   929             projects = {}
       
   930             try:
       
   931                  if self.Config.HasEntry("projects"):
       
   932                     projects = cPickle.loads(str(self.Config.Read("projects")))
       
   933             except:
       
   934                 pass
       
   935             
       
   936             project_infos = projects.setdefault(
       
   937                  EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
       
   938             project_infos["tabs"] = self.SaveTabLayout(self.TabsOpened)
       
   939             if self.EnableDebug:
       
   940                 project_infos["debug_vars"] = self.DebugVariablePanel.GetDebugVariables()
       
   941                 
       
   942             self.Config.Write("projects", cPickle.dumps(projects))
       
   943             self.Config.Flush()
       
   944     
       
   945     def LoadProjectLayout(self):
       
   946         if self.Controler is not None:
       
   947             project = self.GetProjectConfiguration()
       
   948             
       
   949             try:
       
   950                 if project.has_key("tabs"):
       
   951                     self.LoadTabLayout(self.TabsOpened, project["tabs"])
       
   952             except:
       
   953                 self.DeleteAllPages()
       
   954                 
       
   955             if self.EnableDebug:
       
   956                 #try:
       
   957                 self.DebugVariablePanel.SetDebugVariables(project.get("debug_vars", []))
       
   958                 #except:
       
   959                 #    self.DebugVariablePanel.ResetView()
       
   960             
       
   961 #-------------------------------------------------------------------------------
       
   962 #                               General Functions
       
   963 #-------------------------------------------------------------------------------
       
   964 
       
   965     def SetRefreshFunctions(self):
       
   966         self.RefreshFunctions = {
       
   967             TITLE : self.RefreshTitle,
       
   968             EDITORTOOLBAR : self.RefreshEditorToolBar,
       
   969             FILEMENU : self.RefreshFileMenu,
       
   970             EDITMENU : self.RefreshEditMenu,
       
   971             DISPLAYMENU : self.RefreshDisplayMenu,
       
   972             PROJECTTREE : self.RefreshProjectTree,
       
   973             POUINSTANCEVARIABLESPANEL : self.RefreshPouInstanceVariablesPanel, 
       
   974             LIBRARYTREE : self.RefreshLibraryPanel,
       
   975             SCALING : self.RefreshScaling,
       
   976             PAGETITLES: self.RefreshPageTitles}
       
   977 
       
   978     ## Call PLCOpenEditor refresh functions.
       
   979     #  @param elements List of elements to refresh.
       
   980     def _Refresh(self, *elements):
       
   981         try:
       
   982             for element in elements:
       
   983                 self.RefreshFunctions[element]()
       
   984         except wx.PyDeadObjectError:
       
   985             # ignore exceptions caused by refresh while quitting
       
   986             pass
       
   987 
       
   988     ## Callback function when AUINotebook Page closed with CloseButton
       
   989     #  @param event AUINotebook Event.
       
   990     def OnPageClose(self, event):
       
   991         selected = self.TabsOpened.GetSelection()
       
   992         if selected > -1:
       
   993             window = self.TabsOpened.GetPage(selected)
       
   994             
       
   995             if window.CheckSaveBeforeClosing():
       
   996                 self.SavePageState(window)
       
   997                 
       
   998                 # Refresh all window elements that have changed
       
   999                 wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
       
  1000                 wx.CallAfter(self.RefreshTabCtrlEvent)
       
  1001                 wx.CallAfter(self.CloseFindInPouDialog)
       
  1002                 event.Skip()
       
  1003             else:
       
  1004                 event.Veto()
       
  1005         
       
  1006 
       
  1007     def GetCopyBuffer(self):
       
  1008         data = None
       
  1009         if wx.TheClipboard.Open():
       
  1010             dataobj = wx.TextDataObject()
       
  1011             if wx.TheClipboard.GetData(dataobj):
       
  1012                 data = dataobj.GetText()
       
  1013             wx.TheClipboard.Close()
       
  1014         return data
       
  1015         
       
  1016     def SetCopyBuffer(self, text):
       
  1017         if wx.TheClipboard.Open():
       
  1018             data = wx.TextDataObject()
       
  1019             data.SetText(text)
       
  1020             wx.TheClipboard.SetData(data)
       
  1021             wx.TheClipboard.Flush()
       
  1022             wx.TheClipboard.Close()
       
  1023         self.RefreshEditMenu()
       
  1024 
       
  1025     def GetDrawingMode(self):
       
  1026         return self.DrawingMode
       
  1027 
       
  1028     def RefreshScaling(self):
       
  1029         for i in xrange(self.TabsOpened.GetPageCount()):
       
  1030             editor = self.TabsOpened.GetPage(i)
       
  1031             editor.RefreshScaling()
       
  1032 
       
  1033     def EditProjectSettings(self):
       
  1034         old_values = self.Controler.GetProjectProperties()
       
  1035         dialog = ProjectDialog(self)
       
  1036         dialog.SetValues(old_values)
       
  1037         if dialog.ShowModal() == wx.ID_OK:
       
  1038             new_values = dialog.GetValues()
       
  1039             new_values["creationDateTime"] = old_values["creationDateTime"]
       
  1040             if new_values != old_values:
       
  1041                 self.Controler.SetProjectProperties(None, new_values)
       
  1042                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, 
       
  1043                               PROJECTTREE, POUINSTANCEVARIABLESPANEL, SCALING)
       
  1044         dialog.Destroy()
       
  1045 
       
  1046 #-------------------------------------------------------------------------------
       
  1047 #                            Notebook Unified Functions
       
  1048 #-------------------------------------------------------------------------------
       
  1049     
       
  1050     ## Function that add a tab in Notebook, calling refresh for tab DClick event
       
  1051     # for wx.aui.AUINotebook.
       
  1052     #  @param window Panel to display in tab.
       
  1053     #  @param text title for the tab ctrl.
       
  1054     def AddPage(self, window, text):
       
  1055         self.TabsOpened.AddPage(window, text)
       
  1056         self.RefreshTabCtrlEvent()
       
  1057     
       
  1058     ## Function that add a tab in Notebook, calling refresh for tab DClick event
       
  1059     # for wx.aui.AUINotebook.
       
  1060     #  @param window Panel to display in tab.
       
  1061     #  @param text title for the tab ctrl.
       
  1062     def DeletePage(self, window):
       
  1063         for idx in xrange(self.TabsOpened.GetPageCount()):
       
  1064             if self.TabsOpened.GetPage(idx) == window:
       
  1065                 self.TabsOpened.DeletePage(idx)
       
  1066                 self.RefreshTabCtrlEvent()
       
  1067                 return 
       
  1068         
       
  1069     ## Function that fix difference in deleting all tabs between 
       
  1070     # wx.Notebook and wx.aui.AUINotebook.
       
  1071     def DeleteAllPages(self):
       
  1072         for idx in xrange(self.TabsOpened.GetPageCount()):
       
  1073             self.TabsOpened.DeletePage(0)
       
  1074         self.RefreshTabCtrlEvent()
       
  1075 
       
  1076     ## Function that fix difference in setting picture on tab between 
       
  1077     # wx.Notebook and wx.aui.AUINotebook.
       
  1078     #  @param idx Tab index.
       
  1079     #  @param bitmap wx.Bitmap to define on tab.
       
  1080     #  @return True if operation succeeded
       
  1081     def SetPageBitmap(self, idx, bitmap):
       
  1082         return self.TabsOpened.SetPageBitmap(idx, bitmap)
       
  1083 
       
  1084 #-------------------------------------------------------------------------------
       
  1085 #                         Dialog Message Functions
       
  1086 #-------------------------------------------------------------------------------
       
  1087 
       
  1088     ## Function displaying an Error dialog in PLCOpenEditor.
       
  1089     #  @param message The message to display.
       
  1090     def ShowErrorMessage(self, message):
       
  1091         dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
       
  1092         dialog.ShowModal()
       
  1093         dialog.Destroy()
       
  1094 
       
  1095     ## Function displaying an Error dialog in PLCOpenEditor.
       
  1096     #  @return False if closing cancelled.
       
  1097     def CheckSaveBeforeClosing(self, title=_("Close Project")):
       
  1098         if not self.Controler.ProjectIsSaved():
       
  1099             dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), title, wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
       
  1100             answer = dialog.ShowModal()
       
  1101             dialog.Destroy()
       
  1102             if answer == wx.ID_YES:
       
  1103                 self.SaveProject()
       
  1104             elif answer == wx.ID_CANCEL:
       
  1105                 return False
       
  1106         
       
  1107         for idx in xrange(self.TabsOpened.GetPageCount()):
       
  1108             window = self.TabsOpened.GetPage(idx)
       
  1109             if not window.CheckSaveBeforeClosing():
       
  1110                 return False
       
  1111         
       
  1112         return True
       
  1113 
       
  1114 #-------------------------------------------------------------------------------
       
  1115 #                            File Menu Functions
       
  1116 #-------------------------------------------------------------------------------
       
  1117 
       
  1118     def RefreshFileMenu(self):
       
  1119         pass
       
  1120 
       
  1121     def ResetView(self):
       
  1122         self.DeleteAllPages()
       
  1123         self.ProjectTree.DeleteAllItems()
       
  1124         self.ProjectTree.Enable(False)
       
  1125         self.PouInstanceVariablesPanel.ResetView()
       
  1126         self.LibraryPanel.ResetTree()
       
  1127         self.LibraryPanel.SetController(None)
       
  1128         if self.EnableDebug:
       
  1129             self.DebugVariablePanel.ResetView()
       
  1130         self.Controler = None
       
  1131 
       
  1132     def OnCloseTabMenu(self, event):
       
  1133         selected = self.TabsOpened.GetSelection()
       
  1134         if selected >= 0:
       
  1135             self.TabsOpened.DeletePage(selected)
       
  1136             if self.TabsOpened.GetPageCount() > 0:
       
  1137                 new_index = min(selected, self.TabsOpened.GetPageCount() - 1)
       
  1138                 self.TabsOpened.SetSelection(new_index)
       
  1139         # Refresh all window elements that have changed
       
  1140         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
       
  1141         self.RefreshTabCtrlEvent()
       
  1142 
       
  1143     def OnPageSetupMenu(self, event):
       
  1144         dialog = wx.PageSetupDialog(self, self.PageSetupData)
       
  1145         if dialog.ShowModal() == wx.ID_OK:
       
  1146             self.PageSetupData = wx.PageSetupDialogData(dialog.GetPageSetupData())
       
  1147             self.PrintData = wx.PrintData(self.PageSetupData.GetPrintData())
       
  1148         dialog.Destroy()
       
  1149 
       
  1150     def OnPreviewMenu(self, event):
       
  1151         selected = self.TabsOpened.GetSelection()        
       
  1152         if selected != -1:
       
  1153             window = self.TabsOpened.GetPage(selected)
       
  1154             data = wx.PrintDialogData(self.PrintData)
       
  1155             properties = self.Controler.GetProjectProperties(window.IsDebugging())
       
  1156             page_size = map(int, properties["pageSize"])
       
  1157             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
       
  1158             printout = GraphicPrintout(window, page_size, margins, True)
       
  1159             printout2 = GraphicPrintout(window, page_size, margins, True)
       
  1160             preview = wx.PrintPreview(printout, printout2, data)
       
  1161 
       
  1162             if preview.Ok():
       
  1163                 preview_frame = wx.PreviewFrame(preview, self, _("Print preview"), style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT)
       
  1164 
       
  1165                 preview_frame.Initialize()
       
  1166                 
       
  1167                 preview_canvas = preview.GetCanvas()
       
  1168                 preview_canvas.SetMinSize(preview_canvas.GetVirtualSize())
       
  1169                 preview_frame.Fit()
       
  1170                 
       
  1171                 preview_frame.Show(True)
       
  1172 
       
  1173     def OnPrintMenu(self, event):
       
  1174         selected = self.TabsOpened.GetSelection()        
       
  1175         if selected != -1:
       
  1176             window = self.TabsOpened.GetPage(selected)
       
  1177             dialog_data = wx.PrintDialogData(self.PrintData)
       
  1178             dialog_data.SetToPage(1)
       
  1179             properties = self.Controler.GetProjectProperties(window.IsDebugging())
       
  1180             page_size = map(int, properties["pageSize"])
       
  1181             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
       
  1182             printer = wx.Printer(dialog_data)
       
  1183             printout = GraphicPrintout(window, page_size, margins)
       
  1184             
       
  1185             if not printer.Print(self, printout, True) and printer.GetLastError() != wx.PRINTER_CANCELLED:
       
  1186                 self.ShowErrorMessage(_("There was a problem printing.\nPerhaps your current printer is not set correctly?"))
       
  1187             printout.Destroy()
       
  1188 
       
  1189     def OnPropertiesMenu(self, event):
       
  1190         self.EditProjectSettings()
       
  1191 
       
  1192     def OnQuitMenu(self, event):
       
  1193         self.Close()
       
  1194 
       
  1195 #-------------------------------------------------------------------------------
       
  1196 #                            Edit Menu Functions
       
  1197 #-------------------------------------------------------------------------------
       
  1198 
       
  1199     def RefreshEditMenu(self):
       
  1200         MenuToolBar = self.Panes["MenuToolBar"]
       
  1201         if self.Controler is not None:
       
  1202             selected = self.TabsOpened.GetSelection()
       
  1203             if selected > -1:
       
  1204                 window = self.TabsOpened.GetPage(selected)
       
  1205                 undo, redo = window.GetBufferState()
       
  1206             else:
       
  1207                 undo, redo = self.Controler.GetBufferState()
       
  1208             self.EditMenu.Enable(wx.ID_UNDO, undo)
       
  1209             MenuToolBar.EnableTool(wx.ID_UNDO, undo)
       
  1210             self.EditMenu.Enable(wx.ID_REDO, redo)
       
  1211             MenuToolBar.EnableTool(wx.ID_REDO, redo)
       
  1212             #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, True)
       
  1213             #self.EditMenu.Check(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, 
       
  1214             #                self.Controler.IsProjectBufferEnabled())
       
  1215             self.EditMenu.Enable(wx.ID_FIND, selected > -1)
       
  1216             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT, 
       
  1217                   selected > -1 and self.SearchParams is not None)
       
  1218             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, 
       
  1219                   selected > -1 and self.SearchParams is not None)
       
  1220             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
       
  1221             MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
       
  1222             self.EditMenu.Enable(wx.ID_ADD, True)
       
  1223             self.EditMenu.Enable(wx.ID_DELETE, True)
       
  1224             if self.TabsOpened.GetPageCount() > 0:
       
  1225                 self.EditMenu.Enable(wx.ID_CUT, True)
       
  1226                 MenuToolBar.EnableTool(wx.ID_CUT, True)
       
  1227                 self.EditMenu.Enable(wx.ID_COPY, True)
       
  1228                 MenuToolBar.EnableTool(wx.ID_COPY, True)
       
  1229                 if self.GetCopyBuffer() is not None:
       
  1230                     self.EditMenu.Enable(wx.ID_PASTE, True)
       
  1231                     MenuToolBar.EnableTool(wx.ID_PASTE, True)
       
  1232                 else:
       
  1233                     self.EditMenu.Enable(wx.ID_PASTE, False)
       
  1234                     MenuToolBar.EnableTool(wx.ID_PASTE, False)
       
  1235                 self.EditMenu.Enable(wx.ID_SELECTALL, True)
       
  1236             else:
       
  1237                 self.EditMenu.Enable(wx.ID_CUT, False)
       
  1238                 MenuToolBar.EnableTool(wx.ID_CUT, False)
       
  1239                 self.EditMenu.Enable(wx.ID_COPY, False)
       
  1240                 MenuToolBar.EnableTool(wx.ID_COPY, False)
       
  1241                 self.EditMenu.Enable(wx.ID_PASTE, False)
       
  1242                 MenuToolBar.EnableTool(wx.ID_PASTE, False)
       
  1243                 self.EditMenu.Enable(wx.ID_SELECTALL, False)
       
  1244         else:
       
  1245             self.EditMenu.Enable(wx.ID_UNDO, False)
       
  1246             MenuToolBar.EnableTool(wx.ID_UNDO, False)
       
  1247             self.EditMenu.Enable(wx.ID_REDO, False)
       
  1248             MenuToolBar.EnableTool(wx.ID_REDO, False)
       
  1249             #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False)
       
  1250             self.EditMenu.Enable(wx.ID_CUT, False)
       
  1251             MenuToolBar.EnableTool(wx.ID_CUT, False)
       
  1252             self.EditMenu.Enable(wx.ID_COPY, False)
       
  1253             MenuToolBar.EnableTool(wx.ID_COPY, False)
       
  1254             self.EditMenu.Enable(wx.ID_PASTE, False)
       
  1255             MenuToolBar.EnableTool(wx.ID_PASTE, False)
       
  1256             self.EditMenu.Enable(wx.ID_SELECTALL, False)
       
  1257             self.EditMenu.Enable(wx.ID_FIND, False)
       
  1258             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT, False)
       
  1259             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, False)
       
  1260             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
       
  1261             MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
       
  1262             self.EditMenu.Enable(wx.ID_ADD, False)
       
  1263             self.EditMenu.Enable(wx.ID_DELETE, False)
       
  1264     
       
  1265     def CloseTabsWithoutModel(self, refresh=True):
       
  1266         idxs = range(self.TabsOpened.GetPageCount())
       
  1267         idxs.reverse()
       
  1268         for idx in idxs:
       
  1269             window = self.TabsOpened.GetPage(idx)
       
  1270             if window.HasNoModel():
       
  1271                 self.TabsOpened.DeletePage(idx)
       
  1272         if refresh:
       
  1273             self.RefreshEditor()
       
  1274 
       
  1275     def OnUndoMenu(self, event):
       
  1276         selected = self.TabsOpened.GetSelection()
       
  1277         if selected != -1:
       
  1278             window = self.TabsOpened.GetPage(selected)
       
  1279             window.Undo()
       
  1280         else:
       
  1281             self.Controler.LoadPrevious()
       
  1282         self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, 
       
  1283                       SCALING, PAGETITLES)    
       
  1284     
       
  1285     def OnRedoMenu(self, event):
       
  1286         selected = self.TabsOpened.GetSelection()
       
  1287         if selected != -1:
       
  1288             window = self.TabsOpened.GetPage(selected)
       
  1289             window.Redo()
       
  1290         else:
       
  1291             self.Controler.LoadNext()
       
  1292         self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, 
       
  1293                       SCALING, PAGETITLES)
       
  1294     
       
  1295     def OnEnableUndoRedoMenu(self, event):
       
  1296         self.Controler.EnableProjectBuffer(event.IsChecked())
       
  1297         self.RefreshEditMenu()
       
  1298 
       
  1299     OnCutMenu = GetShortcutKeyCallbackFunction("Cut")
       
  1300     OnCopyMenu = GetShortcutKeyCallbackFunction("Copy")
       
  1301     OnPasteMenu = GetShortcutKeyCallbackFunction("Paste")
       
  1302 
       
  1303     def OnSelectAllMenu(self, event):
       
  1304         control = self.FindFocus()
       
  1305         if control is not None and control.GetName() == "Viewer":
       
  1306             control.Parent.SelectAll()
       
  1307         elif isinstance(control, wx.stc.StyledTextCtrl):
       
  1308             control.SelectAll()
       
  1309         elif isinstance(control, wx.TextCtrl):
       
  1310             control.SetSelection(0, control.GetLastPosition())
       
  1311         elif isinstance(control, wx.ComboBox):
       
  1312             control.SetMark(0, control.GetLastPosition() + 1)
       
  1313     
       
  1314     DeleteFunctions = {
       
  1315         ITEM_DATATYPE: GetDeleteElementFunction(PLCControler.ProjectRemoveDataType, check_function=PLCControler.DataTypeIsUsed),
       
  1316         ITEM_POU: GetDeleteElementFunction(PLCControler.ProjectRemovePou, check_function=PLCControler.PouIsUsed),
       
  1317         ITEM_TRANSITION: GetDeleteElementFunction(PLCControler.ProjectRemovePouTransition, ITEM_POU),
       
  1318         ITEM_ACTION: GetDeleteElementFunction(PLCControler.ProjectRemovePouAction, ITEM_POU),
       
  1319         ITEM_CONFIGURATION: GetDeleteElementFunction(PLCControler.ProjectRemoveConfiguration),
       
  1320         ITEM_RESOURCE: GetDeleteElementFunction(PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION)
       
  1321     }
       
  1322     
       
  1323     def OnDeleteMenu(self, event):
       
  1324         window = self.FindFocus()
       
  1325         if window == self.ProjectTree or window is None:
       
  1326             selected = self.ProjectTree.GetSelection()
       
  1327             if selected.IsOk():
       
  1328                 function = self.DeleteFunctions.get(self.ProjectTree.GetPyData(selected)["type"], None)
       
  1329                 if function is not None:
       
  1330                     function(self, selected)
       
  1331                     self.CloseTabsWithoutModel()
       
  1332                     self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, 
       
  1333                                   POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
       
  1334         elif isinstance(window, (Viewer, TextViewer)):
       
  1335             event = wx.KeyEvent(wx.EVT_CHAR._getEvtType())
       
  1336             event.m_keyCode = wx.WXK_DELETE
       
  1337             window.ProcessEvent(event)
       
  1338 
       
  1339     def OnFindMenu(self, event):
       
  1340         if not self.FindDialog.IsShown():
       
  1341             self.FindDialog.Show()
       
  1342     
       
  1343     def CloseFindInPouDialog(self):
       
  1344         selected = self.TabsOpened.GetSelection()
       
  1345         if selected == -1 and self.FindDialog.IsShown():
       
  1346             self.FindDialog.Hide()
       
  1347     
       
  1348     def OnFindNextMenu(self, event):
       
  1349         self.FindInPou(1)
       
  1350     
       
  1351     def OnFindPreviousMenu(self, event):
       
  1352         self.FindInPou(-1)
       
  1353     
       
  1354     def FindInPou(self, direction, search_params=None):
       
  1355         if search_params is not None:
       
  1356             self.SearchParams = search_params
       
  1357         selected = self.TabsOpened.GetSelection()
       
  1358         if selected != -1:
       
  1359             window = self.TabsOpened.GetPage(selected)
       
  1360             window.Find(direction, self.SearchParams)
       
  1361     
       
  1362     def OnSearchInProjectMenu(self, event):
       
  1363         dialog = SearchInProjectDialog(self)
       
  1364         if dialog.ShowModal() == wx.ID_OK:
       
  1365             criteria = dialog.GetCriteria()
       
  1366             result = self.Controler.SearchInProject(criteria)
       
  1367             self.ClearSearchResults()
       
  1368             self.SearchResultPanel.SetSearchResults(criteria, result)
       
  1369             self.BottomNoteBook.SetSelection(self.BottomNoteBook.GetPageIndex(self.SearchResultPanel))
       
  1370             
       
  1371 #-------------------------------------------------------------------------------
       
  1372 #                             Display Menu Functions
       
  1373 #-------------------------------------------------------------------------------
       
  1374 
       
  1375     def RefreshDisplayMenu(self):
       
  1376         if self.Controler is not None:
       
  1377             if self.TabsOpened.GetPageCount() > 0:
       
  1378                 self.DisplayMenu.Enable(wx.ID_REFRESH, True)
       
  1379                 selected = self.TabsOpened.GetSelection()
       
  1380                 if selected != -1:
       
  1381                     window = self.TabsOpened.GetPage(selected)
       
  1382                     if isinstance(window, Viewer):
       
  1383                         self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, True)
       
  1384                         zoommenu = self.DisplayMenu.FindItemById(wx.ID_ZOOM_FIT).GetSubMenu()
       
  1385                         zoomitem = zoommenu.FindItemByPosition(window.GetScale())
       
  1386                         zoomitem.Check(True)
       
  1387                     else:
       
  1388                         self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
       
  1389                 else:
       
  1390                     self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
       
  1391             else:
       
  1392                 self.DisplayMenu.Enable(wx.ID_REFRESH, False)
       
  1393                 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
       
  1394             if self.EnableDebug:
       
  1395                 self.DisplayMenu.Enable(wx.ID_CLEAR, True)
       
  1396         else:
       
  1397             self.DisplayMenu.Enable(wx.ID_REFRESH, False)
       
  1398             if self.EnableDebug:
       
  1399                 self.DisplayMenu.Enable(wx.ID_CLEAR, False)
       
  1400             self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
       
  1401         
       
  1402     def OnRefreshMenu(self, event):
       
  1403         self.RefreshEditor()
       
  1404 
       
  1405     def OnClearErrorsMenu(self, event):
       
  1406         self.ClearErrors()
       
  1407 
       
  1408     def GenerateZoomFunction(self, idx):
       
  1409         def ZoomFunction(event):
       
  1410             selected = self.TabsOpened.GetSelection()
       
  1411             if selected != -1:
       
  1412                 window = self.TabsOpened.GetPage(selected)
       
  1413                 window.SetScale(idx)
       
  1414                 window.RefreshVisibleElements()
       
  1415                 window.RefreshScrollBars()
       
  1416             event.Skip()
       
  1417         return ZoomFunction
       
  1418 
       
  1419     def OnResetPerspective(self, event):
       
  1420         self.ResetPerspective()
       
  1421 
       
  1422 #-------------------------------------------------------------------------------
       
  1423 #                      Project Editor Panels Management Functions
       
  1424 #-------------------------------------------------------------------------------
       
  1425     
       
  1426     def OnPageDragged(self, event):
       
  1427         wx.CallAfter(self.RefreshTabCtrlEvent)
       
  1428         event.Skip()
       
  1429     
       
  1430     def OnAllowNotebookDnD(self, event):
       
  1431         event.Allow()
       
  1432     
       
  1433     def RefreshTabCtrlEvent(self):
       
  1434         auitabctrl = []
       
  1435         for child in self.TabsOpened.GetChildren():
       
  1436             if isinstance(child, wx.aui.AuiTabCtrl):
       
  1437                 auitabctrl.append(child)
       
  1438                 if child not in self.AuiTabCtrl:
       
  1439                     child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
       
  1440         self.AuiTabCtrl = auitabctrl
       
  1441         if self.TabsOpened.GetPageCount() == 0:
       
  1442             pane = self.AUIManager.GetPane(self.TabsOpened)
       
  1443             if pane.IsMaximized():
       
  1444                 self.AUIManager.RestorePane(pane)
       
  1445             self.AUIManager.Update()
       
  1446     
       
  1447     def EnsureTabVisible(self, tab):
       
  1448         notebook = tab.GetParent()
       
  1449         notebook.SetSelection(notebook.GetPageIndex(tab))
       
  1450     
       
  1451     def OnPouSelectedChanging(self, event):
       
  1452         if not self.Starting:
       
  1453             selected = self.TabsOpened.GetSelection()
       
  1454             if selected >= 0:
       
  1455                 window = self.TabsOpened.GetPage(selected)
       
  1456                 if not window.IsDebugging():
       
  1457                     window.ResetBuffer()
       
  1458         event.Skip()
       
  1459     
       
  1460     def OnPouSelectedChanged(self, event):
       
  1461         if not self.Starting:
       
  1462             selected = self.TabsOpened.GetSelection()
       
  1463             if selected >= 0:
       
  1464                 window = self.TabsOpened.GetPage(selected)
       
  1465                 tagname = window.GetTagName()
       
  1466                 if not window.IsDebugging():
       
  1467                     wx.CallAfter(self.SelectProjectTreeItem, tagname)
       
  1468                     wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname)
       
  1469                     window.RefreshView()
       
  1470                     self.EnsureTabVisible(self.LibraryPanel)
       
  1471                 else:
       
  1472                     instance_path = window.GetInstancePath()
       
  1473                     if tagname == "":
       
  1474                         instance_path = instance_path.rsplit(".", 1)[0]
       
  1475                         tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
       
  1476                     self.EnsureTabVisible(self.DebugVariablePanel)
       
  1477                     wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname, instance_path)
       
  1478             wx.CallAfter(self._Refresh, FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
       
  1479         event.Skip()
       
  1480         
       
  1481     def RefreshEditor(self):
       
  1482         selected = self.TabsOpened.GetSelection()
       
  1483         if selected >= 0:
       
  1484             window = self.TabsOpened.GetPage(selected)
       
  1485             tagname = window.GetTagName()
       
  1486             if not window.IsDebugging():
       
  1487                 self.SelectProjectTreeItem(tagname)
       
  1488                 self.PouInstanceVariablesPanel.SetPouType(tagname)
       
  1489             else:
       
  1490                 instance_path = window.GetInstancePath()
       
  1491                 if tagname == "":
       
  1492                     instance_path = instance_path.rsplit(".", 1)[0]
       
  1493                     tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
       
  1494                 self.PouInstanceVariablesPanel.SetPouType(tagname, instance_path)
       
  1495             for child in self.TabsOpened.GetChildren():
       
  1496                 if isinstance(child, wx.aui.AuiTabCtrl):
       
  1497                     active_page = child.GetActivePage()
       
  1498                     if active_page >= 0:
       
  1499                         window = child.GetWindowFromIdx(active_page)
       
  1500                         window.RefreshView()
       
  1501             self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
       
  1502     
       
  1503     def RefreshEditorNames(self, old_tagname, new_tagname):
       
  1504         for i in xrange(self.TabsOpened.GetPageCount()):
       
  1505             editor = self.TabsOpened.GetPage(i)
       
  1506             if editor.GetTagName() == old_tagname:
       
  1507                 editor.SetTagName(new_tagname)
       
  1508     
       
  1509     def IsOpened(self, tagname):
       
  1510         for idx in xrange(self.TabsOpened.GetPageCount()):
       
  1511             if self.TabsOpened.GetPage(idx).IsViewing(tagname):
       
  1512                 return idx
       
  1513         return None
       
  1514 
       
  1515     def RefreshPageTitles(self):
       
  1516         for idx in xrange(self.TabsOpened.GetPageCount()):
       
  1517             window = self.TabsOpened.GetPage(idx)
       
  1518             icon = window.GetIcon()
       
  1519             if icon is not None:
       
  1520                 self.SetPageBitmap(idx, icon)
       
  1521             self.TabsOpened.SetPageText(idx, window.GetTitle())
       
  1522 
       
  1523     def GetTabsOpenedDClickFunction(self, tabctrl):
       
  1524         def OnTabsOpenedDClick(event):
       
  1525             pos = event.GetPosition()
       
  1526             if tabctrl.TabHitTest(pos.x, pos.y, None):
       
  1527                 pane = self.AUIManager.GetPane(self.TabsOpened)
       
  1528                 if pane.IsMaximized():
       
  1529                     self.AUIManager.RestorePane(pane)
       
  1530                 else:
       
  1531                     self.AUIManager.MaximizePane(pane)
       
  1532                 self.AUIManager.Update()
       
  1533             event.Skip()
       
  1534         return OnTabsOpenedDClick
       
  1535 
       
  1536 #-------------------------------------------------------------------------------
       
  1537 #                         Types Tree Management Functions
       
  1538 #-------------------------------------------------------------------------------
       
  1539 
       
  1540     def RefreshProjectTree(self):
       
  1541         infos = self.Controler.GetProjectInfos()
       
  1542         root = self.ProjectTree.GetRootItem()
       
  1543         if not root.IsOk():
       
  1544             root = self.ProjectTree.AddRoot(infos["name"])
       
  1545         self.GenerateProjectTreeBranch(root, infos)
       
  1546         self.ProjectTree.Expand(root)
       
  1547 
       
  1548     def ResetSelectedItem(self):
       
  1549         self.SelectedItem = None
       
  1550 
       
  1551     def GenerateProjectTreeBranch(self, root, infos):
       
  1552         to_delete = []
       
  1553         item_name = infos["name"]
       
  1554         if infos["type"] in ITEMS_UNEDITABLE:
       
  1555             if len(infos["values"]) == 1:
       
  1556                 return self.GenerateProjectTreeBranch(root, infos["values"][0])
       
  1557             item_name = _(item_name)
       
  1558         self.ProjectTree.SetItemText(root, item_name)
       
  1559         self.ProjectTree.SetPyData(root, infos)
       
  1560         highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.WHITE, wx.BLACK))
       
  1561         self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0])
       
  1562         self.ProjectTree.SetItemTextColour(root, highlight_colours[1])
       
  1563         if infos["type"] == ITEM_POU:
       
  1564             self.ProjectTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
       
  1565         elif infos.has_key("icon") and infos["icon"] is not None:
       
  1566             icon_name = infos["icon"]
       
  1567             if not self.TreeImageDict.has_key(icon_name):
       
  1568                 self.TreeImageDict[icon_name] = self.TreeImageList.Add(GetBitmap(icon_name))
       
  1569             self.ProjectTree.SetItemImage(root, self.TreeImageDict[icon_name])
       
  1570         elif self.TreeImageDict.has_key(infos["type"]):
       
  1571             self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]])      
       
  1572         
       
  1573         if wx.VERSION >= (2, 6, 0):
       
  1574             item, root_cookie = self.ProjectTree.GetFirstChild(root)
       
  1575         else:
       
  1576             item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
       
  1577         for values in infos["values"]:
       
  1578             if values["type"] not in ITEMS_UNEDITABLE or len(values["values"]) > 0:
       
  1579                 if not item.IsOk():
       
  1580                     item = self.ProjectTree.AppendItem(root, "")
       
  1581                     if wx.Platform != '__WXMSW__':
       
  1582                         item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
       
  1583                 self.GenerateProjectTreeBranch(item, values)
       
  1584                 item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
       
  1585         while item.IsOk():
       
  1586             to_delete.append(item)
       
  1587             item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
       
  1588         for item in to_delete:
       
  1589             self.ProjectTree.Delete(item)
       
  1590 
       
  1591     def SelectProjectTreeItem(self, tagname):
       
  1592         if self.ProjectTree is not None:
       
  1593             root = self.ProjectTree.GetRootItem()
       
  1594             if root.IsOk():
       
  1595                 words = tagname.split("::")
       
  1596                 if words[0] == "D":
       
  1597                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_DATATYPE)])
       
  1598                 elif words[0] == "P":
       
  1599                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU)])
       
  1600                 elif words[0] == "T":
       
  1601                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)])
       
  1602                 elif words[0] == "A":
       
  1603                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)])
       
  1604                 elif words[0] == "C":
       
  1605                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)])
       
  1606                 elif words[0] == "R":
       
  1607                     return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)])
       
  1608         return False
       
  1609 
       
  1610     def RecursiveProjectTreeItemSelection(self, root, items):
       
  1611         found = False
       
  1612         if wx.VERSION >= (2, 6, 0):
       
  1613             item, root_cookie = self.ProjectTree.GetFirstChild(root)
       
  1614         else:
       
  1615             item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
       
  1616         while item.IsOk() and not found:
       
  1617             item_infos = self.ProjectTree.GetPyData(item)
       
  1618             if (item_infos["name"].split(":")[-1].strip(), item_infos["type"]) == items[0]:
       
  1619                 if len(items) == 1:
       
  1620                     self.SelectedItem = item
       
  1621                     wx.CallAfter(self.ProjectTree.SelectItem, item)
       
  1622                     wx.CallAfter(self.ResetSelectedItem)
       
  1623                     return True
       
  1624                 else:
       
  1625                     found = self.RecursiveProjectTreeItemSelection(item, items[1:])
       
  1626             else:
       
  1627                 found = self.RecursiveProjectTreeItemSelection(item, items)
       
  1628             item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
       
  1629         return found
       
  1630 
       
  1631     def OnProjectTreeBeginDrag(self, event):
       
  1632         if wx.Platform == '__WXMSW__':
       
  1633             self.SelectedItem = event.GetItem()
       
  1634         if self.SelectedItem is not None and self.ProjectTree.GetPyData(self.SelectedItem)["type"] == ITEM_POU:
       
  1635             block_name = self.ProjectTree.GetItemText(self.SelectedItem)
       
  1636             block_type = self.Controler.GetPouType(block_name)
       
  1637             if block_type != "program":
       
  1638                 data = wx.TextDataObject(str((block_name, block_type, "")))
       
  1639                 dragSource = wx.DropSource(self.ProjectTree)
       
  1640                 dragSource.SetData(data)
       
  1641                 dragSource.DoDragDrop()
       
  1642             self.ResetSelectedItem()
       
  1643 
       
  1644     def OnProjectTreeItemBeginEdit(self, event):
       
  1645         selected = event.GetItem()
       
  1646         if self.ProjectTree.GetPyData(selected)["type"] in ITEMS_UNEDITABLE:
       
  1647             event.Veto()
       
  1648         else:
       
  1649             event.Skip()
       
  1650 
       
  1651     def OnProjectTreeItemEndEdit(self, event):
       
  1652         message = None
       
  1653         abort = False
       
  1654         new_name = event.GetLabel()
       
  1655         if new_name != "":
       
  1656             if not TestIdentifier(new_name):
       
  1657                 message = _("\"%s\" is not a valid identifier!")%new_name
       
  1658             elif new_name.upper() in IEC_KEYWORDS:
       
  1659                 message = _("\"%s\" is a keyword. It can't be used!")%new_name
       
  1660             else:
       
  1661                 item = event.GetItem()
       
  1662                 old_name = self.ProjectTree.GetItemText(item)
       
  1663                 item_infos = self.ProjectTree.GetPyData(item)
       
  1664                 if item_infos["type"] == ITEM_PROJECT:
       
  1665                     self.Controler.SetProjectProperties(name = new_name)
       
  1666                 elif item_infos["type"] == ITEM_DATATYPE:
       
  1667                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]:
       
  1668                         message = _("\"%s\" data type already exists!")%new_name
       
  1669                         abort = True
       
  1670                     if not abort:
       
  1671                         self.Controler.ChangeDataTypeName(old_name, new_name)
       
  1672                         self.RefreshEditorNames(self.Controler.ComputeDataTypeName(old_name), 
       
  1673                                                 self.Controler.ComputeDataTypeName(new_name))
       
  1674                         self.RefreshPageTitles()
       
  1675                 elif item_infos["type"] == ITEM_POU:
       
  1676                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
       
  1677                         message = _("\"%s\" pou already exists!")%new_name
       
  1678                         abort = True
       
  1679                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
       
  1680                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
       
  1681                         if messageDialog.ShowModal() == wx.ID_NO:
       
  1682                             abort = True
       
  1683                         messageDialog.Destroy()
       
  1684                     if not abort:
       
  1685                         self.Controler.ChangePouName(old_name, new_name)
       
  1686                         self.RefreshEditorNames(self.Controler.ComputePouName(old_name), 
       
  1687                                                 self.Controler.ComputePouName(new_name))
       
  1688                         self.RefreshLibraryPanel()
       
  1689                         self.RefreshPageTitles()
       
  1690                 elif item_infos["type"] == ITEM_TRANSITION:
       
  1691                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
       
  1692                         message = _("A POU named \"%s\" already exists!")%new_name
       
  1693                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
       
  1694                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
       
  1695                     else:
       
  1696                         words = item_infos["tagname"].split("::")
       
  1697                         self.Controler.ChangePouTransitionName(words[1], old_name, new_name)
       
  1698                         self.RefreshEditorNames(self.Controler.ComputePouTransitionName(words[1], old_name), 
       
  1699                                                 self.Controler.ComputePouTransitionName(words[1], new_name))
       
  1700                         self.RefreshPageTitles()
       
  1701                 elif item_infos["type"] == ITEM_ACTION:
       
  1702                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
       
  1703                         message = _("A POU named \"%s\" already exists!")%new_name
       
  1704                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
       
  1705                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
       
  1706                     else:
       
  1707                         words = item_infos["tagname"].split("::")
       
  1708                         self.Controler.ChangePouActionName(words[1], old_name, new_name)
       
  1709                         self.RefreshEditorNames(self.Controler.ComputePouActionName(words[1], old_name), 
       
  1710                                                 self.Controler.ComputePouActionName(words[1], new_name))
       
  1711                         self.RefreshPageTitles()
       
  1712                 elif item_infos["type"] == ITEM_CONFIGURATION:
       
  1713                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]:
       
  1714                         message = _("\"%s\" config already exists!")%new_name
       
  1715                         abort = True
       
  1716                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
       
  1717                         messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
       
  1718                         if messageDialog.ShowModal() == wx.ID_NO:
       
  1719                             abort = True
       
  1720                         messageDialog.Destroy()
       
  1721                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
       
  1722                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
       
  1723                         if messageDialog.ShowModal() == wx.ID_NO:
       
  1724                             abort = True
       
  1725                         messageDialog.Destroy()
       
  1726                     if not abort:
       
  1727                         self.Controler.ChangeConfigurationName(old_name, new_name)
       
  1728                         self.RefreshEditorNames(self.Controler.ComputeConfigurationName(old_name), 
       
  1729                                                 self.Controler.ComputeConfigurationName(new_name))
       
  1730                         self.RefreshPageTitles()
       
  1731                 elif item_infos["type"] == ITEM_RESOURCE:
       
  1732                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]:
       
  1733                         message = _("\"%s\" config already exists!")%new_name
       
  1734                         abort = True
       
  1735                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
       
  1736                         messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
       
  1737                         if messageDialog.ShowModal() == wx.ID_NO:
       
  1738                             abort = True
       
  1739                         messageDialog.Destroy()
       
  1740                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
       
  1741                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
       
  1742                         if messageDialog.ShowModal() == wx.ID_NO:
       
  1743                             abort = True
       
  1744                         messageDialog.Destroy()
       
  1745                     if not abort:
       
  1746                         words = item_infos["tagname"].split("::")
       
  1747                         self.Controler.ChangeConfigurationResourceName(words[1], old_name, new_name)
       
  1748                         self.RefreshEditorNames(self.Controler.ComputeConfigurationResourceName(words[1], old_name), 
       
  1749                                                 self.Controler.ComputeConfigurationResourceName(words[1], new_name))
       
  1750                         self.RefreshPageTitles()
       
  1751             if message or abort:
       
  1752                 if message:
       
  1753                     self.ShowErrorMessage(message)
       
  1754                 item = event.GetItem()
       
  1755                 wx.CallAfter(self.ProjectTree.EditLabel, item)
       
  1756                 event.Veto()
       
  1757             else:
       
  1758                 wx.CallAfter(self.RefreshProjectTree)
       
  1759                 self.RefreshEditor()
       
  1760                 self._Refresh(TITLE, FILEMENU, EDITMENU)
       
  1761                 event.Skip()
       
  1762     
       
  1763     def OnProjectTreeItemActivated(self, event):
       
  1764         selected = event.GetItem()
       
  1765         name = self.ProjectTree.GetItemText(selected)
       
  1766         item_infos = self.ProjectTree.GetPyData(selected)
       
  1767         if item_infos["type"] == ITEM_PROJECT:
       
  1768             self.EditProjectSettings()
       
  1769         else:
       
  1770             if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
       
  1771                                     ITEM_CONFIGURATION, ITEM_RESOURCE,
       
  1772                                     ITEM_TRANSITION, ITEM_ACTION]:
       
  1773                 self.EditProjectElement(item_infos["type"], item_infos["tagname"])
       
  1774             event.Skip()
       
  1775     
       
  1776     def ProjectTreeItemSelect(self, select_item):
       
  1777         name = self.ProjectTree.GetItemText(select_item)
       
  1778         item_infos = self.ProjectTree.GetPyData(select_item)
       
  1779         if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
       
  1780                                   ITEM_CONFIGURATION, ITEM_RESOURCE,
       
  1781                                   ITEM_TRANSITION, ITEM_ACTION]:
       
  1782             self.EditProjectElement(item_infos["type"], item_infos["tagname"], True)
       
  1783             self.PouInstanceVariablesPanel.SetPouType(item_infos["tagname"])
       
  1784         
       
  1785     def OnProjectTreeLeftUp(self, event):
       
  1786         if self.SelectedItem is not None:
       
  1787             self.ProjectTree.SelectItem(self.SelectedItem)
       
  1788             self.ProjectTreeItemSelect(self.SelectedItem)
       
  1789             wx.CallAfter(self.ResetSelectedItem)
       
  1790         event.Skip()
       
  1791     
       
  1792     def OnProjectTreeItemSelected(self, event):
       
  1793         self.ProjectTreeItemSelect(event.GetItem())
       
  1794         event.Skip()
       
  1795     
       
  1796     def OnProjectTreeItemChanging(self, event):
       
  1797         if self.ProjectTree.GetPyData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
       
  1798             self.SelectedItem = event.GetItem()
       
  1799             event.Veto()
       
  1800         else:
       
  1801             event.Skip()
       
  1802     
       
  1803     def EditProjectElement(self, element, tagname, onlyopened = False):
       
  1804         openedidx = self.IsOpened(tagname)
       
  1805         if openedidx is not None:
       
  1806             old_selected = self.TabsOpened.GetSelection()
       
  1807             if old_selected != openedidx:
       
  1808                 if old_selected >= 0:
       
  1809                     self.TabsOpened.GetPage(old_selected).ResetBuffer()
       
  1810                 self.TabsOpened.SetSelection(openedidx)
       
  1811             self._Refresh(FILEMENU, EDITMENU, EDITORTOOLBAR, PAGETITLES)
       
  1812         elif not onlyopened:
       
  1813             if isinstance(element, EditorPanel):
       
  1814                 new_window = element
       
  1815                 self.AddPage(element, "")
       
  1816             elif self.Controler.GetEditedElement(tagname) is not None:
       
  1817                 new_window = None
       
  1818                 if element == ITEM_CONFIGURATION:
       
  1819                     new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
       
  1820                     new_window.SetIcon(GetBitmap("CONFIGURATION"))
       
  1821                     self.AddPage(new_window, "")
       
  1822                 elif element == ITEM_RESOURCE:
       
  1823                     new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
       
  1824                     new_window.SetIcon(GetBitmap("RESOURCE"))
       
  1825                     self.AddPage(new_window, "")
       
  1826                 elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
       
  1827                     bodytype = self.Controler.GetEditedElementBodyType(tagname)
       
  1828                     if bodytype == "FBD":
       
  1829                         new_window = Viewer(self.TabsOpened, tagname, self, self.Controler)
       
  1830                         new_window.RefreshScaling(False)
       
  1831                     elif bodytype == "LD":
       
  1832                         new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler)
       
  1833                         new_window.RefreshScaling(False)
       
  1834                     elif bodytype == "SFC":
       
  1835                         new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler)
       
  1836                         new_window.RefreshScaling(False)
       
  1837                     else:
       
  1838                         new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler)
       
  1839                         new_window.SetTextSyntax(bodytype)
       
  1840                         if bodytype == "IL":
       
  1841                             new_window.SetKeywords(IL_KEYWORDS)
       
  1842                         else:
       
  1843                             new_window.SetKeywords(ST_KEYWORDS)
       
  1844                     if element == ITEM_POU:
       
  1845                         pou_type = self.Controler.GetEditedElementType(tagname)[1].upper()
       
  1846                         icon = GetBitmap(pou_type, bodytype)
       
  1847                     elif element == ITEM_TRANSITION:
       
  1848                         icon = GetBitmap("TRANSITION", bodytype)
       
  1849                     elif element == ITEM_ACTION:
       
  1850                         icon = GetBitmap("ACTION", bodytype)
       
  1851                     new_window.SetIcon(icon)
       
  1852                     self.AddPage(new_window, "")
       
  1853                 elif element == ITEM_DATATYPE:
       
  1854                     new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
       
  1855                     new_window.SetIcon(GetBitmap("DATATYPE"))
       
  1856                     self.AddPage(new_window, "")
       
  1857             if new_window is not None:
       
  1858                 project_infos = self.GetProjectConfiguration()
       
  1859                 if project_infos.has_key("editors_state"):
       
  1860                     if new_window.IsDebugging():
       
  1861                         state = project_infos["editors_state"].get(new_window.GetInstancePath())
       
  1862                     else:
       
  1863                         state = project_infos["editors_state"].get(tagname)
       
  1864                     if state is not None:
       
  1865                         wx.CallAfter(new_window.SetState, state)
       
  1866                 
       
  1867                 openedidx = self.IsOpened(tagname)
       
  1868                 old_selected = self.TabsOpened.GetSelection()
       
  1869                 if old_selected != openedidx:
       
  1870                     if old_selected >= 0:
       
  1871                         self.TabsOpened.GetPage(old_selected).ResetBuffer()
       
  1872                 for i in xrange(self.TabsOpened.GetPageCount()):
       
  1873                     window = self.TabsOpened.GetPage(i)
       
  1874                     if window == new_window:
       
  1875                         self.TabsOpened.SetSelection(i)
       
  1876                         window.SetFocus()
       
  1877                 self.RefreshPageTitles()
       
  1878             return new_window
       
  1879     
       
  1880     def OnProjectTreeRightUp(self, event):
       
  1881         if wx.Platform == '__WXMSW__':
       
  1882             item = event.GetItem()
       
  1883         else:
       
  1884             item, flags = self.ProjectTree.HitTest(wx.Point(event.GetX(), event.GetY()))
       
  1885         self.ProjectTree.SelectItem(item)
       
  1886         self.ProjectTreeItemSelect(item)
       
  1887         name = self.ProjectTree.GetItemText(item)
       
  1888         item_infos = self.ProjectTree.GetPyData(item)
       
  1889         
       
  1890         menu = None
       
  1891         if item_infos["type"] in ITEMS_UNEDITABLE + [ITEM_PROJECT]:
       
  1892             if item_infos["type"] == ITEM_PROJECT:
       
  1893                 name = "Project"
       
  1894             else:
       
  1895                 name = UNEDITABLE_NAMES_DICT[name]
       
  1896             
       
  1897             if name == "Data Types":
       
  1898                 menu = wx.Menu(title='')
       
  1899                 new_id = wx.NewId()
       
  1900                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType"))
       
  1901                 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id)
       
  1902             
       
  1903             elif name in ["Functions", "Function Blocks", "Programs", "Project"]:
       
  1904                 menu = wx.Menu(title='')
       
  1905                 
       
  1906                 if name != "Project":
       
  1907                     new_id = wx.NewId()
       
  1908                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add POU"))
       
  1909                     self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id)
       
  1910 
       
  1911                 new_id = wx.NewId()
       
  1912                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Paste POU"))
       
  1913                 self.Bind(wx.EVT_MENU, self.OnPastePou, id=new_id)
       
  1914                 if self.GetCopyBuffer() is None:
       
  1915                     menu.Enable(new_id, False)
       
  1916 
       
  1917             elif name == "Configurations":
       
  1918                 menu = wx.Menu(title='')
       
  1919                 new_id = wx.NewId()
       
  1920                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration"))
       
  1921                 self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, id=new_id)
       
  1922             
       
  1923             elif name == "Transitions":
       
  1924                 menu = wx.Menu(title='')
       
  1925                 new_id = wx.NewId()
       
  1926                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition"))
       
  1927                 parent = self.ProjectTree.GetItemParent(item)["type"]
       
  1928                 parent_type = self.ProjectTree.GetPyData(parent)
       
  1929                 while parent_type != ITEM_POU:
       
  1930                     parent = self.ProjectTree.GetItemParent(parent)
       
  1931                     parent_type = self.ProjectTree.GetPyData(parent)["type"]
       
  1932                 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.ProjectTree.GetItemText(parent)), id=new_id)
       
  1933             
       
  1934             elif name == "Actions":
       
  1935                 menu = wx.Menu(title='')
       
  1936                 new_id = wx.NewId()
       
  1937                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
       
  1938                 parent = self.ProjectTree.GetItemParent(item)
       
  1939                 parent_type = self.ProjectTree.GetPyData(parent)["type"]
       
  1940                 while parent_type != ITEM_POU:
       
  1941                     parent = self.ProjectTree.GetItemParent(parent)
       
  1942                     parent_type = self.ProjectTree.GetPyData(parent)["type"]
       
  1943                 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.ProjectTree.GetItemText(parent)), id=new_id)
       
  1944             
       
  1945             elif name == "Resources":
       
  1946                 menu = wx.Menu(title='')
       
  1947                 new_id = wx.NewId()
       
  1948                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource"))
       
  1949                 parent = self.ProjectTree.GetItemParent(item)
       
  1950                 parent_type = self.ProjectTree.GetPyData(parent)["type"]
       
  1951                 while parent_type not in [ITEM_CONFIGURATION, ITEM_PROJECT]:
       
  1952                     parent = self.ProjectTree.GetItemParent(parent)
       
  1953                     parent_type = self.ProjectTree.GetPyData(parent)["type"]
       
  1954                 if parent_type == ITEM_PROJECT:
       
  1955                     parent_name = None
       
  1956                 else:
       
  1957                     parent_name = self.ProjectTree.GetItemText(parent)
       
  1958                 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(parent_name), id=new_id)
       
  1959             
       
  1960         else:
       
  1961             if item_infos["type"] == ITEM_POU:
       
  1962                 menu = wx.Menu(title='')
       
  1963                 if self.Controler.GetPouBodyType(name) == "SFC":
       
  1964                     new_id = wx.NewId()
       
  1965                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition"))
       
  1966                     self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id)
       
  1967                     new_id = wx.NewId()
       
  1968                     AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
       
  1969                     self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id)
       
  1970                     menu.AppendSeparator()
       
  1971     
       
  1972                 new_id = wx.NewId()
       
  1973                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Copy POU"))
       
  1974                 self.Bind(wx.EVT_MENU, self.OnCopyPou, id=new_id)
       
  1975     
       
  1976                 pou_type = self.Controler.GetPouType(name)
       
  1977                 if pou_type in ["function", "functionBlock"]:
       
  1978                     change_menu = wx.Menu(title='')
       
  1979                     if pou_type == "function":
       
  1980                         new_id = wx.NewId()
       
  1981                         AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Function Block"))
       
  1982                         self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "functionBlock"), id=new_id)
       
  1983                     new_id = wx.NewId()
       
  1984                     AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Program"))
       
  1985                     self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "program"), id=new_id)
       
  1986                     menu.AppendMenu(wx.NewId(), _("Change POU Type To"), change_menu)
       
  1987                 new_id = wx.NewId()
       
  1988                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Rename"))
       
  1989                 self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id)
       
  1990             
       
  1991             elif item_infos["type"] == ITEM_CONFIGURATION:
       
  1992                 menu = wx.Menu(title='')
       
  1993                 new_id = wx.NewId()
       
  1994                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource"))
       
  1995                 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), id=new_id)
       
  1996             
       
  1997             elif item_infos["type"] in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
       
  1998                 menu = wx.Menu(title='')
       
  1999                 
       
  2000             if menu is not None:
       
  2001                 new_id = wx.NewId()
       
  2002                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete"))
       
  2003                 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id)
       
  2004         
       
  2005         if menu is not None:
       
  2006             self.PopupMenu(menu)
       
  2007             menu.Destroy()
       
  2008         
       
  2009         event.Skip()
       
  2010 
       
  2011 
       
  2012 #-------------------------------------------------------------------------------
       
  2013 #                         Instances Tree Management Functions
       
  2014 #-------------------------------------------------------------------------------
       
  2015 
       
  2016     def GetTreeImage(self, var_class):
       
  2017         return self.TreeImageDict[var_class]
       
  2018     
       
  2019     def RefreshPouInstanceVariablesPanel(self):
       
  2020         self.PouInstanceVariablesPanel.RefreshView()
       
  2021 
       
  2022     def OpenDebugViewer(self, instance_category, instance_path, instance_type):
       
  2023         openedidx = self.IsOpened(instance_path)
       
  2024         new_window = None
       
  2025         if openedidx is not None:
       
  2026             old_selected = self.TabsOpened.GetSelection()
       
  2027             if old_selected != openedidx:
       
  2028                 if old_selected >= 0:
       
  2029                     self.TabsOpened.GetPage(old_selected).ResetBuffer()
       
  2030                 self.TabsOpened.SetSelection(openedidx)
       
  2031         
       
  2032         elif instance_category in ITEMS_VARIABLE:
       
  2033             if self.Controler.IsNumType(instance_type, True):
       
  2034                 if USE_MPL:
       
  2035                     self.AddDebugVariable(instance_path, True)
       
  2036                 else:
       
  2037                     new_window = GraphicViewer(self.TabsOpened, self, self.Controler, instance_path)
       
  2038                     icon = GetBitmap("GRAPH")
       
  2039         
       
  2040         else:
       
  2041             bodytype = self.Controler.GetEditedElementBodyType(instance_type, True)
       
  2042             if bodytype == "FBD":
       
  2043                 new_window = Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
       
  2044                 new_window.RefreshScaling(False)
       
  2045             elif bodytype == "LD":
       
  2046                 new_window = LD_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
       
  2047                 new_window.RefreshScaling(False)
       
  2048             elif bodytype == "SFC":
       
  2049                 new_window = SFC_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
       
  2050                 new_window.RefreshScaling(False)
       
  2051             else:
       
  2052                 new_window = TextViewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
       
  2053                 new_window.SetTextSyntax(bodytype)
       
  2054                 if bodytype == "IL":
       
  2055                     new_window.SetKeywords(IL_KEYWORDS)
       
  2056                 else:
       
  2057                     new_window.SetKeywords(ST_KEYWORDS)
       
  2058             
       
  2059             if new_window is not None:
       
  2060                 if instance_category in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM]:
       
  2061                     pou_type = self.Controler.GetEditedElementType(instance_type, True)[1].upper()
       
  2062                     icon = GetBitmap(pou_type, bodytype)
       
  2063                 elif instance_category == ITEM_TRANSITION:
       
  2064                     icon = GetBitmap("TRANSITION", bodytype)
       
  2065                 elif instance_category == ITEM_ACTION:
       
  2066                     icon = GetBitmap("ACTION", bodytype)
       
  2067         
       
  2068         if new_window is not None:
       
  2069             project_infos = self.GetProjectConfiguration()
       
  2070             if project_infos.has_key("editors_state"):
       
  2071                 state = project_infos["editors_state"].get(instance_path)
       
  2072                 if state is not None:
       
  2073                     wx.CallAfter(new_window.SetState, state)
       
  2074             
       
  2075             new_window.SetIcon(icon)
       
  2076             self.AddPage(new_window, "")
       
  2077             new_window.RefreshView()
       
  2078             new_window.SetFocus()
       
  2079             self.RefreshPageTitles()
       
  2080         return new_window
       
  2081 
       
  2082     def ResetGraphicViewers(self):
       
  2083         if self.EnableDebug:
       
  2084             for i in xrange(self.TabsOpened.GetPageCount()):
       
  2085                 editor = self.TabsOpened.GetPage(i)
       
  2086                 if isinstance(editor, GraphicViewer):
       
  2087                     editor.ResetView()
       
  2088             self.DebugVariablePanel.ResetGraphicsValues()
       
  2089 
       
  2090     def CloseObsoleteDebugTabs(self):
       
  2091         if self.EnableDebug:
       
  2092             idxs = range(self.TabsOpened.GetPageCount())
       
  2093             idxs.reverse()
       
  2094             for idx in idxs:
       
  2095                 editor = self.TabsOpened.GetPage(idx)
       
  2096                 if isinstance(editor, (Viewer, GraphicViewer)) and editor.IsDebugging():
       
  2097                     instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath(), self.EnableDebug)
       
  2098                     if instance_infos is None:
       
  2099                         self.TabsOpened.DeletePage(idx)
       
  2100                     elif isinstance(editor, GraphicViewer):
       
  2101                         editor.ResetView(True)
       
  2102                     else:
       
  2103                         editor.RefreshView()
       
  2104                 elif editor.IsDebugging():
       
  2105                     editor.RegisterVariables()
       
  2106             self.DebugVariablePanel.UnregisterObsoleteData()
       
  2107     
       
  2108     def AddDebugVariable(self, iec_path, force=False):
       
  2109         if self.EnableDebug:
       
  2110             self.DebugVariablePanel.InsertValue(iec_path, force=force)
       
  2111             self.EnsureTabVisible(self.DebugVariablePanel)
       
  2112             
       
  2113 #-------------------------------------------------------------------------------
       
  2114 #                         Library Panel Management Function
       
  2115 #-------------------------------------------------------------------------------
       
  2116 
       
  2117     def RefreshLibraryPanel(self):
       
  2118         self.LibraryPanel.RefreshTree()
       
  2119         
       
  2120 #-------------------------------------------------------------------------------
       
  2121 #                          ToolBars Management Functions
       
  2122 #-------------------------------------------------------------------------------
       
  2123 
       
  2124     def AddToMenuToolBar(self, items):
       
  2125         MenuToolBar = self.Panes["MenuToolBar"]
       
  2126         if MenuToolBar.GetToolsCount() > 0:
       
  2127             MenuToolBar.AddSeparator()
       
  2128         for toolbar_item in items:
       
  2129             if toolbar_item is None:
       
  2130                 MenuToolBar.AddSeparator()
       
  2131             else:
       
  2132                 id, bitmap, help, callback = toolbar_item
       
  2133                 MenuToolBar.AddSimpleTool(id=id, shortHelpString=help, bitmap=GetBitmap(bitmap))
       
  2134                 if callback is not None:
       
  2135                     self.Bind(wx.EVT_TOOL, callback, id=id)
       
  2136         MenuToolBar.Realize()
       
  2137         self.AUIManager.GetPane("MenuToolBar").BestSize(MenuToolBar.GetBestSize())
       
  2138 
       
  2139     def ResetEditorToolBar(self):
       
  2140         EditorToolBar = self.Panes["EditorToolBar"]
       
  2141         
       
  2142         for item in self.CurrentEditorToolBar:
       
  2143             if wx.VERSION >= (2, 6, 0):
       
  2144                 self.Unbind(wx.EVT_MENU, id=item)
       
  2145             else:
       
  2146                 self.Disconnect(id=item, eventType=wx.wxEVT_COMMAND_MENU_SELECTED) 
       
  2147         
       
  2148             if EditorToolBar:
       
  2149                 EditorToolBar.DeleteTool(item)
       
  2150         
       
  2151         if EditorToolBar:
       
  2152             EditorToolBar.Realize()
       
  2153             self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
       
  2154             self.AUIManager.GetPane("EditorToolBar").Hide()
       
  2155             self.AUIManager.Update()
       
  2156 
       
  2157     def RefreshEditorToolBar(self):
       
  2158         selected = self.TabsOpened.GetSelection()
       
  2159         menu = None
       
  2160         if selected != -1:
       
  2161             window = self.TabsOpened.GetPage(selected)
       
  2162             if isinstance(window, (Viewer, TextViewer, GraphicViewer)):
       
  2163                 if not window.IsDebugging():
       
  2164                     menu = self.Controler.GetEditedElementBodyType(window.GetTagName())
       
  2165                 else:
       
  2166                     menu = "debug"
       
  2167         if menu is not None and menu != self.CurrentMenu:
       
  2168             self.ResetEditorToolBar()
       
  2169             self.CurrentMenu = menu
       
  2170             self.CurrentEditorToolBar = []
       
  2171             EditorToolBar = self.Panes["EditorToolBar"]
       
  2172             if EditorToolBar:
       
  2173                 for radio, modes, id, method, picture, help in EditorToolBarItems[menu]:
       
  2174                     if modes & self.DrawingMode:
       
  2175                         if radio or self.DrawingMode == FREEDRAWING_MODE:
       
  2176                             EditorToolBar.AddRadioTool(id, GetBitmap(picture), wx.NullBitmap, help)
       
  2177                         else:
       
  2178                             EditorToolBar.AddSimpleTool(id, GetBitmap(picture), help)
       
  2179                         self.Bind(wx.EVT_MENU, getattr(self, method), id=id)
       
  2180                         self.CurrentEditorToolBar.append(id)
       
  2181                 EditorToolBar.Realize()
       
  2182                 self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
       
  2183                 self.AUIManager.GetPane("EditorToolBar").Show()
       
  2184                 self.AUIManager.Update()
       
  2185         elif menu is None:
       
  2186             self.ResetEditorToolBar()
       
  2187             self.CurrentMenu = menu
       
  2188         self.ResetCurrentMode()
       
  2189 
       
  2190 
       
  2191 #-------------------------------------------------------------------------------
       
  2192 #                           EditorToolBar Items Functions
       
  2193 #-------------------------------------------------------------------------------
       
  2194 
       
  2195     def ResetCurrentMode(self):
       
  2196         selected = self.TabsOpened.GetSelection()
       
  2197         if selected != -1:
       
  2198             window = self.TabsOpened.GetPage(selected)
       
  2199             window.SetMode(MODE_SELECTION)
       
  2200         EditorToolBar = self.Panes["EditorToolBar"]
       
  2201         if EditorToolBar:
       
  2202             EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, False)
       
  2203             EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, True)
       
  2204         
       
  2205     def ResetToolToggle(self, id):
       
  2206         tool = self.Panes["EditorToolBar"].FindById(id)
       
  2207         tool.SetToggle(False)
       
  2208 
       
  2209     def OnSelectionTool(self, event):
       
  2210         selected = self.TabsOpened.GetSelection()
       
  2211         if selected != -1:
       
  2212             self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION)
       
  2213     
       
  2214     def OnMotionTool(self, event):
       
  2215         selected = self.TabsOpened.GetSelection()
       
  2216         if selected != -1:
       
  2217             self.TabsOpened.GetPage(selected).SetMode(MODE_MOTION)
       
  2218     
       
  2219     def OnCommentTool(self, event):
       
  2220         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOMMENT)
       
  2221         selected = self.TabsOpened.GetSelection()
       
  2222         if selected != -1:
       
  2223             self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT)
       
  2224     
       
  2225     def OnVariableTool(self, event):
       
  2226         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARVARIABLE)
       
  2227         selected = self.TabsOpened.GetSelection()
       
  2228         if selected != -1:
       
  2229             self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE)
       
  2230     
       
  2231     def OnBlockTool(self, event):
       
  2232         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARBLOCK)
       
  2233         selected = self.TabsOpened.GetSelection()
       
  2234         if selected != -1:
       
  2235             self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK)
       
  2236         
       
  2237     def OnConnectionTool(self, event):
       
  2238         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONNECTION)
       
  2239         selected = self.TabsOpened.GetSelection()
       
  2240         if selected != -1:
       
  2241             self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION)
       
  2242     
       
  2243     def OnPowerRailTool(self, event):
       
  2244         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL)
       
  2245         selected = self.TabsOpened.GetSelection()
       
  2246         if selected != -1:
       
  2247             self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL)
       
  2248     
       
  2249     def OnRungTool(self, event):
       
  2250         selected = self.TabsOpened.GetSelection()
       
  2251         if selected != -1:
       
  2252             self.TabsOpened.GetPage(selected).AddLadderRung()
       
  2253         event.Skip()
       
  2254     
       
  2255     def OnCoilTool(self, event):
       
  2256         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOIL)
       
  2257         selected = self.TabsOpened.GetSelection()
       
  2258         if selected != -1:
       
  2259             self.TabsOpened.GetPage(selected).SetMode(MODE_COIL)
       
  2260         event.Skip()
       
  2261     
       
  2262     def OnContactTool(self, event):
       
  2263         if self.DrawingMode == FREEDRAWING_MODE:
       
  2264             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONTACT)
       
  2265         selected = self.TabsOpened.GetSelection()
       
  2266         if selected != -1:
       
  2267             if self.DrawingMode == FREEDRAWING_MODE:
       
  2268                 self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT)
       
  2269             else:
       
  2270                 self.TabsOpened.GetPage(selected).AddLadderContact()
       
  2271     
       
  2272     def OnBranchTool(self, event): 
       
  2273         selected = self.TabsOpened.GetSelection()
       
  2274         if selected != -1:
       
  2275             self.TabsOpened.GetPage(selected).AddLadderBranch()
       
  2276     
       
  2277     def OnInitialStepTool(self, event):
       
  2278         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP)
       
  2279         selected = self.TabsOpened.GetSelection()
       
  2280         if selected != -1:
       
  2281             self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP)
       
  2282     
       
  2283     def OnStepTool(self, event):
       
  2284         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2285             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARSTEP)
       
  2286         selected = self.TabsOpened.GetSelection()
       
  2287         if selected != -1:
       
  2288             if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2289                 self.TabsOpened.GetPage(selected).SetMode(MODE_STEP)
       
  2290             else:
       
  2291                 self.TabsOpened.GetPage(selected).AddStep()
       
  2292     
       
  2293     def OnActionBlockTool(self, event):
       
  2294         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2295             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK)
       
  2296         selected = self.TabsOpened.GetSelection()
       
  2297         if selected != -1:
       
  2298             if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2299                 self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION)
       
  2300             else:
       
  2301                 self.TabsOpened.GetPage(selected).AddStepAction()
       
  2302     
       
  2303     def OnTransitionTool(self, event):
       
  2304         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARTRANSITION)
       
  2305         selected = self.TabsOpened.GetSelection()
       
  2306         if selected != -1:
       
  2307             self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION)
       
  2308     
       
  2309     def OnDivergenceTool(self, event):
       
  2310         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2311             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE)
       
  2312         selected = self.TabsOpened.GetSelection()
       
  2313         if selected != -1:
       
  2314             if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2315                 self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE)
       
  2316             else:
       
  2317                 self.TabsOpened.GetPage(selected).AddDivergence()
       
  2318     
       
  2319     def OnJumpTool(self, event):
       
  2320         if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2321             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARJUMP)
       
  2322         selected = self.TabsOpened.GetSelection()
       
  2323         if selected != -1:
       
  2324             if self.GetDrawingMode() == FREEDRAWING_MODE:
       
  2325                 self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP)
       
  2326             else:
       
  2327                 self.TabsOpened.GetPage(selected).AddJump()
       
  2328     
       
  2329 
       
  2330 #-------------------------------------------------------------------------------
       
  2331 #                         Add Project Elements Functions
       
  2332 #-------------------------------------------------------------------------------
       
  2333 
       
  2334     def OnAddDataTypeMenu(self, event):
       
  2335         tagname = self.Controler.ProjectAddDataType()
       
  2336         if tagname is not None:
       
  2337             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
       
  2338             self.EditProjectElement(ITEM_DATATYPE, tagname)
       
  2339         
       
  2340     def GenerateAddPouFunction(self, pou_type):
       
  2341         def OnAddPouMenu(event):
       
  2342             dialog = PouDialog(self, pou_type)
       
  2343             dialog.SetPouNames(self.Controler.GetProjectPouNames())
       
  2344             dialog.SetPouElementNames(self.Controler.GetProjectPouVariables())
       
  2345             dialog.SetValues({"pouName": self.Controler.GenerateNewName(None, None, "%s%%d" % pou_type)})
       
  2346             if dialog.ShowModal() == wx.ID_OK:
       
  2347                 values = dialog.GetValues()
       
  2348                 tagname = self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"])
       
  2349                 if tagname is not None:
       
  2350                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
       
  2351                     self.EditProjectElement(ITEM_POU, tagname)
       
  2352             dialog.Destroy()
       
  2353         return OnAddPouMenu
       
  2354 
       
  2355     def GenerateAddTransitionFunction(self, pou_name):
       
  2356         def OnAddTransitionMenu(event):
       
  2357             dialog = PouTransitionDialog(self)
       
  2358             dialog.SetPouNames(self.Controler.GetProjectPouNames())
       
  2359             dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
       
  2360             dialog.SetValues({"transitionName": self.Controler.GenerateNewName(None, None, "transition%d")})
       
  2361             if dialog.ShowModal() == wx.ID_OK: 
       
  2362                 values = dialog.GetValues()
       
  2363                 tagname = self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"])
       
  2364                 if tagname is not None:
       
  2365                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
       
  2366                     self.EditProjectElement(ITEM_TRANSITION, tagname)
       
  2367             dialog.Destroy()
       
  2368         return OnAddTransitionMenu
       
  2369 
       
  2370     def GenerateAddActionFunction(self, pou_name):
       
  2371         def OnAddActionMenu(event):
       
  2372             dialog = PouActionDialog(self)
       
  2373             dialog.SetPouNames(self.Controler.GetProjectPouNames())
       
  2374             dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
       
  2375             dialog.SetValues({"actionName": self.Controler.GenerateNewName(None, None, "action%d")})
       
  2376             if dialog.ShowModal() == wx.ID_OK:
       
  2377                 values = dialog.GetValues()
       
  2378                 tagname = self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"])
       
  2379                 if tagname is not None:
       
  2380                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
       
  2381                     self.EditProjectElement(ITEM_ACTION, tagname)
       
  2382             dialog.Destroy()
       
  2383         return OnAddActionMenu
       
  2384 
       
  2385     def OnAddConfigurationMenu(self, event):
       
  2386         tagname = self.Controler.ProjectAddConfiguration()
       
  2387         if tagname is not None:
       
  2388             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
       
  2389             self.EditProjectElement(ITEM_CONFIGURATION, tagname)
       
  2390         dialog.Destroy()
       
  2391 
       
  2392     def GenerateAddResourceFunction(self, config_name):
       
  2393         def OnAddResourceMenu(event):
       
  2394             tagname = self.Controler.ProjectAddConfigurationResource(config_name)
       
  2395             if tagname is not None:
       
  2396                 self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
       
  2397                 self.EditProjectElement(ITEM_RESOURCE, tagname)
       
  2398         return OnAddResourceMenu
       
  2399 
       
  2400     def GenerateChangePouTypeFunction(self, name, new_type):
       
  2401         def OnChangePouTypeMenu(event):
       
  2402             selected = self.ProjectTree.GetSelection()
       
  2403             if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU: 
       
  2404                 self.Controler.ProjectChangePouType(name, new_type)
       
  2405                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
       
  2406         return OnChangePouTypeMenu
       
  2407 
       
  2408     def OnCopyPou(self, event):
       
  2409         selected = self.ProjectTree.GetSelection()
       
  2410         pou_name = self.ProjectTree.GetItemText(selected)
       
  2411         
       
  2412         pou_xml = self.Controler.GetPouXml(pou_name)
       
  2413         if pou_xml is not None:
       
  2414             self.SetCopyBuffer(pou_xml)
       
  2415             self._Refresh(EDITMENU)
       
  2416 
       
  2417     def OnPastePou(self, event):
       
  2418         selected = self.ProjectTree.GetSelection()
       
  2419         
       
  2420         if self.ProjectTree.GetPyData(selected)["type"] != ITEM_PROJECT: 
       
  2421             pou_type = self.ProjectTree.GetItemText(selected)
       
  2422             pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs'
       
  2423             pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type]
       
  2424         else:
       
  2425             pou_type = None
       
  2426         
       
  2427         pou_xml = self.GetCopyBuffer()
       
  2428 
       
  2429         result = self.Controler.PastePou(pou_type, pou_xml)
       
  2430 
       
  2431         if not isinstance(result, TupleType):
       
  2432             message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
       
  2433             message.ShowModal()
       
  2434             message.Destroy()
       
  2435         else:
       
  2436             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
       
  2437             self.EditProjectElement(ITEM_POU, result[0])
       
  2438 
       
  2439 #-------------------------------------------------------------------------------
       
  2440 #                        Remove Project Elements Functions
       
  2441 #-------------------------------------------------------------------------------
       
  2442 
       
  2443     def OnRemoveDataTypeMenu(self, event):
       
  2444         selected = self.ProjectTree.GetSelection()
       
  2445         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_DATATYPE:
       
  2446             name = self.ProjectTree.GetItemText(selected)
       
  2447             if not self.Controler.DataTypeIsUsed(name):
       
  2448                 self.Controler.ProjectRemoveDataType(name)
       
  2449                 tagname = self.Controler.ComputeDataTypeName(name)
       
  2450                 idx = self.IsOpened(tagname)
       
  2451                 if idx is not None:
       
  2452                     self.TabsOpened.DeletePage(idx)
       
  2453                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE)
       
  2454             else:
       
  2455                 self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!"))
       
  2456 
       
  2457     def OnRenamePouMenu(self, event):
       
  2458         selected = self.ProjectTree.GetSelection()
       
  2459         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU: 
       
  2460             wx.CallAfter(self.ProjectTree.EditLabel, selected)
       
  2461 
       
  2462     def OnRemovePouMenu(self, event):
       
  2463         selected = self.ProjectTree.GetSelection()
       
  2464         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU:
       
  2465             name = self.ProjectTree.GetItemText(selected)
       
  2466             if not self.Controler.PouIsUsed(name):
       
  2467                 self.Controler.ProjectRemovePou(name)
       
  2468                 tagname = self.Controler.ComputePouName(name)
       
  2469                 idx = self.IsOpened(tagname)
       
  2470                 if idx is not None:
       
  2471                     self.TabsOpened.DeletePage(idx)
       
  2472                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
       
  2473             else:
       
  2474                 self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!"))
       
  2475 
       
  2476     def OnRemoveTransitionMenu(self, event):
       
  2477         selected = self.ProjectTree.GetSelection()
       
  2478         item_infos = self.ProjectTree.GetPyData(selected)
       
  2479         if item_infos["type"] == ITEM_TRANSITION: 
       
  2480             transition = self.ProjectTree.GetItemText(selected)
       
  2481             pou_name = item_infos["tagname"].split("::")[1]
       
  2482             self.Controler.ProjectRemovePouTransition(pou_name, transition)
       
  2483             tagname = self.Controler.ComputePouTransitionName(pou_name, transition)
       
  2484             idx = self.IsOpened(tagname)
       
  2485             if idx is not None:
       
  2486                 self.TabsOpened.DeletePage(idx)
       
  2487             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
       
  2488 
       
  2489     def OnRemoveActionMenu(self, event):
       
  2490         selected = self.ProjectTree.GetSelection()
       
  2491         item_infos = self.ProjectTree.GetPyData(selected)
       
  2492         if item_infos["type"] == ITEM_ACTION: 
       
  2493             action = self.ProjectTree.GetItemText(selected)
       
  2494             pou_name = item_infos["tagname"].split("::")[1]
       
  2495             self.Controler.ProjectRemovePouAction(pou_name, action)
       
  2496             tagname = self.Controler.ComputePouActionName(pou_name, action)
       
  2497             idx = self.IsOpened(tagname)
       
  2498             if idx is not None:
       
  2499                 self.TabsOpened.DeletePage(idx)
       
  2500             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
       
  2501 
       
  2502     def OnRemoveConfigurationMenu(self, event):
       
  2503         selected = self.ProjectTree.GetSelection()
       
  2504         if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFIGURATION: 
       
  2505             name = self.ProjectTree.GetItemText(selected)
       
  2506             self.Controler.ProjectRemoveConfiguration(name)
       
  2507             tagname = self.Controler.ComputeConfigurationName(name)
       
  2508             idx = self.IsOpened(tagname)
       
  2509             if idx is not None:
       
  2510                 self.TabsOpened.DeletePage(idx)
       
  2511             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
       
  2512 
       
  2513     def OnRemoveResourceMenu(self, event):
       
  2514         selected = self.ProjectTree.GetSelection()
       
  2515         item_infos = self.ProjectTree.GetPyData(selected)
       
  2516         if item_infos["type"] == ITEM_RESOURCE:
       
  2517             resource = self.ProjectTree.GetItemText(selected)
       
  2518             config_name = item_infos["tagname"].split("::")[1]
       
  2519             self.Controler.ProjectRemoveConfigurationResource(config_name, resource)
       
  2520             tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected)
       
  2521             idx = self.IsOpened(tagname)
       
  2522             if idx is not None:
       
  2523                 self.TabsOpened.DeletePage(idx)
       
  2524             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
       
  2525 
       
  2526 #-------------------------------------------------------------------------------
       
  2527 #                        Highlights showing functions
       
  2528 #-------------------------------------------------------------------------------
       
  2529 
       
  2530     def ShowHighlight(self, infos, start, end, highlight_type):
       
  2531         self.SelectProjectTreeItem(infos[0])
       
  2532         if infos[1] == "name":
       
  2533             self.Highlights[infos[0]] = highlight_type
       
  2534             self.RefreshProjectTree()
       
  2535             self.ProjectTree.Unselect()
       
  2536         else:
       
  2537             self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0])
       
  2538             selected = self.TabsOpened.GetSelection()
       
  2539             if selected != -1:
       
  2540                 viewer = self.TabsOpened.GetPage(selected)
       
  2541                 viewer.AddHighlight(infos[1:], start, end, highlight_type)
       
  2542 
       
  2543     def ShowError(self, infos, start, end):
       
  2544         self.ShowHighlight(infos, start, end, ERROR_HIGHLIGHT)
       
  2545 
       
  2546     def ShowSearchResult(self, infos, start, end):
       
  2547         self.ShowHighlight(infos, start, end, SEARCH_RESULT_HIGHLIGHT)
       
  2548 
       
  2549     def ClearHighlights(self, highlight_type=None):
       
  2550         if highlight_type is None:
       
  2551             self.Highlights = {}
       
  2552         else:
       
  2553             self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.iteritems() if highlight != highlight_type])
       
  2554         self.RefreshProjectTree()
       
  2555         for i in xrange(self.TabsOpened.GetPageCount()):
       
  2556             viewer = self.TabsOpened.GetPage(i)
       
  2557             viewer.ClearHighlights(highlight_type)
       
  2558 
       
  2559     def ClearErrors(self):
       
  2560         self.ClearHighlights(ERROR_HIGHLIGHT)
       
  2561 
       
  2562     def ClearSearchResults(self):
       
  2563         self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
       
  2564 
       
  2565 #-------------------------------------------------------------------------------
       
  2566 #                               Viewer Printout
       
  2567 #-------------------------------------------------------------------------------
       
  2568 
       
  2569 UPPER_DIV = lambda x, y: (x / y) + {True : 0, False : 1}[(x % y) == 0]
       
  2570 
       
  2571 class GraphicPrintout(wx.Printout):
       
  2572     def __init__(self, viewer, page_size, margins, preview = False):
       
  2573         wx.Printout.__init__(self)
       
  2574         self.Viewer = viewer
       
  2575         self.PageSize = page_size
       
  2576         if self.PageSize[0] == 0 or self.PageSize[1] == 0:
       
  2577             self.PageSize = (1050, 1485)
       
  2578         self.Preview = preview
       
  2579         self.Margins = margins
       
  2580         self.FontSize = 5
       
  2581         self.TextMargin = 3
       
  2582         
       
  2583         maxx, maxy = viewer.GetMaxSize()
       
  2584         self.PageGrid = (UPPER_DIV(maxx, self.PageSize[0]), 
       
  2585                          UPPER_DIV(maxy, self.PageSize[1]))
       
  2586         
       
  2587     def GetPageNumber(self):
       
  2588         return self.PageGrid[0] * self.PageGrid[1]
       
  2589     
       
  2590     def HasPage(self, page):
       
  2591         return page <= self.GetPageNumber()
       
  2592         
       
  2593     def GetPageInfo(self):
       
  2594         page_number = self.GetPageNumber()
       
  2595         return (1, page_number, 1, page_number)
       
  2596 
       
  2597     def OnBeginDocument(self, startPage, endPage):
       
  2598         dc = self.GetDC()
       
  2599         if not self.Preview and isinstance(dc, wx.PostScriptDC):
       
  2600             dc.SetResolution(720)
       
  2601         super(GraphicPrintout, self).OnBeginDocument(startPage, endPage)
       
  2602 
       
  2603     def OnPrintPage(self, page):
       
  2604         dc = self.GetDC()
       
  2605         dc.SetUserScale(1.0, 1.0)
       
  2606         dc.SetDeviceOrigin(0, 0)
       
  2607         dc.printing = not self.Preview
       
  2608         
       
  2609         # Get the size of the DC in pixels
       
  2610         ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
       
  2611         ppiScreenX, ppiScreenY = self.GetPPIScreen()
       
  2612         pw, ph = self.GetPageSizePixels()
       
  2613         dw, dh = dc.GetSizeTuple()
       
  2614         Xscale = (float(dw) * float(ppiPrinterX)) / (float(pw) * 25.4)
       
  2615         Yscale = (float(dh) * float(ppiPrinterY)) / (float(ph) * 25.4)
       
  2616         
       
  2617         fontsize = self.FontSize * Yscale
       
  2618         text_margin = self.TextMargin * Yscale
       
  2619         
       
  2620         margin_left = self.Margins[0].x * Xscale
       
  2621         margin_top = self.Margins[0].y * Yscale
       
  2622         area_width = dw - self.Margins[1].x * Xscale - margin_left
       
  2623         area_height = dh - self.Margins[1].y * Yscale - margin_top
       
  2624         
       
  2625         dc.SetPen(MiterPen(wx.BLACK))
       
  2626         dc.SetBrush(wx.TRANSPARENT_BRUSH)    
       
  2627         dc.DrawRectangle(margin_left, margin_top, area_width, area_height)
       
  2628         
       
  2629         dc.SetFont(wx.Font(fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
       
  2630         dc.SetTextForeground(wx.BLACK)
       
  2631         block_name = " - ".join(self.Viewer.GetTagName().split("::")[1:])
       
  2632         text_width, text_height = dc.GetTextExtent(block_name)
       
  2633         dc.DrawText(block_name, margin_left, margin_top - text_height - self.TextMargin)
       
  2634         dc.DrawText(_("Page: %d") % page, margin_left, margin_top + area_height + self.TextMargin)
       
  2635         
       
  2636         # Calculate the position on the DC for centering the graphic
       
  2637         posX = area_width * ((page - 1) % self.PageGrid[0])
       
  2638         posY = area_height * ((page - 1) / self.PageGrid[0])
       
  2639 
       
  2640         scaleX = float(area_width) / float(self.PageSize[0])
       
  2641         scaleY = float(area_height) / float(self.PageSize[1])
       
  2642         scale = min(scaleX, scaleY)
       
  2643 
       
  2644         # Set the scale and origin
       
  2645         dc.SetDeviceOrigin(-posX + margin_left, -posY + margin_top)
       
  2646         dc.SetClippingRegion(posX, posY, self.PageSize[0] * scale, self.PageSize[1] * scale)
       
  2647         dc.SetUserScale(scale, scale)
       
  2648         
       
  2649         #-------------------------------------------
       
  2650         
       
  2651         self.Viewer.DoDrawing(dc, True)
       
  2652         
       
  2653         return True
       
  2654