editors/CodeFileEditor.py
changeset 1096 c9ace6a881c9
parent 1095 a73fde048749
child 1097 233681f2a00e
equal deleted inserted replaced
1095:a73fde048749 1096:c9ace6a881c9
     1 import keyword
     1 import re
     2 
     2 
     3 import wx
     3 import wx
     4 import wx.grid
     4 import wx.grid
     5 import wx.stc as stc
     5 import wx.stc as stc
     6 import wx.lib.buttons
     6 import wx.lib.buttons
     7 
     7 
     8 from controls import CustomGrid, CustomTable
     8 from controls import CustomGrid, CustomTable
     9 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
     9 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
    10 from util.BitmapLibrary import GetBitmap
    10 from util.BitmapLibrary import GetBitmap
    11 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos
    11 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos
    12 
    12 
    13 def AppendMenu(parent, help, id, kind, text):
    13 SECTIONS_NAMES = ["Includes", "Globals", "Init",
    14     if wx.VERSION >= (2, 6, 0):
    14                   "CleanUp", "Retrieve", "Publish"]
    15         parent.Append(help=help, id=id, kind=kind, text=text)
    15 
    16     else:
    16 class CodeEditor(CustomStyledTextCtrl):
    17         parent.Append(helpString=help, id=id, kind=kind, item=text)
    17     
    18 
    18     KEYWORDS = []
    19 
    19     COMMENT_HEADER = ""
    20 [ID_CPPEDITOR,
    20 
    21 ] = [wx.NewId() for _init_ctrls in range(1)]
    21     def __init__(self, parent, window, controler):
    22 
    22         CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition, 
    23 CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
       
    24     "const", "const_cast", "continue", "default", "delete", "do", "double", 
       
    25     "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
       
    26     "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
       
    27     "namespace", "new", "operator", "private", "protected", "public", "register", 
       
    28     "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
       
    29     "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
       
    30     "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
       
    31     "void", "volatile", "wchar_t", "while"]
       
    32 
       
    33 class CppEditor(CustomStyledTextCtrl):
       
    34 
       
    35     fold_symbols = 3
       
    36     
       
    37     def __init__(self, parent, name, window, controler):
       
    38         CustomStyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
       
    39                  wx.Size(-1, 300), 0)
    23                  wx.Size(-1, 300), 0)
    40 
    24 
    41         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
    25         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
    42         self.SetMarginWidth(1, 25)
    26         self.SetMarginWidth(1, 25)
    43 
    27 
    44         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
    28         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
    45         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
    29         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
    46 
       
    47         self.SetLexer(stc.STC_LEX_CPP)
       
    48         self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
       
    49 
    30 
    50         self.SetProperty("fold", "1")
    31         self.SetProperty("fold", "1")
    51         self.SetProperty("tab.timmy.whinge.level", "1")
    32         self.SetProperty("tab.timmy.whinge.level", "1")
    52         self.SetMargins(0,0)
    33         self.SetMargins(0,0)
    53 
    34 
    54         self.SetViewWhiteSpace(False)
    35         self.SetViewWhiteSpace(False)
    55         #self.SetBufferedDraw(False)
       
    56         #self.SetViewEOL(True)
       
    57         #self.SetEOLMode(stc.STC_EOL_CRLF)
       
    58         #self.SetUseAntiAliasing(True)
       
    59         
    36         
    60         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    37         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
    61         self.SetEdgeColumn(78)
    38         self.SetEdgeColumn(78)
    62 
    39 
    63         # Setup a margin to hold fold markers
    40         # Setup a margin to hold fold markers
    64         #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
       
    65         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
    41         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
    66         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
    42         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
    67         self.SetMarginSensitive(2, True)
    43         self.SetMarginSensitive(2, True)
    68         self.SetMarginWidth(2, 12)
    44         self.SetMarginWidth(2, 12)
    69 
    45 
    70         if self.fold_symbols == 0:
    46         # Like a flattened tree control using square headers
    71             # Arrow pointing right for contracted folders, arrow pointing down for expanded
    47         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
    72             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
    48         self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
    73             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
    49         self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
    74             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
    50         self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
    75             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
    51         self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
    76             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
    52         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
    77             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
    53         self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
    78             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
    54         
    79             
       
    80         elif self.fold_symbols == 1:
       
    81             # Plus for contracted folders, minus for expanded
       
    82             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
       
    83             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
       
    84             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
       
    85             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
       
    86             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
       
    87             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
       
    88             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
       
    89 
       
    90         elif self.fold_symbols == 2:
       
    91             # Like a flattened tree control using circular headers and curved joins
       
    92             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
       
    93             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
       
    94             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
       
    95             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
       
    96             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
       
    97             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
       
    98             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
       
    99 
       
   100         elif self.fold_symbols == 3:
       
   101             # Like a flattened tree control using square headers
       
   102             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
       
   103             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
       
   104             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
       
   105             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
       
   106             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
       
   107             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
       
   108             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
       
   109 
       
   110 
       
   111         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
    55         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
   112         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
    56         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
   113         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
    57         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
   114 
    58 
   115         # Make some styles,  The lexer defines what each style is used for, we
    59         # Make some styles,  The lexer defines what each style is used for, we
   124         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
    68         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
   125         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces)
    69         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size)d" % faces)
   126         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
    70         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
   127         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
    71         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
   128         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
    72         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
   129 
       
   130         self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060,size:%(size)d' % faces)
       
   131         self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060,size:%(size)d' % faces)
       
   132         self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060,size:%(size)d' % faces)
       
   133         self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE,size:%(size)d' % faces)
       
   134         self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056,size:%(size)d' % faces)
       
   135         self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff,size:%(size)d' % faces)
       
   136         self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056,size:%(size)d' % faces)
       
   137         self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold,size:%(size)d' % faces)
       
   138         self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF,size:%(size)d' % faces)
       
   139         
    73         
   140         # register some images for use in the AutoComplete box.
    74         # register some images for use in the AutoComplete box.
   141         #self.RegisterImage(1, images.getSmilesBitmap())
    75         #self.RegisterImage(1, images.getSmilesBitmap())
   142         self.RegisterImage(1, 
    76         self.RegisterImage(1, 
   143             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
    77             wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
   147             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
    81             wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
   148 
    82 
   149         # Indentation size
    83         # Indentation size
   150         self.SetTabWidth(2)
    84         self.SetTabWidth(2)
   151         self.SetUseTabs(0)
    85         self.SetUseTabs(0)
   152 
    86         
       
    87         self.SetCodeLexer()
       
    88         self.SetKeyWords(0, " ".join(self.KEYWORDS))
       
    89         
   153         self.Controler = controler
    90         self.Controler = controler
   154         self.ParentWindow = window
    91         self.ParentWindow = window
   155         
    92         
   156         self.DisableEvents = True
    93         self.DisableEvents = True
   157         self.Name = name
       
   158         self.CurrentAction = None
    94         self.CurrentAction = None
   159         
    95         
       
    96         self.SectionsComments = {}
       
    97         for section in SECTIONS_NAMES:
       
    98             section_start_comment = "%s %s section\n" % (self.COMMENT_HEADER, section)
       
    99             section_end_comment = "\n%s End %s section\n\n" % (self.COMMENT_HEADER, section)
       
   100             self.SectionsComments[section] = {
       
   101                  "start": section_start_comment,
       
   102                  "end": section_end_comment,
       
   103                  "pattern": re.compile(section_start_comment + 
       
   104                                        "(.*)" + 
       
   105                                        section_end_comment,
       
   106                                        re.DOTALL)
       
   107             }
       
   108         
   160         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
   109         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
   161 
   110 
   162         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
   111         self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop)
   163         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   112         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
   164         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
   113         self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification)
       
   114     
       
   115     def SetCodeLexer(self):
       
   116         pass
   165     
   117     
   166     def OnModification(self, event):
   118     def OnModification(self, event):
   167         if not self.DisableEvents:
   119         if not self.DisableEvents:
   168             mod_type = event.GetModificationType()
   120             mod_type = event.GetModificationType()
   169             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
   121             if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
   190         wx.CallAfter(self.RefreshModel)
   142         wx.CallAfter(self.RefreshModel)
   191         event.Skip()
   143         event.Skip()
   192 
   144 
   193     # Buffer the last model state
   145     # Buffer the last model state
   194     def RefreshBuffer(self):
   146     def RefreshBuffer(self):
   195         self.Controler.BufferCFile()
   147         self.Controler.BufferCodeFile()
   196         if self.ParentWindow is not None:
   148         if self.ParentWindow is not None:
   197             self.ParentWindow.RefreshTitle()
   149             self.ParentWindow.RefreshTitle()
   198             self.ParentWindow.RefreshFileMenu()
   150             self.ParentWindow.RefreshFileMenu()
   199             self.ParentWindow.RefreshEditMenu()
   151             self.ParentWindow.RefreshEditMenu()
   200             self.ParentWindow.RefreshPageTitles()
   152             self.ParentWindow.RefreshPageTitles()
   210     def ResetBuffer(self):
   162     def ResetBuffer(self):
   211         if self.CurrentAction != None:
   163         if self.CurrentAction != None:
   212             self.Controler.EndBuffering()
   164             self.Controler.EndBuffering()
   213             self.CurrentAction = None
   165             self.CurrentAction = None
   214 
   166 
       
   167     def GetCodeText(self):
       
   168         parts = self.Controler.GetTextParts()
       
   169         text = ""
       
   170         for section in SECTIONS_NAMES:
       
   171             section_comments = self.SectionsComments[section]
       
   172             text += section_comments["start"]
       
   173             text += parts[section]
       
   174             text += section_comments["end"]
       
   175         return text
       
   176 
   215     def RefreshView(self):
   177     def RefreshView(self):
   216         self.ResetBuffer()
   178         self.ResetBuffer()
   217         self.DisableEvents = True
   179         self.DisableEvents = True
   218         old_cursor_pos = self.GetCurrentPos()
   180         old_cursor_pos = self.GetCurrentPos()
   219         line = self.GetFirstVisibleLine()
   181         line = self.GetFirstVisibleLine()
   220         column = self.GetXOffset()
   182         column = self.GetXOffset()
   221         old_text = self.GetText()
   183         old_text = self.GetText()
   222         new_text = self.Controler.GetPartText(self.Name)
   184         new_text = self.GetCodeText()
   223         self.SetText(new_text)
   185         self.SetText(new_text)
   224         if old_text != new_text:
   186         if old_text != new_text:
   225             new_cursor_pos = GetCursorPos(old_text, new_text)
   187             new_cursor_pos = GetCursorPos(old_text, new_text)
   226             self.LineScroll(column, line)
   188             self.LineScroll(column, line)
   227             if new_cursor_pos != None:
   189             if new_cursor_pos != None:
   235 
   197 
   236     def DoGetBestSize(self):
   198     def DoGetBestSize(self):
   237         return self.ParentWindow.GetPanelBestSize()
   199         return self.ParentWindow.GetPanelBestSize()
   238 
   200 
   239     def RefreshModel(self):
   201     def RefreshModel(self):
   240         self.Controler.SetPartText(self.Name, self.GetText())
   202         text = self.GetText()
       
   203         parts = {}
       
   204         for section in SECTIONS_NAMES:
       
   205             section_comments = self.SectionsComments[section]
       
   206             result = section_comments["pattern"].search(text)
       
   207             if result is not None:
       
   208                 parts[section] = result.group(1)
       
   209             else:
       
   210                 parts[section] = ""
       
   211         self.Controler.SetTextParts(parts)
   241 
   212 
   242     def OnKeyPressed(self, event):
   213     def OnKeyPressed(self, event):
   243         if self.CallTipActive():
   214         if self.CallTipActive():
   244             self.CallTipCancel()
   215             self.CallTipCancel()
   245         key = event.GetKeyCode()
   216         key = event.GetKeyCode()
   248             pos = self.GetCurrentPos()
   219             pos = self.GetCurrentPos()
   249 
   220 
   250             # Tips
   221             # Tips
   251             if event.ShiftDown():
   222             if event.ShiftDown():
   252                 pass
   223                 pass
   253 ##                self.CallTipSetBackground("yellow")
       
   254 ##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
       
   255 ##                                 'show some suff, maybe parameters..\n\n'
       
   256 ##                                 'fubar(param1, param2)')
       
   257             # Code completion
   224             # Code completion
   258             else:
   225             else:
   259                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
   226                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
   260 
   227 
   261                 # Images are specified with a appended "?type"
   228                 # Images are specified with a appended "?type"
   262                 self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
   229                 self.AutoCompShow(0, " ".join([word + "?1" for word in self.KEYWORDS]))
   263         else:
   230         else:
   264             event.Skip()
   231             event.Skip()
   265 
   232 
   266     def OnKillFocus(self, event):
   233     def OnKillFocus(self, event):
   267         self.AutoCompCancel()
   234         self.AutoCompCancel()
   295 
   262 
   296         if braceAtCaret != -1  and braceOpposite == -1:
   263         if braceAtCaret != -1  and braceOpposite == -1:
   297             self.BraceBadLight(braceAtCaret)
   264             self.BraceBadLight(braceAtCaret)
   298         else:
   265         else:
   299             self.BraceHighlight(braceAtCaret, braceOpposite)
   266             self.BraceHighlight(braceAtCaret, braceOpposite)
   300             #pt = self.PointFromPosition(braceOpposite)
       
   301             #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
       
   302             #print pt
       
   303             #self.Refresh(False)
       
   304 
       
   305 
   267 
   306     def OnMarginClick(self, evt):
   268     def OnMarginClick(self, evt):
   307         # fold and unfold as needed
   269         # fold and unfold as needed
   308         if evt.GetMargin() == 2:
   270         if evt.GetMargin() == 2:
   309             if evt.GetShift() and evt.GetControl():
   271             if evt.GetShift() and evt.GetControl():
   441             for col in range(self.GetNumberCols()):
   403             for col in range(self.GetNumberCols()):
   442                 editor = None
   404                 editor = None
   443                 renderer = None
   405                 renderer = None
   444                 colname = self.GetColLabelValue(col, False)
   406                 colname = self.GetColLabelValue(col, False)
   445                 
   407                 
   446                 if colname == "Name":
   408                 if colname in ["Name", "Initial"]:
   447                     editor = wx.grid.GridCellTextEditor()
   409                     editor = wx.grid.GridCellTextEditor()
   448                 elif colname == "Class":
   410                 elif colname == "Class":
   449                     editor = wx.grid.GridCellChoiceEditor()
   411                     editor = wx.grid.GridCellChoiceEditor()
   450                     editor.SetParameters("input,memory,output")
   412                     editor.SetParameters("input,memory,output")
   451                 elif colname == "Type":
   413                 elif colname == "Type":
   492         self.SetSizer(main_sizer)
   454         self.SetSizer(main_sizer)
   493                 
   455                 
   494         self.ParentWindow = window
   456         self.ParentWindow = window
   495         self.Controler = controler
   457         self.Controler = controler
   496         
   458         
   497         self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
   459         self.VariablesDefaultValue = {"Name" : "", "Type" : "", "Initial": ""}
   498         self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
   460         self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
   499         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   461         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   500         self.ColSizes = [40, 200, 150, 150]
   462         self.ColSizes = [40, 200, 150, 150]
   501         self.VariablesGrid.SetTable(self.Table)
   463         self.VariablesGrid.SetTable(self.Table)
   502         self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
   464         self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
   503                                        "Delete": self.DeleteVariableButton,
   465                                        "Delete": self.DeleteVariableButton,
   537         self.Controler.SetVariables(self.Table.GetData())
   499         self.Controler.SetVariables(self.Table.GetData())
   538         self.RefreshBuffer()
   500         self.RefreshBuffer()
   539         
   501         
   540     # Buffer the last model state
   502     # Buffer the last model state
   541     def RefreshBuffer(self):
   503     def RefreshBuffer(self):
   542         self.Controler.BufferCFile()
   504         self.Controler.BufferCodeFile()
   543         self.ParentWindow.RefreshTitle()
   505         self.ParentWindow.RefreshTitle()
   544         self.ParentWindow.RefreshFileMenu()
   506         self.ParentWindow.RefreshFileMenu()
   545         self.ParentWindow.RefreshEditMenu()
   507         self.ParentWindow.RefreshEditMenu()
   546         self.ParentWindow.RefreshPageTitles()
   508         self.ParentWindow.RefreshPageTitles()
   547 
   509 
   563         if self.Table.GetColLabelValue(col, False) == "Type":
   525         if self.Table.GetColLabelValue(col, False) == "Type":
   564             type_menu = wx.Menu(title='')
   526             type_menu = wx.Menu(title='')
   565             base_menu = wx.Menu(title='')
   527             base_menu = wx.Menu(title='')
   566             for base_type in self.Controler.GetBaseTypes():
   528             for base_type in self.Controler.GetBaseTypes():
   567                 new_id = wx.NewId()
   529                 new_id = wx.NewId()
   568                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
   530                 base_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
   569                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
   531                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
   570             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
   532             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
   571             datatype_menu = wx.Menu(title='')
   533             datatype_menu = wx.Menu(title='')
   572             for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
   534             for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
   573                 new_id = wx.NewId()
   535                 new_id = wx.NewId()
   574                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   536                 datatype_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   575                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   537                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   576             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
   538             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
   577             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   539             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
   578             
   540             
   579             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
   541             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
   606             return
   568             return
   607         event.Skip()
   569         event.Skip()
   608     
   570     
   609 
   571 
   610 #-------------------------------------------------------------------------------
   572 #-------------------------------------------------------------------------------
   611 #                          SVGUIEditor Main Frame Class
   573 #                          CodeFileEditor Main Frame Class
   612 #-------------------------------------------------------------------------------
   574 #-------------------------------------------------------------------------------
   613 
   575 
   614 CFILE_PARTS = [
   576 class CodeFileEditor(ConfTreeNodeEditor):
   615     ("Includes", CppEditor), 
       
   616     ("Variables", VariablesEditor), 
       
   617     ("Globals", CppEditor), 
       
   618     ("Init", CppEditor), 
       
   619     ("CleanUp", CppEditor), 
       
   620     ("Retrieve", CppEditor), 
       
   621     ("Publish", CppEditor),
       
   622 ]
       
   623 
       
   624 class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
       
   625     
       
   626     def GetBackgroundBrush(self, dc):
       
   627         colBg = self.GetBackgroundColour()
       
   628         brush = wx.Brush(colBg, wx.SOLID)
       
   629         if self.style & wx.BORDER_NONE:
       
   630             myAttr = self.GetDefaultAttributes()
       
   631             parAttr = self.GetParent().GetDefaultAttributes()
       
   632             myDef = colBg == myAttr.colBg
       
   633             parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
       
   634             if myDef and parDef:
       
   635                 if wx.Platform == "__WXMAC__":
       
   636                     brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
       
   637                 elif wx.Platform == "__WXMSW__":
       
   638                     if self.DoEraseBackground(dc):
       
   639                         brush = None
       
   640             elif myDef and not parDef:
       
   641                 colBg = self.GetParent().GetBackgroundColour()
       
   642                 brush = wx.Brush(colBg, wx.SOLID)
       
   643         return brush
       
   644     
       
   645     def DrawLabel(self, dc, width, height, dx=0, dy=0):
       
   646         bmp = self.bmpLabel
       
   647         if bmp is not None:     # if the bitmap is used
       
   648             if self.bmpDisabled and not self.IsEnabled():
       
   649                 bmp = self.bmpDisabled
       
   650             if self.bmpFocus and self.hasFocus:
       
   651                 bmp = self.bmpFocus
       
   652             if self.bmpSelected and not self.up:
       
   653                 bmp = self.bmpSelected
       
   654             bw,bh = bmp.GetWidth(), bmp.GetHeight()
       
   655             hasMask = bmp.GetMask() is not None
       
   656         else:
       
   657             bw = bh = 0     # no bitmap -> size is zero
       
   658         
       
   659         dc.SetFont(self.GetFont())
       
   660         if self.IsEnabled():
       
   661             dc.SetTextForeground(self.GetForegroundColour())
       
   662         else:
       
   663             dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
       
   664 
       
   665         label = self.GetLabel()
       
   666         tw, th = dc.GetTextExtent(label)        # size of text
       
   667         
       
   668         if bmp is not None:
       
   669             dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
       
   670         
       
   671         dc.DrawText(label, 2, (height-th)/2)      # draw the text
       
   672 
       
   673         dc.SetPen(wx.Pen(self.GetForegroundColour()))
       
   674         dc.SetBrush(wx.TRANSPARENT_BRUSH)
       
   675         dc.DrawRectangle(0, 0, width, height)
       
   676 
       
   677 class CFileEditor(ConfTreeNodeEditor):
       
   678     
   577     
   679     CONFNODEEDITOR_TABS = [
   578     CONFNODEEDITOR_TABS = [
   680         (_("C code"), "_create_CCodeEditor")]
   579         (_("Variables"), "_create_VariablesPanel")]
   681     
   580     
   682     def _create_CCodeEditor(self, prnt):
   581     def _create_VariablesPanel(self, prnt):
   683         self.CCodeEditor = wx.ScrolledWindow(prnt, 
   582         self.VariablesPanel = VariablesEditor(prnt, self.ParentWindow, self.Controler)
   684               style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
   583         
   685         self.CCodeEditor.Bind(wx.EVT_SIZE, self.OnCCodeEditorResize)
   584         return self.VariablesPanel
   686         
       
   687         self.Panels = {}
       
   688         self.MainSizer = wx.BoxSizer(wx.VERTICAL)
       
   689         
       
   690         for idx, (name, panel_class) in enumerate(CFILE_PARTS):
       
   691             button_id = wx.NewId()
       
   692             button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, 
       
   693                   label=name, bitmap=GetBitmap("CollapsedIconData"), 
       
   694                   parent=self.CCodeEditor, pos=wx.Point(0, 0),
       
   695                   size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
       
   696             button.SetBitmapSelected(GetBitmap("ExpandedIconData"))
       
   697             button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
       
   698             self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
       
   699             
       
   700             if panel_class == VariablesEditor:
       
   701                 panel = VariablesEditor(self.CCodeEditor, self.ParentWindow, self.Controler)
       
   702             else:
       
   703                 panel = panel_class(self.CCodeEditor, name, self.ParentWindow, self.Controler)
       
   704             self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
       
   705             panel.Hide()
       
   706             
       
   707             self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
       
   708         
       
   709         self.CCodeEditor.SetSizer(self.MainSizer)
       
   710         
       
   711         return self.CCodeEditor
       
   712     
   585     
   713     def __init__(self, parent, controler, window):
   586     def __init__(self, parent, controler, window):
   714         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   587         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   715     
   588     
   716     def GetBufferState(self):
   589     def GetBufferState(self):
   725         self.RefreshView()
   598         self.RefreshView()
   726     
   599     
   727     def RefreshView(self):
   600     def RefreshView(self):
   728         ConfTreeNodeEditor.RefreshView(self)
   601         ConfTreeNodeEditor.RefreshView(self)
   729         
   602         
   730         for infos in self.Panels.itervalues():
   603         self.VariablesPanel.RefreshView()
   731             infos["panel"].RefreshView()
       
   732         
       
   733         self.RefreshCCodeEditorScrollbars()
       
   734 
       
   735     def GenPanelButtonCallback(self, name):
       
   736         def PanelButtonCallback(event):
       
   737             self.TogglePanel(name)
       
   738         return PanelButtonCallback
       
   739 
       
   740     def ExpandPanel(self, name):
       
   741         infos = self.Panels.get(name, None)
       
   742         if infos is not None and not infos["expanded"]:
       
   743             infos["expanded"] = True
       
   744             infos["button"].SetToggle(True)
       
   745             infos["panel"].Show()
       
   746             
   604             
   747             self.RefreshSizerLayout()
       
   748     
       
   749     def CollapsePanel(self, name):
       
   750         infos = self.Panels.get(name, None)
       
   751         if infos is not None and infos["expanded"]:
       
   752             infos["expanded"] = False
       
   753             infos["button"].SetToggle(False)
       
   754             infos["panel"].Hide()
       
   755             
       
   756             self.RefreshSizerLayout()
       
   757         
       
   758     def TogglePanel(self, name):
       
   759         infos = self.Panels.get(name, None)
       
   760         if infos is not None:
       
   761             infos["expanded"] = not infos["expanded"]
       
   762             infos["button"].SetToggle(infos["expanded"])
       
   763             if infos["expanded"]:
       
   764                 infos["panel"].Show()
       
   765             else:
       
   766                 infos["panel"].Hide()
       
   767             
       
   768             self.RefreshSizerLayout()
       
   769     
       
   770     def RefreshSizerLayout(self):
       
   771         self.MainSizer.Layout()
       
   772         self.RefreshCCodeEditorScrollbars()
       
   773     
       
   774     def RefreshCCodeEditorScrollbars(self):
       
   775         self.CCodeEditor.GetBestSize()
       
   776         xstart, ystart = self.CCodeEditor.GetViewStart()
       
   777         window_size = self.CCodeEditor.GetClientSize()
       
   778         maxx, maxy = self.MainSizer.GetMinSize()
       
   779         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
       
   780         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
       
   781         self.CCodeEditor.Scroll(posx, posy)
       
   782         self.CCodeEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
       
   783                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
       
   784     
       
   785     def OnCCodeEditorResize(self, event):
       
   786         self.RefreshCCodeEditorScrollbars()
       
   787         event.Skip()
       
   788