Adding support for defining mandatory parameters and creating blank xml file when there is nothing in the folder in LPCBeremiz
import wx, wx.grid
import wx.stc as stc
import keyword
if wx.Platform == '__WXMSW__':
faces = { 'times': 'Times New Roman',
'mono' : 'Courier New',
'helv' : 'Arial',
'other': 'Comic Sans MS',
'size' : 10,
'size2': 8,
}
elif wx.Platform == '__WXMAC__':
faces = { 'times': 'Times New Roman',
'mono' : 'Monaco',
'helv' : 'Arial',
'other': 'Comic Sans MS',
'size' : 12,
'size2': 10,
}
else:
faces = { 'times': 'Times',
'mono' : 'Courier',
'helv' : 'Helvetica',
'other': 'new century schoolbook',
'size' : 12,
'size2': 10,
}
def AppendMenu(parent, help, id, kind, text):
if wx.VERSION >= (2, 6, 0):
parent.Append(help=help, id=id, kind=kind, text=text)
else:
parent.Append(helpString=help, id=id, kind=kind, item=text)
[ID_PYTHONEDITOR,
] = [wx.NewId() for _init_ctrls in range(1)]
def GetCursorPos(old, new):
old_length = len(old)
new_length = len(new)
common_length = min(old_length, new_length)
i = 0
for i in xrange(common_length):
if old[i] != new[i]:
break
if old_length < new_length:
if common_length > 0 and old[i] != new[i]:
return i + new_length - old_length
else:
return i + new_length - old_length + 1
elif old_length > new_length or i < min(old_length, new_length) - 1:
if common_length > 0 and old[i] != new[i]:
return i
else:
return i + 1
else:
return None
class PythonEditor(stc.StyledTextCtrl):
fold_symbols = 3
def __init__(self, parent, window, controler):
stc.StyledTextCtrl.__init__(self, parent, ID_PYTHONEDITOR, wx.DefaultPosition,
wx.DefaultSize, 0)
self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
self.SetLexer(stc.STC_LEX_PYTHON)
self.SetKeyWords(0, " ".join(keyword.kwlist))
self.SetProperty("fold", "1")
self.SetProperty("tab.timmy.whinge.level", "1")
self.SetMargins(0,0)
self.SetViewWhiteSpace(False)
#self.SetBufferedDraw(False)
#self.SetViewEOL(True)
#self.SetEOLMode(stc.STC_EOL_CRLF)
#self.SetUseAntiAliasing(True)
self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
self.SetEdgeColumn(78)
# Set up the numbers in the margin for margin #1
self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
# Reasonable value for, say, 4-5 digits using a mono font (40 pix)
self.SetMarginWidth(1, 40)
# Setup a margin to hold fold markers
self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
self.SetMarginSensitive(2, True)
self.SetMarginWidth(2, 12)
if self.fold_symbols == 0:
# Arrow pointing right for contracted folders, arrow pointing down for expanded
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
elif self.fold_symbols == 1:
# Plus for contracted folders, minus for expanded
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
elif self.fold_symbols == 2:
# Like a flattened tree control using circular headers and curved joins
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
elif self.fold_symbols == 3:
# Like a flattened tree control using square headers
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
# Global default style
if wx.Platform == '__WXMSW__':
self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
'fore:#000000,back:#FFFFFF,face:Courier New')
elif wx.Platform == '__WXMAC__':
# TODO: if this looks fine on Linux too, remove the Mac-specific case
# and use this whenever OS != MSW.
self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
'fore:#000000,back:#FFFFFF,face:Monaco')
else:
defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
# Clear styles and revert to default.
self.StyleClearAll()
# Following style specs only indicate differences from default.
# The rest remains unchanged.
# Line numbers in margin
self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
# Highlighted brace
self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
# Unmatched brace
self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
# Indentation guide
self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
# Python styles
self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
# Comments
self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
# Numbers
self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
# Strings and characters
self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
# Keywords
self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
# Triple quotes
self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
# Class names
self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
# Function names
self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
# Operators
self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
# Identifiers. I leave this as not bold because everything seems
# to be an identifier if it doesn't match the above criterae
self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
# Caret color
self.SetCaretForeground("BLUE")
# Selection background
self.SetSelBackground(1, '#66CCFF')
self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
# register some images for use in the AutoComplete box.
#self.RegisterImage(1, images.getSmilesBitmap())
self.RegisterImage(1,
wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
self.RegisterImage(2,
wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
self.RegisterImage(3,
wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
# Indentation and tab stuff
self.SetIndent(4) # Proscribed indent size for wx
self.SetIndentationGuides(True) # Show indent guides
self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
self.SetTabIndents(True) # Tab key indents
self.SetTabWidth(4) # Proscribed tab size for wx
self.SetUseTabs(False) # Use spaces rather than tabs, or
# TabTimmy will complain!
# White space
self.SetViewWhiteSpace(False) # Don't view white space
# EOL: Since we are loading/saving ourselves, and the
# strings will always have \n's in them, set the STC to
# edit them that way.
self.SetEOLMode(wx.stc.STC_EOL_LF)
self.SetViewEOL(False)
# No right-edge mode indicator
self.SetEdgeMode(stc.STC_EDGE_NONE)
self.Controler = controler
self.ParentWindow = window
self.DisableEvents = True
self.CurrentAction = None
self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
def OnModification(self, event):
if not self.DisableEvents:
mod_type = event.GetModificationType()
if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
if self.CurrentAction == None:
self.StartBuffering()
elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
self.Controler.EndBuffering()
self.StartBuffering()
self.CurrentAction = ("Add", event.GetPosition())
elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
if self.CurrentAction == None:
self.StartBuffering()
elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
self.Controler.EndBuffering()
self.StartBuffering()
self.CurrentAction = ("Delete", event.GetPosition())
event.Skip()
def OnDoDrop(self, event):
self.ResetBuffer()
wx.CallAfter(self.RefreshModel)
event.Skip()
def IsViewing(self, name):
return self.Name == name
# Buffer the last model state
def RefreshBuffer(self):
self.Controler.BufferPython()
if self.ParentWindow:
self.ParentWindow.RefreshTitle()
self.ParentWindow.RefreshEditMenu()
def StartBuffering(self):
self.Controler.StartBuffering()
if self.ParentWindow:
self.ParentWindow.RefreshTitle()
self.ParentWindow.RefreshEditMenu()
def ResetBuffer(self):
if self.CurrentAction != None:
self.Controler.EndBuffering()
self.CurrentAction = None
def RefreshView(self):
self.ResetBuffer()
self.DisableEvents = True
old_cursor_pos = self.GetCurrentPos()
old_text = self.GetText()
new_text = self.Controler.GetPythonCode()
self.SetText(new_text)
new_cursor_pos = GetCursorPos(old_text, new_text)
if new_cursor_pos != None:
self.GotoPos(new_cursor_pos)
else:
self.GotoPos(old_cursor_pos)
self.ScrollToColumn(0)
self.EmptyUndoBuffer()
self.DisableEvents = False
self.Colourise(0, -1)
def RefreshModel(self):
self.Controler.SetPythonCode(self.GetText())
def OnKeyPressed(self, event):
if self.CallTipActive():
self.CallTipCancel()
key = event.GetKeyCode()
if key == 32 and event.ControlDown():
pos = self.GetCurrentPos()
# Tips
if event.ShiftDown():
pass
## self.CallTipSetBackground("yellow")
## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
## 'show some suff, maybe parameters..\n\n'
## 'fubar(param1, param2)')
# Code completion
else:
self.AutoCompSetIgnoreCase(False) # so this needs to match
# Images are specified with a appended "?type"
self.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
else:
wx.CallAfter(self.RefreshModel)
event.Skip()
def OnKillFocus(self, event):
self.AutoCompCancel()
event.Skip()
def OnUpdateUI(self, evt):
# check for matching braces
braceAtCaret = -1
braceOpposite = -1
charBefore = None
caretPos = self.GetCurrentPos()
if caretPos > 0:
charBefore = self.GetCharAt(caretPos - 1)
styleBefore = self.GetStyleAt(caretPos - 1)
# check before
if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
braceAtCaret = caretPos - 1
# check after
if braceAtCaret < 0:
charAfter = self.GetCharAt(caretPos)
styleAfter = self.GetStyleAt(caretPos)
if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
braceAtCaret = caretPos
if braceAtCaret >= 0:
braceOpposite = self.BraceMatch(braceAtCaret)
if braceAtCaret != -1 and braceOpposite == -1:
self.BraceBadLight(braceAtCaret)
else:
self.BraceHighlight(braceAtCaret, braceOpposite)
#pt = self.PointFromPosition(braceOpposite)
#self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
#print pt
#self.Refresh(False)
def OnMarginClick(self, evt):
# fold and unfold as needed
if evt.GetMargin() == 2:
if evt.GetShift() and evt.GetControl():
self.FoldAll()
else:
lineClicked = self.LineFromPosition(evt.GetPosition())
if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
if evt.GetShift():
self.SetFoldExpanded(lineClicked, True)
self.Expand(lineClicked, True, True, 1)
elif evt.GetControl():
if self.GetFoldExpanded(lineClicked):
self.SetFoldExpanded(lineClicked, False)
self.Expand(lineClicked, False, True, 0)
else:
self.SetFoldExpanded(lineClicked, True)
self.Expand(lineClicked, True, True, 100)
else:
self.ToggleFold(lineClicked)
def FoldAll(self):
lineCount = self.GetLineCount()
expanding = True
# find out if we are folding or unfolding
for lineNum in range(lineCount):
if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
expanding = not self.GetFoldExpanded(lineNum)
break
lineNum = 0
while lineNum < lineCount:
level = self.GetFoldLevel(lineNum)
if level & stc.STC_FOLDLEVELHEADERFLAG and \
(level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
if expanding:
self.SetFoldExpanded(lineNum, True)
lineNum = self.Expand(lineNum, True)
lineNum = lineNum - 1
else:
lastChild = self.GetLastChild(lineNum, -1)
self.SetFoldExpanded(lineNum, False)
if lastChild > lineNum:
self.HideLines(lineNum+1, lastChild)
lineNum = lineNum + 1
def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
lastChild = self.GetLastChild(line, level)
line = line + 1
while line <= lastChild:
if force:
if visLevels > 0:
self.ShowLines(line, line)
else:
self.HideLines(line, line)
else:
if doExpand:
self.ShowLines(line, line)
if level == -1:
level = self.GetFoldLevel(line)
if level & stc.STC_FOLDLEVELHEADERFLAG:
if force:
if visLevels > 1:
self.SetFoldExpanded(line, True)
else:
self.SetFoldExpanded(line, False)
line = self.Expand(line, doExpand, force, visLevels-1)
else:
if doExpand and self.GetFoldExpanded(line):
line = self.Expand(line, True, force, visLevels-1)
else:
line = self.Expand(line, False, force, visLevels-1)
else:
line = line + 1
return line
#-------------------------------------------------------------------------------
# PythonEditor Main Frame Class
#-------------------------------------------------------------------------------
[ID_PYTHONEDITORFRAME,
] = [wx.NewId() for _init_ctrls in range(1)]
class PythonEditorFrame(wx.Frame):
if wx.VERSION < (2, 6, 0):
def Bind(self, event, function, id = None):
if id is not None:
event(self, id, function)
else:
event(self, function)
def _init_coll_EditMenu_Items(self, parent):
AppendMenu(parent, help='', id=wx.ID_REFRESH,
kind=wx.ITEM_NORMAL, text=_(u'Refresh\tCTRL+R'))
AppendMenu(parent, help='', id=wx.ID_UNDO,
kind=wx.ITEM_NORMAL, text=_(u'Undo\tCTRL+Z'))
AppendMenu(parent, help='', id=wx.ID_REDO,
kind=wx.ITEM_NORMAL, text=_(u'Redo\tCTRL+Y'))
self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
def _init_coll_MenuBar_Menus(self, parent):
parent.Append(menu=self.EditMenu, title=_(u'&Edit'))
def _init_utils(self):
self.MenuBar = wx.MenuBar()
self.EditMenu = wx.Menu(title='')
self._init_coll_MenuBar_Menus(self.MenuBar)
self._init_coll_EditMenu_Items(self.EditMenu)
def _init_ctrls(self, prnt):
wx.Frame.__init__(self, id=ID_PYTHONEDITORFRAME, name=u'PythonEditor',
parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650),
style=wx.DEFAULT_FRAME_STYLE, title=_(u'PythonEditor'))
self._init_utils()
self.SetClientSize(wx.Size(1000, 600))
self.SetMenuBar(self.MenuBar)
self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE)
accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)])
self.SetAcceleratorTable(accel)
if wx.VERSION >= (2, 8, 0):
self.AUIManager = wx.aui.AuiManager(self)
self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
self.PythonEdited = PythonEditor(self, self, self.Controler)
if wx.VERSION < (2, 8, 0):
self.MainSizer = wx.BoxSizer(wx.VERTICAL)
self.MainSizer.AddWindow(self.PythonEdited, 0, border=0, flag=wx.GROW)
self.SetSizer(self.MainSizer)
else:
self.AUIManager.AddPane(self.PythonEdited, wx.aui.AuiPaneInfo().CentrePane())
self.StatusBar = wx.StatusBar( name='HelpBar',
parent=self, style=wx.ST_SIZEGRIP)
self.SetStatusBar(self.StatusBar)
if wx.VERSION >= (2, 8, 0):
self.AUIManager.Update()
def __init__(self, parent, controler):
self.Controler = controler
self._init_ctrls(parent)
self.PythonEdited.RefreshView()
self.RefreshTitle()
self.RefreshEditMenu()
def OnCloseFrame(self, event):
if wx.VERSION >= (2, 8, 0):
self.AUIManager.UnInit()
if getattr(self, "_onclose", None) is not None:
self._onclose()
event.Skip()
def OnSaveMenu(self, event):
if getattr(self, "_onsave", None) != None:
self._onsave()
self.RefreshTitle()
self.RefreshEditMenu()
def RefreshTitle(self):
title = _("PythonEditor")
self.SetTitle("%s - %s"%(title, self.Controler.GetFilename()))
#-------------------------------------------------------------------------------
# Edit Project Menu Functions
#-------------------------------------------------------------------------------
def RefreshEditMenu(self):
undo, redo = self.Controler.GetBufferState()
self.EditMenu.Enable(wx.ID_UNDO, undo)
self.EditMenu.Enable(wx.ID_REDO, redo)
def OnRefreshMenu(self, event):
self.PythonEdited.RefreshView()
def OnUndoMenu(self, event):
self.Controler.LoadPrevious()
self.PythonEdited.RefreshView()
self.RefreshTitle()
self.RefreshEditMenu()
def OnRedoMenu(self, event):
self.Controler.LoadNext()
self.PythonEdited.RefreshView()
self.RefreshTitle()
self.RefreshEditMenu()