diff --git a/Components.py b/Components.py index dc541fca..ed776ec1 100644 --- a/Components.py +++ b/Components.py @@ -681,6 +681,7 @@ def setBlock(self, devs): DEVSComponent.setBlockModel(devs, self) + ### def setDEVSClassModel(self, classe): """ Set the __class__ attribut of the devs model @param classe: new classe object @@ -688,6 +689,30 @@ def setDEVSClassModel(self, classe): if inspect.isclass(classe): self.devsModel.__class__ = classe + ### + def isCMD(self): + """ Return True if the python file is embedded in CMD file + """ + fn = os.path.dirname(self.getDEVSPythonPath()) + return zipfile.is_zipfile(fn) and fn.endswith(('.cmd')) if os.path.isfile(fn) else False + + ### + def isAMD(self): + """ Return True if the python file is embedded in AMD file + """ + fn = os.path.dirname(self.getDEVSPythonPath()) + return zipfile.is_zipfile(fn) and fn.endswith(('.amd')) if os.path.isfile(fn) else False + + def isPYC(self): + """ Return True if the python path point to a python file + """ + return self.python_path.endswith('.pyc') if os.path.isfile(self.python_path) else False + + def isPY(self): + """ Return True if the python path point to a compiled python file + """ + return self.python_path.endswith('.py') if os.path.isfile(self.python_path) else False + ### def OnLog(self, event): """ Shows informations inserted with debugger instructions into the model. @@ -810,6 +835,7 @@ def OnEditor(self, event): # loading file in DEVSimPy editor windows (self.text) try: + editorFrame = Editor.GetEditor(None, wx.NewIdRef(), ''.join([name,' - ',model_path]), obj=self, file_type='block') # if zipfile.is_zipfile(model_path): diff --git a/Container.py b/Container.py index 769ef386..f944f0f5 100644 --- a/Container.py +++ b/Container.py @@ -3046,7 +3046,11 @@ def GetTestFile(self): # NOTE: Testable :: isAMD => Test if the model is an AMD and if it's well-formed def isAMD(self): fn = os.path.dirname(self.python_path) - return zipfile.is_zipfile(fn) or fn.endswith(('.amd','.cmd')) if os.path.isfile(fn) else False + return zipfile.is_zipfile(fn) and fn.endswith(('.amd')) if os.path.isfile(fn) else False + + def isCMD(self): + fn = os.path.dirname(self.python_path) + return zipfile.is_zipfile(fn) and fn.endswith(('.cmd')) if os.path.isfile(fn) else False def isPYC(self): return self.python_path.endswith('.pyc') if os.path.isfile(self.python_path) else False diff --git a/Editor.py b/Editor.py index ec1107b0..0d8631ca 100644 --- a/Editor.py +++ b/Editor.py @@ -44,7 +44,8 @@ import ReloadModule import ZipManager -_ = wx.GetTranslation +import gettext +_ = gettext.gettext # Turn on verbose mode tabnanny.verbose = 1 @@ -164,6 +165,41 @@ def GetEditor(parent, id, title="", obj=None, **kwargs): ### ################################################################# +class TestSearchCtrl(wx.SearchCtrl): + maxSearches = 5 + + def __init__(self, parent, id=-1, value="", + pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, + doSearch=None): + style |= wx.TE_PROCESS_ENTER + wx.SearchCtrl.__init__(self, parent, id, value, pos, size, style) + self.Bind(wx.EVT_TEXT_ENTER, self.OnTextEntered) + self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnTextEntered) + self.Bind(wx.EVT_MENU_RANGE, self.OnMenuItem, id=1, id2=self.maxSearches) + self.doSearch = doSearch + self.searches = [] + + def OnTextEntered(self, evt): + text = self.GetValue() + if self.doSearch(text): + self.searches.append(text) + if len(self.searches) > self.maxSearches: + del self.searches[0] + self.SetMenu(self.MakeMenu()) + self.SetValue("") + + def OnMenuItem(self, evt): + text = self.searches[evt.GetId()-1] + self.doSearch(text) + + def MakeMenu(self): + menu = wx.Menu() + item = menu.Append(-1, "Recent Searches") + item.Enable(False) + for idx, txt in enumerate(self.searches): + menu.Append(1+idx, txt) + return menu + ### NOTE: PythonSTC << stc.StyledTextCtrl :: todo class PythonSTC(stc.StyledTextCtrl): """ @@ -830,7 +866,6 @@ def AddEditPage(self, title="", path=""): """ fileCode = "" - ### FIXME: try to consider zipfile in zipfile L = re.findall("(.*\.(amd|cmd))\%s(.*)" % os.sep, path) @@ -1048,19 +1083,19 @@ def WriteFile(fileName, code, encode='utf-8'): ### NOTE: EditionNotebook :: OnCut => Event on cut def OnCut(self, event): - """ + """ Cut the text """ self.GetCurrentPage().Cut() ### NOTE: EditionNotebook :: OnCopy => Event on copy def OnCopy(self, event): - """ + """ Copy the text """ self.GetCurrentPage().Copy() ### NOTE: EditionNotebook :: OnPaste => Event on paste def OnPaste(self, event): - """ + """ Paste the text """ self.GetCurrentPage().Paste() @@ -1074,7 +1109,7 @@ def CheckIndent(fileName): ### NOTE: EditionNotebook :: OnReIndent => Event on re-indent def OnReIndent(self, event): - """ + """ Reindent all the text """ cp = self.GetCurrentPage() @@ -1108,28 +1143,79 @@ def OnReIndent(self, event): cp.SetValue(text) ### status bar notification - self.parent.Notification(True, _('re-indented'), '', '') + self.parent.Notification(True, _('%s re-indented' % (os.path.basename(cp.GetFilename()))), '', '') - def OnComment(self, event): - """ Comment current line + def OnCommentUnComment(self, event): + """ Comment/Uncomment current line(s) """ cp = self.GetCurrentPage() - cur_line = cp.GetCurrentLine() - cp.InsertText(cp.PositionFromLine(cur_line), "#") + selected_txt = cp.GetSelectedText() + raws = selected_txt.split('\n') + + ### select lines + if len(raws) > 1: + commented_txt = "" + ### for each raw, we insert # in front of the first caractere of the string in raw + for i,raw in enumerate(raws): + ### find index position of the first caractere + find = re.search(r'[A-Za-z#]', raw) + ### if caracter finded (False in the case of raw without caratere...) + if find: + ### position of the first caractere in the raw + pos = find.start() + ### \n not for the last line + end_line = '\n' if i < len(raws)-1 else '' + ### comment symbol in python + symbol = "#" + + ### uncomment - comment symbol is finded + if raw[pos] == symbol: + raw = raw.replace(symbol,"") + symbol = "" + + commented_txt += "".join(f"{raw[:pos]}{symbol}{raw[pos:]}{end_line}") + + ### replace slelected text by the commented text + cp.ReplaceSelection(commented_txt) + ### cursor is in the line to comment/uncomment + else: - def OnUnComment(self, event): - """ Uncomment current line - """ - cp = self.GetCurrentPage() - cur_line = cp.GetCurrentLine() - indent = cp.GetLineIndentPosition(cur_line) - cp.Home() - cp.DelWordRight() - cp.SetCurrentPos(indent) + ### comment symbol in python + symbol = "#" + + ### pointed line that contain the line to comment/unncomment + pointed_txt,pos = cp.GetCurLine() + cur_line = cp.GetCurrentLine() + ### search # + find = re.search(r'[#]', pointed_txt) + ### uncomment - comment symbol is finded + if find: + ### remove # and \n + pointed_txt = pointed_txt.replace(symbol,"").replace("\n",'') + pos_from = cp.PositionFromLine(cur_line) + pos_to = pos_from+len(pointed_txt)+1 + ### replace the commented line by the uncommented one + cp.Replace(pos_from, pos_to, pointed_txt) + ### comment + else: + cp.InsertText(cp.PositionFromLine(cur_line), symbol) + + ### status bar notification + self.parent.Notification(True, _('%s modified' % (os.path.basename(cp.GetFilename()))), '', '') + + # def OnUnComment(self, event): + # """ Uncomment current line(s) + # """ + # cp = self.GetCurrentPage() + # cur_line = cp.GetCurrentLine() + # indent = cp.GetLineIndentPosition(cur_line) + # cp.Home() + # cp.DelWordRight() + # cp.SetCurrentPos(indent) ### def OnDelete(self, event): - """ + """ Delete selected text """ cp = self.GetCurrentPage() frm, to = cp.GetSelection() @@ -1137,7 +1223,7 @@ def OnDelete(self, event): ### def OnSelectAll(self, event): - """ + """ Select all the text """ self.GetCurrentPage().SelectAll() @@ -1273,7 +1359,8 @@ def CreateMenu(self): select = wx.MenuItem(edit, wx.NewIdRef(), _('Select &All\tCtrl+A'), _('Select the entire text')) reindent = wx.MenuItem(edit, wx.NewIdRef(), _('Re-indent\tCtrl+R'), _('re-indent all code')) comment = wx.MenuItem(edit, wx.NewIdRef(), _('&Comment\tCtrl+D'), _('comment current ligne')) - uncomment = wx.MenuItem(edit, wx.NewIdRef(), _('&Uncomment\tCtrl+Shift+D'), _('uncomment current ligne')) + uncomment = wx.MenuItem(edit, wx.NewIdRef(), _('&Uncomment\tCtrl+D'), _('uncomment current ligne')) + # uncomment = wx.MenuItem(edit, wx.NewIdRef(), _('&Uncomment\tCtrl+Shift+D'), _('uncomment current ligne')) self.cut.SetBitmap(wx.Bitmap(os.path.join(ICON_PATH, 'cut.png'))) self.copy.SetBitmap(wx.Bitmap(os.path.join(ICON_PATH, 'copy.png'))) @@ -1355,9 +1442,9 @@ def CreateMenu(self): self.Bind(wx.EVT_MENU, self.nb.OnCopy, id=self.copy.GetId()) self.Bind(wx.EVT_MENU, self.nb.OnPaste, id=self.paste.GetId()) self.Bind(wx.EVT_MENU, self.nb.OnReIndent, id=reindent.GetId()) - self.Bind(wx.EVT_MENU, self.nb.OnComment, id=comment.GetId()) + self.Bind(wx.EVT_MENU, self.nb.OnCommentUnComment, id=comment.GetId()) self.Bind(wx.EVT_MENU, self.OnSearch, id=self.search.GetId()) - self.Bind(wx.EVT_MENU, self.nb.OnUnComment, id=uncomment.GetId()) + self.Bind(wx.EVT_MENU, self.nb.OnCommentUnComment, id=uncomment.GetId()) self.Bind(wx.EVT_MENU, self.nb.OnDelete, id=delete.GetId()) self.Bind(wx.EVT_MENU, self.nb.OnSelectAll, id=select.GetId()) self.Bind(wx.EVT_MENU, self.ToggleStatusBar, id=showStatusBar.GetId()) @@ -1412,6 +1499,15 @@ def CreateTB(self): return tb + def DoSearch(self, text): + """ + """ + ### TODO ! + # called by TestSearchCtrl + sys.stdout.write("DoSearch: %s\n" % text) + # return true to tell the search ctrl to remember the text + return True + def GetNoteBook(self): """ Return the NoteBook """ @@ -1521,6 +1617,8 @@ def OnSaveFile(self, event): self.Notification(False, _('%s not saved' % fn), _('file in readonly'), '') def OnSearch(self, evt): + """ + """ currentPage = self.nb.GetCurrentPage() self.txt = currentPage.GetValue() self.data = wx.FindReplaceData() # initializes and holds search parameters @@ -1528,6 +1626,8 @@ def OnSearch(self, evt): self.dlg.Show() def OnFind(self, evt): + """ + """ fstring = self.data.GetFindString() # also from event.GetFindString() self.pos = self.txt.find(fstring, self.pos+self.size) self.size = len(fstring) @@ -1839,6 +1939,43 @@ def __init__(self, parent, id, title, block): """ self.cb = block + self.parent = parent + + def OnCombo(self, event): + choice = event.GetString() + if choice == "New peek": + sins = list(map(str, list(range(self.cb.input if hasattr(self.cb, 'input') else 10)))) + dlg = wx.SingleChoiceDialog(self, _('Port number'), _('Which port?'), sins, wx.CHOICEDLG_STYLE) + port = dlg.GetStringSelection() if dlg.ShowModal() == wx.ID_OK else None + dlg.Destroy() + + if port is not None: + cp = self.nb.GetCurrentPage() + cp.AddText("self.peek(self.IPorts[%d], *args)" % int(port)) + self.Notification(True, _('%s modified' % (os.path.basename(cp.GetFilename()))), '', '') + + elif choice == "New poke": + sins = list(map(str, list(range(self.cb.input if hasattr(self.cb, 'output') else 10)))) + dlg = wx.SingleChoiceDialog(self, _('Port number'), _('Which port?'), sins, wx.CHOICEDLG_STYLE) + port = dlg.GetStringSelection() if dlg.ShowModal() == wx.ID_OK else None + dlg.Destroy() + + if port is not None: + cp = self.nb.GetCurrentPage() + cp.AddText("return self.poke(self.OPorts[%d], Message(<>, self.timeNext))" % int(port)) + self.Notification(True, _('%s modified' % (os.path.basename(cp.GetFilename()))), '', '') + elif choice == "New hold in state": + self.OnInsertHoldInState(event) + elif choice == 'New passivate in state': + self.OnInsertPassivateInState(event) + elif choice == 'New passivate state': + self.OnInsertPassivateState(event) + elif choice == 'New debugger stdout': + self.OnInsertDebug(event) + elif choice == 'New Phase test': + self.OnInsertPhaseIs(event) + + # sys.stdout.write("combobox item selected: %s\n" % event.GetString()) ### def OnInsertPeekPoke(self, event): @@ -1868,84 +2005,84 @@ def OnInsertPeekPoke(self, event): cp.AddText("self.peek(self.IPorts[%d], *args)" % int(port)) elif "poke" in label: cp.AddText("return self.poke(self.OPorts[%d], Message(<>, self.timeNext))" % int(port)) - cp.modify = True + self.Notification(True, _('%s modified' % (os.path.basename(cp.GetFilename()))), '', '') def OnInsertInitPhase(self, event): """ Insert a sentence to get the init phase (status and sigma) """ cp = self.nb.GetCurrentPage() cp.AddText("self.initPhase(,)") - cp.modify = True + self.Notification(True, _('%s modified' % (os.path.basename(cp.GetFilename()))), '', '') def OnInsertSetState(self, event): """ Insert a sentence to set the state (status and sigma) """ cp = self.nb.GetCurrentPage() cp.AddText("self.setState({'status':'', 'sigma':