confnodes/c_ext/CFileEditor.py
changeset 721 ecf4d203c4d4
parent 720 6be032177e2a
child 722 a94f361fc42e
equal deleted inserted replaced
720:6be032177e2a 721:ecf4d203c4d4
     1 import keyword
       
     2 
       
     3 import wx
       
     4 import wx.grid
       
     5 import wx.stc as stc
       
     6 import wx.lib.buttons
       
     7 
       
     8 from controls import CustomGrid, CustomTable, EditorPanel
       
     9 
       
    10 if wx.Platform == '__WXMSW__':
       
    11     faces = { 'times': 'Times New Roman',
       
    12               'mono' : 'Courier New',
       
    13               'helv' : 'Arial',
       
    14               'other': 'Comic Sans MS',
       
    15               'size' : 10,
       
    16               'size2': 8,
       
    17              }
       
    18 else:
       
    19     faces = { 'times': 'Times',
       
    20               'mono' : 'Courier',
       
    21               'helv' : 'Helvetica',
       
    22               'other': 'new century schoolbook',
       
    23               'size' : 12,
       
    24               'size2': 10,
       
    25              }
       
    26 
       
    27 
       
    28 def AppendMenu(parent, help, id, kind, text):
       
    29     if wx.VERSION >= (2, 6, 0):
       
    30         parent.Append(help=help, id=id, kind=kind, text=text)
       
    31     else:
       
    32         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
    33 
       
    34 
       
    35 [ID_CPPEDITOR,
       
    36 ] = [wx.NewId() for _init_ctrls in range(1)]
       
    37 
       
    38 CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
       
    39     "const", "const_cast", "continue", "default", "delete", "do", "double", 
       
    40     "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
       
    41     "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
       
    42     "namespace", "new", "operator", "private", "protected", "public", "register", 
       
    43     "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
       
    44     "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
       
    45     "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
       
    46     "void", "volatile", "wchar_t", "while"]
       
    47 
       
    48 def GetCursorPos(old, new):
       
    49     old_length = len(old)
       
    50     new_length = len(new)
       
    51     common_length = min(old_length, new_length)
       
    52     i = 0
       
    53     for i in xrange(common_length):
       
    54         if old[i] != new[i]:
       
    55             break
       
    56     if old_length < new_length:
       
    57         if common_length > 0 and old[i] != new[i]:
       
    58             return i + new_length - old_length
       
    59         else:
       
    60             return i + new_length - old_length + 1
       
    61     elif old_length > new_length or i < min(old_length, new_length) - 1:
       
    62         if common_length > 0 and old[i] != new[i]:
       
    63             return i
       
    64         else:
       
    65             return i + 1
       
    66     else:
       
    67         return None
       
    68 
       
    69 class CppEditor(stc.StyledTextCtrl):
       
    70 
       
    71     fold_symbols = 3
       
    72     
       
    73     def __init__(self, parent, name, window, controler):
       
    74         stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
       
    75                  wx.Size(0, 0), 0)
       
    76 
       
    77         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
       
    78         self.SetMarginWidth(1, 25)
       
    79 
       
    80         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
       
    81         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
       
    82 
       
    83         self.SetLexer(stc.STC_LEX_CPP)
       
    84         self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
       
    85 
       
    86         self.SetProperty("fold", "1")
       
    87         self.SetProperty("tab.timmy.whinge.level", "1")
       
    88         self.SetMargins(0,0)
       
    89 
       
    90         self.SetViewWhiteSpace(False)
       
    91         #self.SetBufferedDraw(False)
       
    92         #self.SetViewEOL(True)
       
    93         #self.SetEOLMode(stc.STC_EOL_CRLF)
       
    94         #self.SetUseAntiAliasing(True)
       
    95         
       
    96         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
       
    97         self.SetEdgeColumn(78)
       
    98 
       
    99         # Setup a margin to hold fold markers
       
   100         #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
       
   101         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
       
   102         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
       
   103         self.SetMarginSensitive(2, True)
       
   104         self.SetMarginWidth(2, 12)
       
   105 
       
   106         if self.fold_symbols == 0:
       
   107             # Arrow pointing right for contracted folders, arrow pointing down for expanded
       
   108             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
       
   109             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
       
   110             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
       
   111             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
       
   112             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
       
   113             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
       
   114             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
       
   115             
       
   116         elif self.fold_symbols == 1:
       
   117             # Plus for contracted folders, minus for expanded
       
   118             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
       
   119             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
       
   120             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
       
   121             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
       
   122             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
       
   123             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
       
   124             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
       
   125 
       
   126         elif self.fold_symbols == 2:
       
   127             # Like a flattened tree control using circular headers and curved joins
       
   128             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
       
   129             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
       
   130             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
       
   131             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
       
   132             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
       
   133             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
       
   134             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
       
   135 
       
   136         elif self.fold_symbols == 3:
       
   137             # Like a flattened tree control using square headers
       
   138             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   139             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   140             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
       
   141             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
       
   142             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   143             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   144             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
       
   145 
       
   146 
       
   147         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
       
   148         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
       
   149         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
       
   150 
       
   151         # Make some styles,  The lexer defines what each style is used for, we
       
   152         # just have to define what each style looks like.  This set is adapted from
       
   153         # Scintilla sample property files.
       
   154 
       
   155         # Global default styles for all languages
       
   156         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   157         self.StyleClearAll()  # Reset all to be like the default
       
   158 
       
   159         # Global default styles for all languages
       
   160         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
       
   161         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
       
   162         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
       
   163         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
       
   164         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
       
   165 
       
   166         self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
       
   167         self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
       
   168         self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
       
   169         self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
       
   170         self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
       
   171         self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
       
   172         self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
       
   173         self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
       
   174         self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
       
   175         
       
   176         # register some images for use in the AutoComplete box.
       
   177         #self.RegisterImage(1, images.getSmilesBitmap())
       
   178         self.RegisterImage(1, 
       
   179             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
       
   180         self.RegisterImage(2, 
       
   181             wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
       
   182         self.RegisterImage(3, 
       
   183             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
       
   184 
       
   185         # Indentation size
       
   186         self.SetTabWidth(2)
       
   187         self.SetUseTabs(0)
       
   188 
       
   189         self.Controler = controler
       
   190         self.ParentWindow = window
       
   191         
       
   192         self.DisableEvents = True
       
   193         self.Name = name
       
   194         self.CurrentAction = None
       
   195         
       
   196         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
       
   197 
       
   198         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
       
   199         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
       
   200         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
       
   201     
       
   202     def OnModification(self, event):
       
   203         if not self.DisableEvents:
       
   204             mod_type = event.GetModificationType()
       
   205             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
       
   206                 if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
       
   207                     if self.CurrentAction == None:
       
   208                         self.StartBuffering()
       
   209                     elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
       
   210                         self.Controler.EndBuffering()
       
   211                         self.StartBuffering()
       
   212                     self.CurrentAction = ("Add", event.GetPosition())
       
   213                     wx.CallAfter(self.RefreshModel)
       
   214                 elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
       
   215                     if self.CurrentAction == None:
       
   216                         self.StartBuffering()
       
   217                     elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
       
   218                         self.Controler.EndBuffering()
       
   219                         self.StartBuffering()
       
   220                     self.CurrentAction = ("Delete", event.GetPosition())
       
   221                     wx.CallAfter(self.RefreshModel)
       
   222         event.Skip()
       
   223     
       
   224     def OnDoDrop(self, event):
       
   225         self.ResetBuffer()
       
   226         wx.CallAfter(self.RefreshModel)
       
   227         event.Skip()
       
   228 
       
   229     # Buffer the last model state
       
   230     def RefreshBuffer(self):
       
   231         self.Controler.BufferCFile()
       
   232         if self.ParentWindow is not None:
       
   233             self.ParentWindow.RefreshTitle()
       
   234             self.ParentWindow.RefreshFileMenu()
       
   235             self.ParentWindow.RefreshEditMenu()
       
   236             self.ParentWindow.RefreshPageTitles()
       
   237     
       
   238     def StartBuffering(self):
       
   239         self.Controler.StartBuffering()
       
   240         if self.ParentWindow is not None:
       
   241             self.ParentWindow.RefreshTitle()
       
   242             self.ParentWindow.RefreshFileMenu()
       
   243             self.ParentWindow.RefreshEditMenu()
       
   244             self.ParentWindow.RefreshPageTitles()
       
   245     
       
   246     def ResetBuffer(self):
       
   247         if self.CurrentAction != None:
       
   248             self.Controler.EndBuffering()
       
   249             self.CurrentAction = None
       
   250 
       
   251     def RefreshView(self):
       
   252         self.ResetBuffer()
       
   253         self.DisableEvents = True
       
   254         old_cursor_pos = self.GetCurrentPos()
       
   255         old_text = self.GetText()
       
   256         new_text = self.Controler.GetPartText(self.Name)
       
   257         self.SetText(new_text)
       
   258         new_cursor_pos = GetCursorPos(old_text, new_text)
       
   259         if new_cursor_pos != None:
       
   260             self.GotoPos(new_cursor_pos)
       
   261         else:
       
   262             self.GotoPos(old_cursor_pos)
       
   263         self.ScrollToColumn(0)
       
   264         self.EmptyUndoBuffer()
       
   265         self.DisableEvents = False
       
   266         
       
   267         self.Colourise(0, -1)
       
   268 
       
   269     def DoGetBestSize(self):
       
   270         return self.ParentWindow.GetPanelBestSize()
       
   271 
       
   272     def RefreshModel(self):
       
   273         self.Controler.SetPartText(self.Name, self.GetText())
       
   274 
       
   275     def OnKeyPressed(self, event):
       
   276         if self.CallTipActive():
       
   277             self.CallTipCancel()
       
   278         key = event.GetKeyCode()
       
   279 
       
   280         if key == 32 and event.ControlDown():
       
   281             pos = self.GetCurrentPos()
       
   282 
       
   283             # Tips
       
   284             if event.ShiftDown():
       
   285                 pass
       
   286 ##                self.CallTipSetBackground("yellow")
       
   287 ##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
       
   288 ##                                 'show some suff, maybe parameters..\n\n'
       
   289 ##                                 'fubar(param1, param2)')
       
   290             # Code completion
       
   291             else:
       
   292                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
       
   293 
       
   294                 # Images are specified with a appended "?type"
       
   295                 self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
       
   296         else:
       
   297             event.Skip()
       
   298 
       
   299     def OnKillFocus(self, event):
       
   300         self.AutoCompCancel()
       
   301         event.Skip()
       
   302 
       
   303     def OnUpdateUI(self, evt):
       
   304         # check for matching braces
       
   305         braceAtCaret = -1
       
   306         braceOpposite = -1
       
   307         charBefore = None
       
   308         caretPos = self.GetCurrentPos()
       
   309 
       
   310         if caretPos > 0:
       
   311             charBefore = self.GetCharAt(caretPos - 1)
       
   312             styleBefore = self.GetStyleAt(caretPos - 1)
       
   313 
       
   314         # check before
       
   315         if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
       
   316             braceAtCaret = caretPos - 1
       
   317 
       
   318         # check after
       
   319         if braceAtCaret < 0:
       
   320             charAfter = self.GetCharAt(caretPos)
       
   321             styleAfter = self.GetStyleAt(caretPos)
       
   322 
       
   323             if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
       
   324                 braceAtCaret = caretPos
       
   325 
       
   326         if braceAtCaret >= 0:
       
   327             braceOpposite = self.BraceMatch(braceAtCaret)
       
   328 
       
   329         if braceAtCaret != -1  and braceOpposite == -1:
       
   330             self.BraceBadLight(braceAtCaret)
       
   331         else:
       
   332             self.BraceHighlight(braceAtCaret, braceOpposite)
       
   333             #pt = self.PointFromPosition(braceOpposite)
       
   334             #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
       
   335             #print pt
       
   336             #self.Refresh(False)
       
   337 
       
   338 
       
   339     def OnMarginClick(self, evt):
       
   340         # fold and unfold as needed
       
   341         if evt.GetMargin() == 2:
       
   342             if evt.GetShift() and evt.GetControl():
       
   343                 self.FoldAll()
       
   344             else:
       
   345                 lineClicked = self.LineFromPosition(evt.GetPosition())
       
   346 
       
   347                 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
       
   348                     if evt.GetShift():
       
   349                         self.SetFoldExpanded(lineClicked, True)
       
   350                         self.Expand(lineClicked, True, True, 1)
       
   351                     elif evt.GetControl():
       
   352                         if self.GetFoldExpanded(lineClicked):
       
   353                             self.SetFoldExpanded(lineClicked, False)
       
   354                             self.Expand(lineClicked, False, True, 0)
       
   355                         else:
       
   356                             self.SetFoldExpanded(lineClicked, True)
       
   357                             self.Expand(lineClicked, True, True, 100)
       
   358                     else:
       
   359                         self.ToggleFold(lineClicked)
       
   360 
       
   361 
       
   362     def FoldAll(self):
       
   363         lineCount = self.GetLineCount()
       
   364         expanding = True
       
   365 
       
   366         # find out if we are folding or unfolding
       
   367         for lineNum in range(lineCount):
       
   368             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
       
   369                 expanding = not self.GetFoldExpanded(lineNum)
       
   370                 break
       
   371 
       
   372         lineNum = 0
       
   373 
       
   374         while lineNum < lineCount:
       
   375             level = self.GetFoldLevel(lineNum)
       
   376             if level & stc.STC_FOLDLEVELHEADERFLAG and \
       
   377                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
       
   378 
       
   379                 if expanding:
       
   380                     self.SetFoldExpanded(lineNum, True)
       
   381                     lineNum = self.Expand(lineNum, True)
       
   382                     lineNum = lineNum - 1
       
   383                 else:
       
   384                     lastChild = self.GetLastChild(lineNum, -1)
       
   385                     self.SetFoldExpanded(lineNum, False)
       
   386 
       
   387                     if lastChild > lineNum:
       
   388                         self.HideLines(lineNum+1, lastChild)
       
   389 
       
   390             lineNum = lineNum + 1
       
   391 
       
   392 
       
   393 
       
   394     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
       
   395         lastChild = self.GetLastChild(line, level)
       
   396         line = line + 1
       
   397 
       
   398         while line <= lastChild:
       
   399             if force:
       
   400                 if visLevels > 0:
       
   401                     self.ShowLines(line, line)
       
   402                 else:
       
   403                     self.HideLines(line, line)
       
   404             else:
       
   405                 if doExpand:
       
   406                     self.ShowLines(line, line)
       
   407 
       
   408             if level == -1:
       
   409                 level = self.GetFoldLevel(line)
       
   410 
       
   411             if level & stc.STC_FOLDLEVELHEADERFLAG:
       
   412                 if force:
       
   413                     if visLevels > 1:
       
   414                         self.SetFoldExpanded(line, True)
       
   415                     else:
       
   416                         self.SetFoldExpanded(line, False)
       
   417 
       
   418                     line = self.Expand(line, doExpand, force, visLevels-1)
       
   419 
       
   420                 else:
       
   421                     if doExpand and self.GetFoldExpanded(line):
       
   422                         line = self.Expand(line, True, force, visLevels-1)
       
   423                     else:
       
   424                         line = self.Expand(line, False, force, visLevels-1)
       
   425             else:
       
   426                 line = line + 1
       
   427 
       
   428         return line
       
   429 
       
   430     def Cut(self):
       
   431         self.ResetBuffer()
       
   432         self.DisableEvents = True
       
   433         self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
       
   434         self.DisableEvents = False
       
   435         self.RefreshModel()
       
   436         self.RefreshBuffer()
       
   437     
       
   438     def Copy(self):
       
   439         self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
       
   440     
       
   441     def Paste(self):
       
   442         self.ResetBuffer()
       
   443         self.DisableEvents = True
       
   444         self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
       
   445         self.DisableEvents = False
       
   446         self.RefreshModel()
       
   447         self.RefreshBuffer()
       
   448 
       
   449 
       
   450 #-------------------------------------------------------------------------------
       
   451 #                         Helper for VariablesGrid values
       
   452 #-------------------------------------------------------------------------------
       
   453 
       
   454 class VariablesTable(CustomTable):
       
   455     
       
   456     def GetValue(self, row, col):
       
   457         if row < self.GetNumberRows():
       
   458             if col == 0:
       
   459                 return row + 1
       
   460             else:
       
   461                 return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
       
   462     
       
   463     def _updateColAttrs(self, grid):
       
   464         """
       
   465         wxGrid -> update the column attributes to add the
       
   466         appropriate renderer given the column name.
       
   467 
       
   468         Otherwise default to the default renderer.
       
   469         """
       
   470         
       
   471         typelist = None
       
   472         accesslist = None
       
   473         for row in range(self.GetNumberRows()):
       
   474             for col in range(self.GetNumberCols()):
       
   475                 editor = None
       
   476                 renderer = None
       
   477                 colname = self.GetColLabelValue(col, False)
       
   478                 
       
   479                 if colname == "Name":
       
   480                     editor = wx.grid.GridCellTextEditor()
       
   481                 elif colname == "Class":
       
   482                     editor = wx.grid.GridCellChoiceEditor()
       
   483                     editor.SetParameters("input,memory,output")
       
   484                 elif colname == "Type":
       
   485                     pass
       
   486                 else:
       
   487                     grid.SetReadOnly(row, col, True)
       
   488                 
       
   489                 grid.SetCellEditor(row, col, editor)
       
   490                 grid.SetCellRenderer(row, col, renderer)
       
   491                 
       
   492                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
       
   493             self.ResizeRow(grid, row)
       
   494     
       
   495 
       
   496 [ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
       
   497  ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, 
       
   498  ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
       
   499 ] = [wx.NewId() for _init_ctrls in range(6)]
       
   500 
       
   501 class VariablesEditor(wx.Panel):
       
   502     
       
   503     if wx.VERSION < (2, 6, 0):
       
   504         def Bind(self, event, function, id = None):
       
   505             if id is not None:
       
   506                 event(self, id, function)
       
   507             else:
       
   508                 event(self, function)
       
   509     
       
   510     def _init_coll_MainSizer_Growables(self, parent):
       
   511         parent.AddGrowableCol(0)
       
   512         parent.AddGrowableRow(0)
       
   513 
       
   514     def _init_coll_MainSizer_Items(self, parent):
       
   515         parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
       
   516         parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
       
   517 
       
   518     def _init_coll_ButtonsSizer_Growables(self, parent):
       
   519         parent.AddGrowableCol(0)
       
   520         parent.AddGrowableRow(0)
       
   521 
       
   522     def _init_coll_ButtonsSizer_Items(self, parent):
       
   523         parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
       
   524         parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
       
   525         parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
       
   526         parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
       
   527 
       
   528     def _init_sizers(self):
       
   529         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
       
   530         self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
   531         
       
   532         self._init_coll_MainSizer_Growables(self.MainSizer)
       
   533         self._init_coll_MainSizer_Items(self.MainSizer)
       
   534         self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
       
   535         self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
       
   536         
       
   537         self.SetSizer(self.MainSizer)
       
   538 
       
   539     def _init_ctrls(self, prnt):
       
   540         wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
       
   541               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
   542         
       
   543         self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
       
   544               name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
       
   545               size=wx.Size(-1, -1), style=wx.VSCROLL)
       
   546         if wx.VERSION >= (2, 5, 0):
       
   547             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
       
   548             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
       
   549             self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
       
   550         else:
       
   551             wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
       
   552             wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
       
   553             wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
       
   554         
       
   555         self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
       
   556               name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
       
   557               size=wx.Size(122, 32), style=0)
       
   558         
       
   559         self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
       
   560               name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
       
   561               size=wx.Size(122, 32), style=0)
       
   562         
       
   563         self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
       
   564               name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
       
   565               size=wx.Size(32, 32), style=0)
       
   566         
       
   567         self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
       
   568               name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
       
   569               size=wx.Size(32, 32), style=0)
       
   570         
       
   571         self._init_sizers()
       
   572 
       
   573     def __init__(self, parent, window, controler):
       
   574         self._init_ctrls(parent)
       
   575         
       
   576         self.ParentWindow = window
       
   577         self.Controler = controler
       
   578         
       
   579         self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
       
   580         self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
       
   581         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
       
   582         self.ColSizes = [40, 200, 150, 150]
       
   583         self.VariablesGrid.SetTable(self.Table)
       
   584         self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
       
   585                                        "Delete": self.DeleteVariableButton,
       
   586                                        "Up": self.UpVariableButton,
       
   587                                        "Down": self.DownVariableButton})
       
   588         
       
   589         def _AddVariable(new_row):
       
   590             self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
       
   591             self.RefreshModel()
       
   592             self.RefreshView()
       
   593             return new_row
       
   594         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
       
   595         
       
   596         def _DeleteVariable(row):
       
   597             self.Table.RemoveRow(row)
       
   598             self.RefreshModel()
       
   599             self.RefreshView()
       
   600         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
       
   601         
       
   602         def _MoveVariable(row, move):
       
   603             new_row = self.Table.MoveRow(row, move)
       
   604             if new_row != row:
       
   605                 self.RefreshModel()
       
   606                 self.RefreshView()
       
   607             return new_row
       
   608         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
       
   609         
       
   610         self.VariablesGrid.SetRowLabelSize(0)
       
   611         for col in range(self.Table.GetNumberCols()):
       
   612             attr = wx.grid.GridCellAttr()
       
   613             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
       
   614             self.VariablesGrid.SetColAttr(col, attr)
       
   615             self.VariablesGrid.SetColSize(col, self.ColSizes[col])
       
   616         self.Table.ResetView(self.VariablesGrid)
       
   617 
       
   618     def RefreshModel(self):
       
   619         self.Controler.SetVariables(self.Table.GetData())
       
   620         self.RefreshBuffer()
       
   621         
       
   622     # Buffer the last model state
       
   623     def RefreshBuffer(self):
       
   624         self.Controler.BufferCFile()
       
   625         self.ParentWindow.RefreshTitle()
       
   626         self.ParentWindow.RefreshFileMenu()
       
   627         self.ParentWindow.RefreshEditMenu()
       
   628         self.ParentWindow.RefreshPageTitles()
       
   629 
       
   630     def RefreshView(self):
       
   631         self.Table.SetData(self.Controler.GetVariables())
       
   632         self.Table.ResetView(self.VariablesGrid)
       
   633         self.VariablesGrid.RefreshButtons()
       
   634     
       
   635     def DoGetBestSize(self):
       
   636         return self.ParentWindow.GetPanelBestSize()
       
   637     
       
   638     def OnVariablesGridCellChange(self, event):
       
   639         self.RefreshModel()
       
   640         wx.CallAfter(self.RefreshView)
       
   641         event.Skip()
       
   642 
       
   643     def OnVariablesGridEditorShown(self, event):
       
   644         row, col = event.GetRow(), event.GetCol() 
       
   645         if self.Table.GetColLabelValue(col) == "Type":
       
   646             type_menu = wx.Menu(title='')
       
   647             base_menu = wx.Menu(title='')
       
   648             for base_type in self.Controler.GetBaseTypes():
       
   649                 new_id = wx.NewId()
       
   650                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
       
   651                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
       
   652             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
       
   653             datatype_menu = wx.Menu(title='')
       
   654             for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
       
   655                 new_id = wx.NewId()
       
   656                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
       
   657                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
       
   658             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
       
   659             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
       
   660             
       
   661             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
       
   662             type_menu.Destroy()
       
   663             event.Veto()
       
   664         else:
       
   665             event.Skip()
       
   666 
       
   667     def GetVariableTypeFunction(self, base_type):
       
   668         def VariableTypeFunction(event):
       
   669             row = self.VariablesGrid.GetGridCursorRow()
       
   670             self.Table.SetValueByName(row, "Type", base_type)
       
   671             self.Table.ResetView(self.VariablesGrid)
       
   672             self.RefreshModel()
       
   673             self.RefreshView()
       
   674             event.Skip()
       
   675         return VariableTypeFunction
       
   676 
       
   677     def OnVariablesGridCellLeftClick(self, event):
       
   678         if event.GetCol() == 0:
       
   679             row = event.GetRow()
       
   680             num = 0
       
   681             if self.Table.GetValueByName(row, "Class") == "input":
       
   682                 dir = "%I"
       
   683                 for i in xrange(row):
       
   684                     if self.Table.GetValueByName(i, "Class") == "input":
       
   685                         num += 1
       
   686             elif self.Table.GetValueByName(row, "Class") == "memory":
       
   687                 dir = "%M"
       
   688                 for i in xrange(row):
       
   689                     if self.Table.GetValueByName(i, "Class") == "memory":
       
   690                         num += 1
       
   691             else:
       
   692                 dir = "%Q"
       
   693                 for i in xrange(row):
       
   694                     if self.Table.GetValueByName(i, "Class") == "output":
       
   695                         num += 1
       
   696             data_type = self.Table.GetValueByName(row, "Type")
       
   697             var_name = self.Table.GetValueByName(row, "Name")
       
   698             base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
       
   699             location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
       
   700             data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
       
   701             dragSource = wx.DropSource(self.VariablesGrid)
       
   702             dragSource.SetData(data)
       
   703             dragSource.DoDragDrop()
       
   704         event.Skip()
       
   705     
       
   706 
       
   707 #-------------------------------------------------------------------------------
       
   708 #                          SVGUIEditor Main Frame Class
       
   709 #-------------------------------------------------------------------------------
       
   710 
       
   711 CFILE_PARTS = [
       
   712     ("Includes", CppEditor), 
       
   713     ("Variables", VariablesEditor), 
       
   714     ("Globals", CppEditor), 
       
   715     ("Init", CppEditor), 
       
   716     ("CleanUp", CppEditor), 
       
   717     ("Retrieve", CppEditor), 
       
   718     ("Publish", CppEditor),
       
   719 ]
       
   720 
       
   721 #----------------------------------------------------------------------
       
   722 # different icons for the collapsed/expanded states.
       
   723 # Taken from standard Windows XP collapsed/expanded states.
       
   724 #----------------------------------------------------------------------
       
   725 
       
   726 def GetCollapsedIconData():
       
   727     return \
       
   728 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
       
   729 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
       
   730 \x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
       
   731 \xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
       
   732 \xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
       
   733 H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
       
   734 \xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
       
   735 \xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
       
   736 \x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
       
   737 \xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
       
   738 zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
       
   739 \x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
       
   740 ~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
       
   741 \x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
       
   742 \xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
       
   743 \xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
       
   744 0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
       
   745 \x00\x00\x00IEND\xaeB`\x82' 
       
   746 
       
   747 def GetCollapsedIconBitmap():
       
   748     return wx.BitmapFromImage(GetCollapsedIconImage())
       
   749 
       
   750 def GetCollapsedIconImage():
       
   751     import cStringIO
       
   752     stream = cStringIO.StringIO(GetCollapsedIconData())
       
   753     return wx.ImageFromStream(stream)
       
   754 
       
   755 #----------------------------------------------------------------------
       
   756 def GetExpandedIconData():
       
   757     return \
       
   758 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
       
   759 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
       
   760 \x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
       
   761 \xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
       
   762 \x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
       
   763 \xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
       
   764 \x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
       
   765 \x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
       
   766 \x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
       
   767 \xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
       
   768 \x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
       
   769 \x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
       
   770 \xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
       
   771 \xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
       
   772 \x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\
       
   773 [\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\
       
   774 \xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\
       
   775 \x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
       
   776 \xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
       
   777 `\x82' 
       
   778 
       
   779 def GetExpandedIconBitmap():
       
   780     return wx.BitmapFromImage(GetExpandedIconImage())
       
   781 
       
   782 def GetExpandedIconImage():
       
   783     import cStringIO
       
   784     stream = cStringIO.StringIO(GetExpandedIconData())
       
   785     return wx.ImageFromStream(stream)
       
   786 
       
   787 class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
       
   788     
       
   789     def GetBackgroundBrush(self, dc):
       
   790         colBg = self.GetBackgroundColour()
       
   791         brush = wx.Brush(colBg, wx.SOLID)
       
   792         if self.style & wx.BORDER_NONE:
       
   793             myAttr = self.GetDefaultAttributes()
       
   794             parAttr = self.GetParent().GetDefaultAttributes()
       
   795             myDef = colBg == myAttr.colBg
       
   796             parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
       
   797             if myDef and parDef:
       
   798                 if wx.Platform == "__WXMAC__":
       
   799                     brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
       
   800                 elif wx.Platform == "__WXMSW__":
       
   801                     if self.DoEraseBackground(dc):
       
   802                         brush = None
       
   803             elif myDef and not parDef:
       
   804                 colBg = self.GetParent().GetBackgroundColour()
       
   805                 brush = wx.Brush(colBg, wx.SOLID)
       
   806         return brush
       
   807     
       
   808     def DrawLabel(self, dc, width, height, dx=0, dy=0):
       
   809         bmp = self.bmpLabel
       
   810         if bmp is not None:     # if the bitmap is used
       
   811             if self.bmpDisabled and not self.IsEnabled():
       
   812                 bmp = self.bmpDisabled
       
   813             if self.bmpFocus and self.hasFocus:
       
   814                 bmp = self.bmpFocus
       
   815             if self.bmpSelected and not self.up:
       
   816                 bmp = self.bmpSelected
       
   817             bw,bh = bmp.GetWidth(), bmp.GetHeight()
       
   818             hasMask = bmp.GetMask() is not None
       
   819         else:
       
   820             bw = bh = 0     # no bitmap -> size is zero
       
   821         
       
   822         dc.SetFont(self.GetFont())
       
   823         if self.IsEnabled():
       
   824             dc.SetTextForeground(self.GetForegroundColour())
       
   825         else:
       
   826             dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
       
   827 
       
   828         label = self.GetLabel()
       
   829         tw, th = dc.GetTextExtent(label)        # size of text
       
   830         
       
   831         if bmp is not None:
       
   832             dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
       
   833         
       
   834         dc.DrawText(label, 2, (height-th)/2)      # draw the text
       
   835 
       
   836         dc.SetPen(wx.Pen(self.GetForegroundColour()))
       
   837         dc.SetBrush(wx.TRANSPARENT_BRUSH)
       
   838         dc.DrawRectangle(0, 0, width, height)
       
   839 
       
   840 [ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, 
       
   841  ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED, 
       
   842 ] = [wx.NewId() for _init_ctrls in range(4)]
       
   843 
       
   844 class CFileEditor(EditorPanel):
       
   845     
       
   846     def _init_Editor(self, prnt):
       
   847         self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), 
       
   848                 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
   849         
       
   850         self.Panels = {}
       
   851         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
       
   852         self.MainSizer.AddGrowableCol(0)
       
   853         
       
   854         for idx, (name, panel_class) in enumerate(CFILE_PARTS):
       
   855             button_id = wx.NewId()
       
   856             button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, 
       
   857                   label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
       
   858                   size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
       
   859             button.SetBitmapSelected(GetExpandedIconBitmap())
       
   860             button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
       
   861             self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
       
   862             
       
   863             if panel_class == VariablesEditor:
       
   864                 panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
       
   865             else:
       
   866                 panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
       
   867             self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
       
   868             panel.Hide()
       
   869             
       
   870             self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
       
   871         
       
   872         self.Spacer = wx.Panel(self.Editor, -1)
       
   873         self.SpacerExpanded = True
       
   874         self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
       
   875         
       
   876         self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
       
   877         
       
   878         self.Editor.SetSizer(self.MainSizer)
       
   879         
       
   880     def __init__(self, parent, controler, window):
       
   881         EditorPanel.__init__(self, parent, "", window, controler)
       
   882         
       
   883         img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
       
   884         self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
       
   885         
       
   886     def __del__(self):
       
   887         self.Controler.OnCloseEditor(self)
       
   888     
       
   889     def GetTitle(self):
       
   890         fullname = self.Controler.CTNFullName()
       
   891         if not self.Controler.CFileIsSaved():
       
   892             return "~%s~" % fullname
       
   893         return fullname
       
   894     
       
   895     def GetBufferState(self):
       
   896         return self.Controler.GetBufferState()
       
   897         
       
   898     def Undo(self):
       
   899         self.Controler.LoadPrevious()
       
   900         self.RefreshView()
       
   901             
       
   902     def Redo(self):
       
   903         self.Controler.LoadNext()
       
   904         self.RefreshView()
       
   905     
       
   906     def HasNoModel(self):
       
   907         return False
       
   908 
       
   909     def RefreshView(self):
       
   910         for infos in self.Panels.itervalues():
       
   911             infos["panel"].RefreshView()
       
   912 
       
   913     def GenPanelButtonCallback(self, name):
       
   914         def PanelButtonCallback(event):
       
   915             self.TogglePanel(name)
       
   916         return PanelButtonCallback
       
   917 
       
   918     def ExpandPanel(self, name):
       
   919         infos = self.Panels.get(name, None)
       
   920         if infos is not None and not infos["expanded"]:
       
   921             infos["expanded"] = True
       
   922             infos["button"].SetToggle(True)
       
   923             infos["panel"].Show()
       
   924             self.MainSizer.AddGrowableRow(infos["row"])
       
   925         
       
   926             self.RefreshSizerLayout()
       
   927     
       
   928     def CollapsePanel(self, name):
       
   929         infos = self.Panels.get(name, None)
       
   930         if infos is not None and infos["expanded"]:
       
   931             infos["expanded"] = False
       
   932             infos["button"].SetToggle(False)
       
   933             infos["panel"].Hide()
       
   934             self.MainSizer.RemoveGrowableRow(infos["row"])
       
   935         
       
   936             self.RefreshSizerLayout()
       
   937         
       
   938     def TogglePanel(self, name):
       
   939         infos = self.Panels.get(name, None)
       
   940         if infos is not None:
       
   941             infos["expanded"] = not infos["expanded"]
       
   942             infos["button"].SetToggle(infos["expanded"])
       
   943             if infos["expanded"]:
       
   944                 infos["panel"].Show()
       
   945                 self.MainSizer.AddGrowableRow(infos["row"])
       
   946             else:
       
   947                 infos["panel"].Hide()
       
   948                 self.MainSizer.RemoveGrowableRow(infos["row"])
       
   949             
       
   950             self.RefreshSizerLayout()
       
   951     
       
   952     def RefreshSizerLayout(self):
       
   953         expand_spacer = True
       
   954         for infos in self.Panels.itervalues():
       
   955             expand_spacer = expand_spacer and not infos["expanded"]
       
   956         
       
   957         if self.SpacerExpanded != expand_spacer:
       
   958             self.SpacerExpanded = expand_spacer
       
   959             if expand_spacer:
       
   960                 self.Spacer.Show()
       
   961                 self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
       
   962             else:
       
   963                 self.Spacer.Hide()
       
   964                 self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
       
   965         
       
   966         self.MainSizer.Layout()
       
   967