plugins/c_ext/CFileEditor.py
changeset 145 94855f7b08a9
child 161 faad68924b53
equal deleted inserted replaced
144:7818ec7b5c53 145:94855f7b08a9
       
     1 import  wx, wx.grid
       
     2 import  wx.stc  as  stc
       
     3 import keyword
       
     4 
       
     5 if wx.Platform == '__WXMSW__':
       
     6     faces = { 'times': 'Times New Roman',
       
     7               'mono' : 'Courier New',
       
     8               'helv' : 'Arial',
       
     9               'other': 'Comic Sans MS',
       
    10               'size' : 10,
       
    11               'size2': 8,
       
    12              }
       
    13 else:
       
    14     faces = { 'times': 'Times',
       
    15               'mono' : 'Courier',
       
    16               'helv' : 'Helvetica',
       
    17               'other': 'new century schoolbook',
       
    18               'size' : 12,
       
    19               'size2': 10,
       
    20              }
       
    21 
       
    22 if wx.VERSION >= (2, 8, 0):
       
    23     import wx.aui
       
    24 
       
    25     class MDICppEditor(wx.aui.AuiMDIChildFrame):
       
    26         def __init__(self, parent, name, window, controler):
       
    27             wx.aui.AuiMDIChildFrame.__init__(self, parent, -1, title = name)
       
    28             
       
    29             sizer = wx.BoxSizer(wx.HORIZONTAL)
       
    30             
       
    31             self.Viewer = CppEditor(self, name, window, controler)
       
    32             
       
    33             sizer.AddWindow(self.Viewer, 1, border=0, flag=wx.GROW)
       
    34             
       
    35             self.SetSizer(sizer)
       
    36         
       
    37         def GetViewer(self):
       
    38             return self.Viewer
       
    39 
       
    40     class MDIVariablesEditor(wx.aui.AuiMDIChildFrame):
       
    41         def __init__(self, parent, name, window, controler):
       
    42             wx.aui.AuiMDIChildFrame.__init__(self, parent, -1, title = name)
       
    43             
       
    44             sizer = wx.BoxSizer(wx.HORIZONTAL)
       
    45             
       
    46             self.Viewer = VariablesEditor(self, window, controler)
       
    47             
       
    48             sizer.AddWindow(self.Viewer, 1, border=0, flag=wx.GROW)
       
    49             
       
    50             self.SetSizer(sizer)
       
    51         
       
    52         def GetViewer(self):
       
    53             return self.Viewer
       
    54 
       
    55 
       
    56 def AppendMenu(parent, help, id, kind, text):
       
    57     if wx.VERSION >= (2, 6, 0):
       
    58         parent.Append(help=help, id=id, kind=kind, text=text)
       
    59     else:
       
    60         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
    61 
       
    62 
       
    63 [ID_CPPEDITOR,
       
    64 ] = [wx.NewId() for _init_ctrls in range(1)]
       
    65 
       
    66 CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
       
    67     "const", "const_cast", "continue", "default", "delete", "do", "double", 
       
    68     "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
       
    69     "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
       
    70     "namespace", "new", "operator", "private", "protected", "public", "register", 
       
    71     "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
       
    72     "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
       
    73     "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
       
    74     "void", "volatile", "wchar_t", "while"]
       
    75 
       
    76 def GetCursorPos(old, new):
       
    77     old_length = len(old)
       
    78     new_length = len(new)
       
    79     common_length = min(old_length, new_length)
       
    80     i = 0
       
    81     for i in xrange(common_length):
       
    82         if old[i] != new[i]:
       
    83             break
       
    84     if old_length < new_length:
       
    85         if common_length > 0 and old[i] != new[i]:
       
    86             return i + new_length - old_length
       
    87         else:
       
    88             return i + new_length - old_length + 1
       
    89     elif old_length > new_length or i < min(old_length, new_length) - 1:
       
    90         if common_length > 0 and old[i] != new[i]:
       
    91             return i
       
    92         else:
       
    93             return i + 1
       
    94     else:
       
    95         return None
       
    96 
       
    97 class CppEditor(stc.StyledTextCtrl):
       
    98 
       
    99     fold_symbols = 3
       
   100     
       
   101     def __init__(self, parent, name, window, controler):
       
   102         stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
       
   103                  wx.DefaultSize, 0)
       
   104 
       
   105         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
       
   106         self.SetMarginWidth(1, 25)
       
   107 
       
   108         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
       
   109         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
       
   110 
       
   111         self.SetLexer(stc.STC_LEX_CPP)
       
   112         self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
       
   113 
       
   114         self.SetProperty("fold", "1")
       
   115         self.SetProperty("tab.timmy.whinge.level", "1")
       
   116         self.SetMargins(0,0)
       
   117 
       
   118         self.SetViewWhiteSpace(False)
       
   119         #self.SetBufferedDraw(False)
       
   120         #self.SetViewEOL(True)
       
   121         #self.SetEOLMode(stc.STC_EOL_CRLF)
       
   122         #self.SetUseAntiAliasing(True)
       
   123         
       
   124         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
       
   125         self.SetEdgeColumn(78)
       
   126 
       
   127         # Setup a margin to hold fold markers
       
   128         #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
       
   129         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
       
   130         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
       
   131         self.SetMarginSensitive(2, True)
       
   132         self.SetMarginWidth(2, 12)
       
   133 
       
   134         if self.fold_symbols == 0:
       
   135             # Arrow pointing right for contracted folders, arrow pointing down for expanded
       
   136             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
       
   137             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
       
   138             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
       
   139             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
       
   140             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
       
   141             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
       
   142             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
       
   143             
       
   144         elif self.fold_symbols == 1:
       
   145             # Plus for contracted folders, minus for expanded
       
   146             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
       
   147             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
       
   148             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
       
   149             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
       
   150             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
       
   151             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
       
   152             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
       
   153 
       
   154         elif self.fold_symbols == 2:
       
   155             # Like a flattened tree control using circular headers and curved joins
       
   156             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
       
   157             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
       
   158             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
       
   159             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
       
   160             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
       
   161             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
       
   162             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
       
   163 
       
   164         elif self.fold_symbols == 3:
       
   165             # Like a flattened tree control using square headers
       
   166             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   167             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   168             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
       
   169             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
       
   170             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   171             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   172             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
       
   173 
       
   174 
       
   175         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
       
   176         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   177         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
       
   178 
       
   179         # Make some styles,  The lexer defines what each style is used for, we
       
   180         # just have to define what each style looks like.  This set is adapted from
       
   181         # Scintilla sample property files.
       
   182 
       
   183         # Global default styles for all languages
       
   184         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   185         self.StyleClearAll()  # Reset all to be like the default
       
   186 
       
   187         # Global default styles for all languages
       
   188         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   189         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
       
   190         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
       
   191         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
       
   192         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
       
   193 
       
   194         self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
       
   195         self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
       
   196         self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
       
   197         self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
       
   198         self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
       
   199         self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
       
   200         self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
       
   201         self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
       
   202         self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
       
   203         
       
   204         # register some images for use in the AutoComplete box.
       
   205         #self.RegisterImage(1, images.getSmilesBitmap())
       
   206         self.RegisterImage(1, 
       
   207             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
       
   208         self.RegisterImage(2, 
       
   209             wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
       
   210         self.RegisterImage(3, 
       
   211             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
       
   212 
       
   213         # Indentation size
       
   214         self.SetTabWidth(2)
       
   215         self.SetUseTabs(0)
       
   216 
       
   217         self.Controler = controler
       
   218         self.ParentWindow = window
       
   219         
       
   220         self.DisableEvents = True
       
   221         self.Name = name
       
   222         self.CurrentAction = None
       
   223         
       
   224         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
       
   225 
       
   226         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
       
   227         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
       
   228         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
       
   229     
       
   230     def OnModification(self, event):
       
   231         if not self.DisableEvents:
       
   232             mod_type = event.GetModificationType()
       
   233             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
       
   234                 if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
       
   235                     if self.CurrentAction == None:
       
   236                         self.StartBuffering()
       
   237                     elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
       
   238                         self.Controler.EndBuffering()
       
   239                         self.StartBuffering()
       
   240                     self.CurrentAction = ("Add", event.GetPosition())
       
   241                 elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
       
   242                     if self.CurrentAction == None:
       
   243                         self.StartBuffering()
       
   244                     elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
       
   245                         self.Controler.EndBuffering()
       
   246                         self.StartBuffering()
       
   247                     self.CurrentAction = ("Delete", event.GetPosition())
       
   248         event.Skip()
       
   249     
       
   250     def OnDoDrop(self, event):
       
   251         self.ResetBuffer()
       
   252         wx.CallAfter(self.RefreshModel)
       
   253         event.Skip()
       
   254 
       
   255     def IsViewing(self, name):
       
   256         return self.Name == name
       
   257 
       
   258     # Buffer the last model state
       
   259     def RefreshBuffer(self):
       
   260         self.Controler.BufferCFile()
       
   261         if self.ParentWindow:
       
   262             self.ParentWindow.RefreshTitle()
       
   263             self.ParentWindow.RefreshEditMenu()
       
   264     
       
   265     def StartBuffering(self):
       
   266         self.Controler.StartBuffering()
       
   267         if self.ParentWindow:
       
   268             self.ParentWindow.RefreshTitle()
       
   269             self.ParentWindow.RefreshEditMenu()
       
   270     
       
   271     def ResetBuffer(self):
       
   272         if self.CurrentAction != None:
       
   273             self.Controler.EndBuffering()
       
   274             self.CurrentAction = None
       
   275 
       
   276     def RefreshView(self):
       
   277         self.ResetBuffer()
       
   278         self.DisableEvents = True
       
   279         old_cursor_pos = self.GetCurrentPos()
       
   280         old_text = self.GetText()
       
   281         new_text = self.Controler.GetPartText(self.Name)
       
   282         self.SetText(new_text)
       
   283         new_cursor_pos = GetCursorPos(old_text, new_text)
       
   284         if new_cursor_pos != None:
       
   285             self.GotoPos(new_cursor_pos)
       
   286         else:
       
   287             self.GotoPos(old_cursor_pos)
       
   288         self.ScrollToColumn(0)
       
   289         self.EmptyUndoBuffer()
       
   290         self.DisableEvents = False
       
   291         
       
   292         self.Colourise(0, -1)
       
   293 
       
   294     def RefreshModel(self):
       
   295         self.Controler.SetPartText(self.Name, self.GetText())
       
   296 
       
   297     def OnKeyPressed(self, event):
       
   298         if self.CallTipActive():
       
   299             self.CallTipCancel()
       
   300         key = event.GetKeyCode()
       
   301 
       
   302         if key == 32 and event.ControlDown():
       
   303             pos = self.GetCurrentPos()
       
   304 
       
   305             # Tips
       
   306             if event.ShiftDown():
       
   307                 pass
       
   308 ##                self.CallTipSetBackground("yellow")
       
   309 ##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
       
   310 ##                                 'show some suff, maybe parameters..\n\n'
       
   311 ##                                 'fubar(param1, param2)')
       
   312             # Code completion
       
   313             else:
       
   314                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
       
   315 
       
   316                 # Images are specified with a appended "?type"
       
   317                 self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
       
   318         else:
       
   319             wx.CallAfter(self.RefreshModel)
       
   320             event.Skip()
       
   321 
       
   322     def OnKillFocus(self, event):
       
   323         self.AutoCompCancel()
       
   324         event.Skip()
       
   325 
       
   326     def OnUpdateUI(self, evt):
       
   327         # check for matching braces
       
   328         braceAtCaret = -1
       
   329         braceOpposite = -1
       
   330         charBefore = None
       
   331         caretPos = self.GetCurrentPos()
       
   332 
       
   333         if caretPos > 0:
       
   334             charBefore = self.GetCharAt(caretPos - 1)
       
   335             styleBefore = self.GetStyleAt(caretPos - 1)
       
   336 
       
   337         # check before
       
   338         if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
       
   339             braceAtCaret = caretPos - 1
       
   340 
       
   341         # check after
       
   342         if braceAtCaret < 0:
       
   343             charAfter = self.GetCharAt(caretPos)
       
   344             styleAfter = self.GetStyleAt(caretPos)
       
   345 
       
   346             if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
       
   347                 braceAtCaret = caretPos
       
   348 
       
   349         if braceAtCaret >= 0:
       
   350             braceOpposite = self.BraceMatch(braceAtCaret)
       
   351 
       
   352         if braceAtCaret != -1  and braceOpposite == -1:
       
   353             self.BraceBadLight(braceAtCaret)
       
   354         else:
       
   355             self.BraceHighlight(braceAtCaret, braceOpposite)
       
   356             #pt = self.PointFromPosition(braceOpposite)
       
   357             #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
       
   358             #print pt
       
   359             #self.Refresh(False)
       
   360 
       
   361 
       
   362     def OnMarginClick(self, evt):
       
   363         # fold and unfold as needed
       
   364         if evt.GetMargin() == 2:
       
   365             if evt.GetShift() and evt.GetControl():
       
   366                 self.FoldAll()
       
   367             else:
       
   368                 lineClicked = self.LineFromPosition(evt.GetPosition())
       
   369 
       
   370                 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
       
   371                     if evt.GetShift():
       
   372                         self.SetFoldExpanded(lineClicked, True)
       
   373                         self.Expand(lineClicked, True, True, 1)
       
   374                     elif evt.GetControl():
       
   375                         if self.GetFoldExpanded(lineClicked):
       
   376                             self.SetFoldExpanded(lineClicked, False)
       
   377                             self.Expand(lineClicked, False, True, 0)
       
   378                         else:
       
   379                             self.SetFoldExpanded(lineClicked, True)
       
   380                             self.Expand(lineClicked, True, True, 100)
       
   381                     else:
       
   382                         self.ToggleFold(lineClicked)
       
   383 
       
   384 
       
   385     def FoldAll(self):
       
   386         lineCount = self.GetLineCount()
       
   387         expanding = True
       
   388 
       
   389         # find out if we are folding or unfolding
       
   390         for lineNum in range(lineCount):
       
   391             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
       
   392                 expanding = not self.GetFoldExpanded(lineNum)
       
   393                 break
       
   394 
       
   395         lineNum = 0
       
   396 
       
   397         while lineNum < lineCount:
       
   398             level = self.GetFoldLevel(lineNum)
       
   399             if level & stc.STC_FOLDLEVELHEADERFLAG and \
       
   400                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
       
   401 
       
   402                 if expanding:
       
   403                     self.SetFoldExpanded(lineNum, True)
       
   404                     lineNum = self.Expand(lineNum, True)
       
   405                     lineNum = lineNum - 1
       
   406                 else:
       
   407                     lastChild = self.GetLastChild(lineNum, -1)
       
   408                     self.SetFoldExpanded(lineNum, False)
       
   409 
       
   410                     if lastChild > lineNum:
       
   411                         self.HideLines(lineNum+1, lastChild)
       
   412 
       
   413             lineNum = lineNum + 1
       
   414 
       
   415 
       
   416 
       
   417     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
       
   418         lastChild = self.GetLastChild(line, level)
       
   419         line = line + 1
       
   420 
       
   421         while line <= lastChild:
       
   422             if force:
       
   423                 if visLevels > 0:
       
   424                     self.ShowLines(line, line)
       
   425                 else:
       
   426                     self.HideLines(line, line)
       
   427             else:
       
   428                 if doExpand:
       
   429                     self.ShowLines(line, line)
       
   430 
       
   431             if level == -1:
       
   432                 level = self.GetFoldLevel(line)
       
   433 
       
   434             if level & stc.STC_FOLDLEVELHEADERFLAG:
       
   435                 if force:
       
   436                     if visLevels > 1:
       
   437                         self.SetFoldExpanded(line, True)
       
   438                     else:
       
   439                         self.SetFoldExpanded(line, False)
       
   440 
       
   441                     line = self.Expand(line, doExpand, force, visLevels-1)
       
   442 
       
   443                 else:
       
   444                     if doExpand and self.GetFoldExpanded(line):
       
   445                         line = self.Expand(line, True, force, visLevels-1)
       
   446                     else:
       
   447                         line = self.Expand(line, False, force, visLevels-1)
       
   448             else:
       
   449                 line = line + 1
       
   450 
       
   451         return line
       
   452 
       
   453 
       
   454 #-------------------------------------------------------------------------------
       
   455 #                         Helper for VariablesGrid values
       
   456 #-------------------------------------------------------------------------------
       
   457 
       
   458 class VariablesTable(wx.grid.PyGridTableBase):
       
   459     
       
   460     """
       
   461     A custom wxGrid Table using user supplied data
       
   462     """
       
   463     def __init__(self, parent, data, colnames):
       
   464         # The base class must be initialized *first*
       
   465         wx.grid.PyGridTableBase.__init__(self)
       
   466         self.data = data
       
   467         self.colnames = colnames
       
   468         self.Parent = parent
       
   469         # XXX
       
   470         # we need to store the row length and collength to
       
   471         # see if the table has changed size
       
   472         self._rows = self.GetNumberRows()
       
   473         self._cols = self.GetNumberCols()
       
   474     
       
   475     def GetNumberCols(self):
       
   476         return len(self.colnames)
       
   477         
       
   478     def GetNumberRows(self):
       
   479         return len(self.data)
       
   480 
       
   481     def GetColLabelValue(self, col):
       
   482         if col < len(self.colnames):
       
   483             return self.colnames[col]
       
   484 
       
   485     def GetRowLabelValues(self, row):
       
   486         return row
       
   487 
       
   488     def GetValue(self, row, col):
       
   489         if row < self.GetNumberRows():
       
   490             if col == 0:
       
   491                 return row + 1
       
   492             else:
       
   493                 return str(self.data[row].get(self.GetColLabelValue(col), ""))
       
   494     
       
   495     def GetValueByName(self, row, colname):
       
   496         if row < self.GetNumberRows():
       
   497             return self.data[row].get(colname, None)
       
   498         return None
       
   499 
       
   500     def SetValue(self, row, col, value):
       
   501         if col < len(self.colnames):
       
   502             self.data[row][self.GetColLabelValue(col)] = value
       
   503     
       
   504     def SetValueByName(self, row, colname, value):
       
   505         if row < self.GetNumberRows():
       
   506             self.data[row][colname] = value
       
   507         
       
   508     def ResetView(self, grid):
       
   509         """
       
   510         (wxGrid) -> Reset the grid view.   Call this to
       
   511         update the grid if rows and columns have been added or deleted
       
   512         """
       
   513         grid.BeginBatch()
       
   514         for current, new, delmsg, addmsg in [
       
   515             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
       
   516             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
       
   517         ]:
       
   518             if new < current:
       
   519                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
       
   520                 grid.ProcessTableMessage(msg)
       
   521             elif new > current:
       
   522                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
       
   523                 grid.ProcessTableMessage(msg)
       
   524                 self.UpdateValues(grid)
       
   525         grid.EndBatch()
       
   526 
       
   527         self._rows = self.GetNumberRows()
       
   528         self._cols = self.GetNumberCols()
       
   529         # update the column rendering scheme
       
   530         self._updateColAttrs(grid)
       
   531 
       
   532         # update the scrollbars and the displayed part of the grid
       
   533         grid.AdjustScrollbars()
       
   534         grid.ForceRefresh()
       
   535 
       
   536     def UpdateValues(self, grid):
       
   537         """Update all displayed values"""
       
   538         # This sends an event to the grid table to update all of the values
       
   539         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
       
   540         grid.ProcessTableMessage(msg)
       
   541 
       
   542     def _updateColAttrs(self, grid):
       
   543         """
       
   544         wxGrid -> update the column attributes to add the
       
   545         appropriate renderer given the column name.
       
   546 
       
   547         Otherwise default to the default renderer.
       
   548         """
       
   549         
       
   550         typelist = None
       
   551         accesslist = None
       
   552         for row in range(self.GetNumberRows()):
       
   553             for col in range(self.GetNumberCols()):
       
   554                 editor = None
       
   555                 renderer = None
       
   556                 colname = self.GetColLabelValue(col)
       
   557                 grid.SetReadOnly(row, col, False)
       
   558                 
       
   559                 if colname == "Name":
       
   560                     editor = wx.grid.GridCellTextEditor()
       
   561                 elif colname == "Class":
       
   562                     editor = wx.grid.GridCellChoiceEditor()
       
   563                     editor.SetParameters("input,output")
       
   564                 elif colname == "Type":
       
   565                     pass
       
   566                 else:
       
   567                     grid.SetReadOnly(row, col, True)
       
   568                 
       
   569                 grid.SetCellEditor(row, col, editor)
       
   570                 grid.SetCellRenderer(row, col, renderer)
       
   571                 
       
   572                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
       
   573     
       
   574     def SetData(self, data):
       
   575         self.data = data
       
   576     
       
   577     def GetData(self):
       
   578         return self.data
       
   579     
       
   580     def GetCurrentIndex(self):
       
   581         return self.CurrentIndex
       
   582     
       
   583     def SetCurrentIndex(self, index):
       
   584         self.CurrentIndex = index
       
   585     
       
   586     def AppendRow(self, row_content):
       
   587         self.data.append(row_content)
       
   588 
       
   589     def RemoveRow(self, row_index):
       
   590         self.data.pop(row_index)
       
   591 
       
   592     def MoveRow(self, row_index, move, grid):
       
   593         new_index = max(0, min(row_index + move, len(self.data) - 1))
       
   594         if new_index != row_index:
       
   595             self.data.insert(new_index, self.data.pop(row_index))
       
   596             grid.SetGridCursor(new_index, grid.GetGridCursorCol())
       
   597 
       
   598     def GetRow(self, row_index):
       
   599         return self.data[row_index]
       
   600 
       
   601     def Empty(self):
       
   602         self.data = []
       
   603         self.editors = []
       
   604 
       
   605 
       
   606 [ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
       
   607  ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, 
       
   608  ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
       
   609 ] = [wx.NewId() for _init_ctrls in range(6)]
       
   610 
       
   611 class VariablesEditor(wx.Panel):
       
   612     
       
   613     if wx.VERSION < (2, 6, 0):
       
   614         def Bind(self, event, function, id = None):
       
   615             if id is not None:
       
   616                 event(self, id, function)
       
   617             else:
       
   618                 event(self, function)
       
   619     
       
   620     def _init_coll_MainSizer_Growables(self, parent):
       
   621         parent.AddGrowableCol(0)
       
   622         parent.AddGrowableRow(0)
       
   623 
       
   624     def _init_coll_MainSizer_Items(self, parent):
       
   625         parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
       
   626         parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
       
   627 
       
   628     def _init_coll_ButtonsSizer_Growables(self, parent):
       
   629         parent.AddGrowableCol(0)
       
   630         parent.AddGrowableRow(0)
       
   631 
       
   632     def _init_coll_ButtonsSizer_Items(self, parent):
       
   633         parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
       
   634         parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
       
   635         parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
       
   636         parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
       
   637 
       
   638     def _init_sizers(self):
       
   639         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
       
   640         self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
   641         
       
   642         self._init_coll_MainSizer_Growables(self.MainSizer)
       
   643         self._init_coll_MainSizer_Items(self.MainSizer)
       
   644         self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
       
   645         self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
       
   646         
       
   647         self.SetSizer(self.MainSizer)
       
   648 
       
   649     def _init_ctrls(self, prnt):
       
   650         wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
       
   651               size=wx.Size(0, 0), style=wx.SUNKEN_BORDER)
       
   652         
       
   653         self.VariablesGrid = wx.grid.Grid(id=ID_VARIABLESEDITORVARIABLESGRID,
       
   654               name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
       
   655               size=wx.Size(-1, -1), style=wx.VSCROLL)
       
   656         self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
   657               'Sans'))
       
   658         self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
   659               False, 'Sans'))
       
   660         if wx.VERSION >= (2, 5, 0):
       
   661             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
       
   662             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
       
   663             self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
       
   664         else:
       
   665             wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
       
   666             wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
       
   667             wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
       
   668         
       
   669         self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
       
   670               name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
       
   671               size=wx.Size(122, 32), style=0)
       
   672         self.Bind(wx.EVT_BUTTON, self.OnAddVariableButton, id=ID_VARIABLESEDITORADDVARIABLEBUTTON)
       
   673 
       
   674         self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
       
   675               name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
       
   676               size=wx.Size(122, 32), style=0)
       
   677         self.Bind(wx.EVT_BUTTON, self.OnDeleteVariableButton, id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON)
       
   678 
       
   679         self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
       
   680               name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
       
   681               size=wx.Size(32, 32), style=0)
       
   682         self.Bind(wx.EVT_BUTTON, self.OnUpVariableButton, id=ID_VARIABLESEDITORUPVARIABLEBUTTON)
       
   683 
       
   684         self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
       
   685               name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
       
   686               size=wx.Size(32, 32), style=0)
       
   687         self.Bind(wx.EVT_BUTTON, self.OnDownVariableButton, id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON)
       
   688 
       
   689         self._init_sizers()
       
   690 
       
   691     def __init__(self, parent, window, controler):
       
   692         self._init_ctrls(parent)
       
   693         
       
   694         self.ParentWindow = window
       
   695         self.Controler = controler
       
   696         
       
   697         self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
       
   698         self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
       
   699         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
       
   700         self.ColSizes = [40, 200, 150, 150]
       
   701         self.VariablesGrid.SetTable(self.Table)
       
   702         self.VariablesGrid.SetRowLabelSize(0)
       
   703         for col in range(self.Table.GetNumberCols()):
       
   704             attr = wx.grid.GridCellAttr()
       
   705             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
       
   706             self.VariablesGrid.SetColAttr(col, attr)
       
   707             self.VariablesGrid.SetColSize(col, self.ColSizes[col])
       
   708         self.Table.ResetView(self.VariablesGrid)
       
   709 
       
   710     def IsViewing(self, name):
       
   711         return name == "Variables"
       
   712 
       
   713     def RefreshModel(self):
       
   714         self.Controler.SetVariables(self.Table.GetData())
       
   715         self.RefreshBuffer()
       
   716         
       
   717     def ResetBuffer(self):
       
   718         pass
       
   719 
       
   720     # Buffer the last model state
       
   721     def RefreshBuffer(self):
       
   722         self.Controler.BufferCFile()
       
   723         self.ParentWindow.RefreshTitle()
       
   724         self.ParentWindow.RefreshEditMenu()
       
   725 
       
   726     def RefreshView(self):
       
   727         self.Table.SetData(self.Controler.GetVariables())
       
   728         self.Table.ResetView(self.VariablesGrid)
       
   729     
       
   730     def OnAddVariableButton(self, event):
       
   731         self.Table.AppendRow(self.VariablesDefaultValue.copy())
       
   732         self.RefreshModel()
       
   733         self.RefreshView()
       
   734         event.Skip()
       
   735 
       
   736     def OnDeleteVariableButton(self, event):
       
   737         row = self.VariablesGrid.GetGridCursorRow()
       
   738         self.Table.RemoveRow(row)
       
   739         self.RefreshModel()
       
   740         self.RefreshView()
       
   741         event.Skip()
       
   742 
       
   743     def OnUpVariableButton(self, event):
       
   744         row = self.VariablesGrid.GetGridCursorRow()
       
   745         self.Table.MoveRow(row, -1, self.VariablesGrid)
       
   746         self.RefreshModel()
       
   747         self.RefreshView()
       
   748         event.Skip()
       
   749 
       
   750     def OnDownVariableButton(self, event):
       
   751         row = self.VariablesGrid.GetGridCursorRow()
       
   752         self.Table.MoveRow(row, 1, self.VariablesGrid)
       
   753         self.RefreshModel()
       
   754         self.RefreshView()
       
   755         event.Skip()
       
   756 
       
   757     def OnVariablesGridCellChange(self, event):
       
   758         self.RefreshModel()
       
   759         self.RefreshView()
       
   760         event.Skip()
       
   761 
       
   762     def OnVariablesGridEditorShown(self, event):
       
   763         row, col = event.GetRow(), event.GetCol() 
       
   764         if self.Table.GetColLabelValue(col) == "Type":
       
   765             type_menu = wx.Menu(title='')
       
   766             base_menu = wx.Menu(title='')
       
   767             for base_type in self.Controler.GetBaseTypes():
       
   768                 new_id = wx.NewId()
       
   769                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
       
   770                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
       
   771             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
       
   772             datatype_menu = wx.Menu(title='')
       
   773             for datatype in self.Controler.GetDataTypes(basetypes = False):
       
   774                 new_id = wx.NewId()
       
   775                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
       
   776                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
       
   777             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
       
   778             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
       
   779             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
       
   780             event.Veto()
       
   781         else:
       
   782             event.Skip()
       
   783 
       
   784     def GetVariableTypeFunction(self, base_type):
       
   785         def VariableTypeFunction(event):
       
   786             row = self.VariablesGrid.GetGridCursorRow()
       
   787             self.Table.SetValueByName(row, "Type", base_type)
       
   788             self.Table.ResetView(self.VariablesGrid)
       
   789             self.RefreshModel()
       
   790             self.RefreshView()
       
   791             event.Skip()
       
   792         return VariableTypeFunction
       
   793 
       
   794     def OnVariablesGridCellLeftClick(self, event):
       
   795         if event.GetCol() == 0:
       
   796             row = event.GetRow()
       
   797             num = 0
       
   798             if self.Table.GetValueByName(row, "Class") == "input":
       
   799                 dir = "%I"
       
   800                 for i in xrange(row):
       
   801                     if self.Table.GetValueByName(i, "Class") == "input":
       
   802                         num += 1
       
   803             else:
       
   804                 dir = "%Q"
       
   805                 for i in xrange(row):
       
   806                     if self.Table.GetValueByName(i, "Class") == "input":
       
   807                         num += 1
       
   808             data_type = self.Table.GetValueByName(row, "Type")
       
   809             base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
       
   810             location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
       
   811             data = wx.TextDataObject(str((location, "location", data_type)))
       
   812             dragSource = wx.DropSource(self.VariablesGrid)
       
   813             dragSource.SetData(data)
       
   814             dragSource.DoDragDrop()
       
   815         event.Skip()
       
   816     
       
   817 
       
   818 #-------------------------------------------------------------------------------
       
   819 #                          SVGUIEditor Main Frame Class
       
   820 #-------------------------------------------------------------------------------
       
   821 
       
   822 if wx.VERSION >= (2, 8, 0):
       
   823     base_class = wx.aui.AuiMDIParentFrame
       
   824 else:
       
   825     base_class = wx.Frame
       
   826 
       
   827 CFILE_PARTS = ["Includes", "Variables", "Globals", "Init", "CleanUp", "Retrieve", 
       
   828                "Publish"]
       
   829 
       
   830 [ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, 
       
   831  ID_CFILEEDITORCFILETREE, CFILEEDITORPARTSOPENED, 
       
   832 ] = [wx.NewId() for _init_ctrls in range(4)]
       
   833 
       
   834 class CFileEditor(base_class):
       
   835     
       
   836     if wx.VERSION < (2, 6, 0):
       
   837         def Bind(self, event, function, id = None):
       
   838             if id is not None:
       
   839                 event(self, id, function)
       
   840             else:
       
   841                 event(self, function)
       
   842     
       
   843     def _init_coll_EditMenu_Items(self, parent):
       
   844         AppendMenu(parent, help='', id=wx.ID_REFRESH,
       
   845               kind=wx.ITEM_NORMAL, text=u'Refresh\tCTRL+R')
       
   846         AppendMenu(parent, help='', id=wx.ID_UNDO,
       
   847               kind=wx.ITEM_NORMAL, text=u'Undo\tCTRL+Z')
       
   848         AppendMenu(parent, help='', id=wx.ID_REDO,
       
   849               kind=wx.ITEM_NORMAL, text=u'Redo\tCTRL+Y')
       
   850         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
       
   851         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
       
   852         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
       
   853     
       
   854     def _init_coll_MenuBar_Menus(self, parent):
       
   855         parent.Append(menu=self.EditMenu, title=u'&Edit')
       
   856     
       
   857     def _init_utils(self):
       
   858         self.MenuBar = wx.MenuBar()
       
   859 
       
   860         self.EditMenu = wx.Menu(title='')
       
   861         
       
   862         self._init_coll_MenuBar_Menus(self.MenuBar)
       
   863         self._init_coll_EditMenu_Items(self.EditMenu)
       
   864         
       
   865     def _init_ctrls(self, prnt):
       
   866         if wx.VERSION >= (2, 8, 0):
       
   867             wx.aui.AuiMDIParentFrame.__init__(self, winid=ID_CFILEEDITOR, name=u'CFileEditor', 
       
   868                   parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650),
       
   869                   style=wx.DEFAULT_FRAME_STYLE|wx.SUNKEN_BORDER|wx.CLIP_CHILDREN, title=u'CFileEditor')
       
   870         else:
       
   871             wx.Frame.__init__(self, id=ID_CFILEEDITOR, name=u'CFileEditor',
       
   872                   parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650),
       
   873                   style=wx.DEFAULT_FRAME_STYLE, title=u'CFileEditor')
       
   874         self._init_utils()
       
   875         self.SetClientSize(wx.Size(1000, 600))
       
   876         self.SetMenuBar(self.MenuBar)
       
   877         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
       
   878         
       
   879         self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE)
       
   880         accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)])
       
   881         self.SetAcceleratorTable(accel)
       
   882         
       
   883         if wx.VERSION >= (2, 8, 0):
       
   884             self.AUIManager = wx.aui.AuiManager(self)
       
   885             self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
       
   886         
       
   887         if wx.VERSION < (2, 8, 0):
       
   888             self.MainSplitter = wx.SplitterWindow(id=ID_CFILEEDITORMAINSPLITTER, 
       
   889                   name='MainSplitter', parent=self, point=wx.Point(0, 0),
       
   890                   size=wx.Size(-1, -1), style=wx.SP_3D)
       
   891             self.MainSplitter.SetNeedUpdating(True)
       
   892             self.MainSplitter.SetMinimumPaneSize(1)
       
   893         
       
   894             self.CFileTree = wx.TreeCtrl(id=ID_CFILEEDITORCFILETREE, 
       
   895                   name='CFileTree', parent=self.MainSplitter, pos=wx.Point(0, 0),
       
   896                   size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER)
       
   897         else:
       
   898             self.CFileTree = wx.TreeCtrl(id=ID_CFILEEDITORCFILETREE, 
       
   899                   name='CFileTree', parent=self, pos=wx.Point(0, 0),
       
   900                   size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER)
       
   901             self.AUIManager.AddPane(self.CFileTree, wx.aui.AuiPaneInfo().Caption("CFile Tree").Left().Layer(1).BestSize(wx.Size(200, 500)).CloseButton(False))
       
   902         self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnCFileTreeItemSelected, 
       
   903               id=ID_CFILEEDITORCFILETREE)
       
   904         self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnCFileTreeItemActivated,
       
   905               id=ID_CFILEEDITORCFILETREE)
       
   906         
       
   907         if wx.VERSION < (2, 8, 0):
       
   908             self.PartsOpened = wx.Notebook(id=ID_CFILEEDITORPARTSOPENED,
       
   909                   name='PartsOpened', parent=self.MainSplitter, pos=wx.Point(0,
       
   910                   0), size=wx.Size(0, 0), style=0)
       
   911             if wx.VERSION >= (2, 6, 0):
       
   912                 self.PartsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
       
   913                     self.OnPartSelectedChanged, id=CFILEEDITORPARTSOPENED)
       
   914             else:
       
   915                 wx.EVT_NOTEBOOK_PAGE_CHANGED(self.PartsOpened, CFILEEDITORPARTSOPENED,
       
   916                     self.OnPartSelectedChanged)
       
   917             
       
   918             self.MainSplitter.SplitVertically(self.ProjectTree, self.PartsOpened, 200)
       
   919         
       
   920         self.StatusBar = wx.StatusBar( name='HelpBar',
       
   921               parent=self, style=wx.ST_SIZEGRIP)
       
   922         self.SetStatusBar(self.StatusBar)
       
   923         
       
   924         if wx.VERSION >= (2, 8, 0):
       
   925             self.AUIManager.Update()
       
   926     
       
   927     def __init__(self, parent, controler):
       
   928         self._init_ctrls(parent)
       
   929         
       
   930         self.Controler = controler
       
   931 
       
   932         self.InitCFileTree()
       
   933         self.RefreshTitle()
       
   934         self.RefreshEditMenu()
       
   935 
       
   936     def OnCloseFrame(self, event):
       
   937         if wx.VERSION >= (2, 8, 0):
       
   938             self.AUIManager.UnInit()
       
   939         if getattr(self, "_onclose", None) is not None:
       
   940             self._onclose()
       
   941         event.Skip()
       
   942 
       
   943     def OnCloseTabMenu(self, event):
       
   944         selected = self.GetPageSelection()
       
   945         if selected >= 0:
       
   946             self.DeletePage(selected)
       
   947         event.Skip()
       
   948 
       
   949     def OnSaveMenu(self, event):
       
   950         if getattr(self, "_onsave", None) != None:
       
   951             self._onsave()
       
   952         self.RefreshTitle()
       
   953         self.RefreshEditMenu()
       
   954         event.Skip()
       
   955 
       
   956 #-------------------------------------------------------------------------------
       
   957 #                            Notebook Unified Functions
       
   958 #-------------------------------------------------------------------------------
       
   959 
       
   960     def GetPageCount(self):
       
   961         if wx.VERSION >= (2, 8, 0):
       
   962             notebook = self.GetNotebook()
       
   963             if notebook is not None:
       
   964                 return notebook.GetPageCount()
       
   965             else:
       
   966                 return 0
       
   967         else:
       
   968             return self.PartsOpened.GetPageCount()
       
   969     
       
   970     def GetPage(self, idx):
       
   971         if wx.VERSION >= (2, 8, 0):
       
   972             notebook = self.GetNotebook()
       
   973             if notebook is not None:
       
   974                 return notebook.GetPage(idx).GetViewer()
       
   975             else:
       
   976                 return None
       
   977         else:
       
   978             return self.PartsOpened.GetPage(idx)
       
   979 
       
   980     def GetPageSelection(self):
       
   981         if wx.VERSION >= (2, 8, 0):
       
   982             notebook = self.GetNotebook()
       
   983             if notebook is not None:
       
   984                 return notebook.GetSelection()
       
   985             else:
       
   986                 return -1
       
   987         else:
       
   988             return self.PartsOpened.GetSelection()
       
   989 
       
   990     def SetPageSelection(self, idx):
       
   991         if wx.VERSION >= (2, 8, 0):
       
   992             notebook = self.GetNotebook()
       
   993             if notebook is not None:
       
   994                 notebook.SetSelection(idx)
       
   995         else:
       
   996             self.PartsOpened.SetSelection(idx)
       
   997 
       
   998     def DeletePage(self, idx):
       
   999         if wx.VERSION >= (2, 8, 0):
       
  1000             notebook = self.GetNotebook()
       
  1001             if notebook is not None:
       
  1002                 notebook.DeletePage(idx)
       
  1003         else:
       
  1004             self.PartsOpened.DeletePage(idx)
       
  1005 
       
  1006     def DeleteAllPages(self):
       
  1007         if wx.VERSION >= (2, 8, 0):
       
  1008             notebook = self.GetNotebook()
       
  1009             if notebook is not None:
       
  1010                 for idx in xrange(notebook.GetPageCount()):
       
  1011                     notebook.DeletePage(0)
       
  1012         else:
       
  1013             self.PartsOpened.DeleteAllPages()
       
  1014 
       
  1015     def SetPageText(self, idx, text):
       
  1016         if wx.VERSION >= (2, 8, 0):
       
  1017             notebook = self.GetNotebook()
       
  1018             if notebook is not None:
       
  1019                 return notebook.SetPageText(idx, text)
       
  1020         else:
       
  1021             return self.PartsOpened.SetPageText(idx, text)
       
  1022 
       
  1023     def SetPageBitmap(self, idx, bitmap):
       
  1024         if wx.VERSION >= (2, 8, 0):
       
  1025             notebook = self.GetNotebook()
       
  1026             if notebook is not None:
       
  1027                 return notebook.SetPageBitmap(idx, bitmap)
       
  1028         else:
       
  1029             return self.PartsOpened.SetPageImage(idx, bitmap)
       
  1030 
       
  1031     def GetPageText(self, idx):
       
  1032         if wx.VERSION >= (2, 8, 0):
       
  1033             notebook = self.GetNotebook()
       
  1034             if notebook is not None:
       
  1035                 return notebook.GetPageText(idx)
       
  1036             else:
       
  1037                 return ""
       
  1038         else:
       
  1039             return self.PartsOpened.GetPageText(idx)
       
  1040 
       
  1041     def IsOpened(self, name):
       
  1042         for idx in xrange(self.GetPageCount()):
       
  1043             if self.GetPage(idx).IsViewing(name):
       
  1044                 return idx
       
  1045         return None
       
  1046 
       
  1047     def RefreshTitle(self):
       
  1048         self.SetTitle("CFileEditor - %s"%self.Controler.GetFilename())
       
  1049         
       
  1050 #-------------------------------------------------------------------------------
       
  1051 #                          Edit Project Menu Functions
       
  1052 #-------------------------------------------------------------------------------
       
  1053 
       
  1054     def RefreshEditMenu(self):
       
  1055         if self.EditMenu:
       
  1056             undo, redo = self.Controler.GetBufferState()
       
  1057             self.EditMenu.Enable(wx.ID_UNDO, undo)
       
  1058             self.EditMenu.Enable(wx.ID_REDO, redo)
       
  1059 
       
  1060     def OnRefreshMenu(self, event):
       
  1061         selected = self.GetPageSelection()
       
  1062         if selected != -1:
       
  1063             window = self.GetPage(selected)
       
  1064             window.RefreshView()
       
  1065         event.Skip()
       
  1066 
       
  1067     def OnUndoMenu(self, event):
       
  1068         self.Controler.LoadPrevious()
       
  1069         selected = self.GetPageSelection()        
       
  1070         if selected != -1:
       
  1071             window = self.GetPage(selected)
       
  1072             window.RefreshView()
       
  1073         self.RefreshTitle()
       
  1074         self.RefreshEditMenu()
       
  1075         event.Skip()
       
  1076     
       
  1077     def OnRedoMenu(self, event):
       
  1078         self.Controler.LoadNext()
       
  1079         selected = self.GetPageSelection()
       
  1080         if selected != -1:
       
  1081             window = self.GetPage(selected)
       
  1082             window.RefreshView()
       
  1083         self.RefreshTitle()
       
  1084         self.RefreshEditMenu()
       
  1085         event.Skip()
       
  1086         
       
  1087 #-------------------------------------------------------------------------------
       
  1088 #                      CFile Editor Panels Management Functions
       
  1089 #-------------------------------------------------------------------------------
       
  1090     
       
  1091     def OnPartSelectedChanged(self, event):
       
  1092         if wx.VERSION < (2, 8, 0) or event.GetActive():
       
  1093             old_selected = self.GetPageSelection()
       
  1094             if old_selected >= 0:
       
  1095                 self.GetPage(old_selected).ResetBuffer()
       
  1096             if wx.VERSION >= (2, 8, 0):
       
  1097                 window = event.GetEventObject().GetViewer()
       
  1098             else:
       
  1099                 selected = event.GetSelection()
       
  1100                 if selected >= 0:
       
  1101                     window = self.GetPage(selected)
       
  1102                 else:
       
  1103                     window = None
       
  1104             if window:
       
  1105                 window.RefreshView()
       
  1106         event.Skip()
       
  1107 
       
  1108 #-------------------------------------------------------------------------------
       
  1109 #                         CFile Tree Management Functions
       
  1110 #-------------------------------------------------------------------------------
       
  1111 
       
  1112     def InitCFileTree(self):
       
  1113         root = self.CFileTree.AddRoot("C File")
       
  1114         for name in CFILE_PARTS:
       
  1115             self.CFileTree.AppendItem(root, name)
       
  1116         self.CFileTree.Expand(root)
       
  1117 
       
  1118     def OnCFileTreeItemActivated(self, event):
       
  1119         self.EditCFilePart(self.CFileTree.GetItemText(event.GetItem()))
       
  1120         event.Skip()
       
  1121 
       
  1122     def OnCFileTreeItemSelected(self, event):
       
  1123         select_item = event.GetItem()
       
  1124         self.EditCFilePart(self.CFileTree.GetItemText(event.GetItem()), True)
       
  1125         event.Skip()
       
  1126         
       
  1127     def EditCFilePart(self, name, onlyopened = False):
       
  1128         openedidx = self.IsOpened(name)
       
  1129         if openedidx is not None:
       
  1130             old_selected = self.GetPageSelection()
       
  1131             if old_selected != openedidx:
       
  1132                 if old_selected >= 0:
       
  1133                     self.GetPage(old_selected).ResetBuffer()
       
  1134                 self.SetPageSelection(openedidx)
       
  1135             self.GetPage(openedidx).RefreshView()
       
  1136         elif not onlyopened:
       
  1137             if wx.VERSION >= (2, 8, 0):
       
  1138                 if name == "Variables":
       
  1139                     new_window = MDIVariablesEditor(self, name, self, self.Controler)
       
  1140                 else:
       
  1141                     new_window = MDICppEditor(self, name, self, self.Controler)
       
  1142                 new_window.Bind(wx.EVT_ACTIVATE, self.OnPartSelectedChanged)
       
  1143                 new_window.Layout()
       
  1144             else:
       
  1145                 if name == "Variables":
       
  1146                     new_window = VariablesEditor(self.TabsOpened, self, self.Controler)
       
  1147                     self.TabsOpened.AddPage(new_window, name)
       
  1148                 else:
       
  1149                     new_window = CppEditor(self.TabsOpened, name, self, self.Controler)
       
  1150                     self.TabsOpened.AddPage(new_window, name)
       
  1151             openedidx = self.IsOpened(name)
       
  1152             old_selected = self.GetPageSelection()
       
  1153             if old_selected != openedidx:
       
  1154                 if old_selected >= 0:
       
  1155                     self.GetPage(old_selected).ResetBuffer()
       
  1156             for i in xrange(self.GetPageCount()):
       
  1157                 window = self.GetPage(i)
       
  1158                 if window.IsViewing(name):
       
  1159                     self.SetPageSelection(i)
       
  1160                     window.RefreshView()
       
  1161                     window.SetFocus()