35 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
35 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
36 from util.BitmapLibrary import GetBitmap |
36 from util.BitmapLibrary import GetBitmap |
37 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS |
37 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS |
38 from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL |
38 from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL |
39 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD |
39 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD |
|
40 from util.TranslationCatalogs import NoTranslate |
40 |
41 |
41 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT, |
42 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT, |
42 STC_CODE_SECTION] = range(15, 18) |
43 STC_CODE_SECTION] = range(15, 18) |
43 |
44 |
44 HIGHLIGHT_TYPES = { |
45 HIGHLIGHT_TYPES = { |
46 SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT, |
47 SEARCH_RESULT_HIGHLIGHT: STC_CODE_SEARCH_RESULT, |
47 } |
48 } |
48 |
49 |
49 EDGE_COLUMN = 80 |
50 EDGE_COLUMN = 80 |
50 |
51 |
|
52 |
51 class CodeEditor(CustomStyledTextCtrl): |
53 class CodeEditor(CustomStyledTextCtrl): |
52 |
54 |
53 KEYWORDS = [] |
55 KEYWORDS = [] |
54 COMMENT_HEADER = "" |
56 COMMENT_HEADER = "" |
55 |
57 |
56 def __init__(self, parent, window, controler): |
58 def __init__(self, parent, window, controler): |
57 CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition, |
59 CustomStyledTextCtrl.__init__(self, parent, -1, wx.DefaultPosition, |
58 wx.Size(-1, 300), 0) |
60 wx.Size(-1, 300), 0) |
59 |
61 |
60 self.SetMarginType(1, stc.STC_MARGIN_NUMBER) |
62 self.SetMarginType(1, stc.STC_MARGIN_NUMBER) |
61 self.SetMarginWidth(1, 25) |
63 self.SetMarginWidth(1, 25) |
62 |
64 |
63 self.SetProperty("fold", "1") |
65 self.SetProperty("fold", "1") |
64 self.SetProperty("tab.timmy.whinge.level", "1") |
66 self.SetProperty("tab.timmy.whinge.level", "1") |
65 self.SetMargins(0,0) |
67 self.SetMargins(0, 0) |
66 |
68 |
67 self.SetViewWhiteSpace(False) |
69 self.SetViewWhiteSpace(False) |
68 |
70 |
69 self.SetEdgeMode(stc.STC_EDGE_BACKGROUND) |
71 self.SetEdgeMode(stc.STC_EDGE_BACKGROUND) |
70 self.SetEdgeColumn(EDGE_COLUMN) |
72 self.SetEdgeColumn(EDGE_COLUMN) |
131 |
133 |
132 self.SectionsComments = {} |
134 self.SectionsComments = {} |
133 for section in self.Controler.SECTIONS_NAMES: |
135 for section in self.Controler.SECTIONS_NAMES: |
134 section_comment = " %s section " % (section) |
136 section_comment = " %s section " % (section) |
135 len_headers = EDGE_COLUMN - len(section_comment) |
137 len_headers = EDGE_COLUMN - len(section_comment) |
136 section_comment = self.COMMENT_HEADER * (len_headers / 2) + \ |
138 section_comment = \ |
137 section_comment + \ |
139 self.COMMENT_HEADER * (len_headers / 2) + \ |
138 self.COMMENT_HEADER * (len_headers - len_headers / 2) |
140 section_comment + \ |
|
141 self.COMMENT_HEADER * (len_headers - len_headers / 2) |
139 |
142 |
140 self.SectionsComments[section] = { |
143 self.SectionsComments[section] = { |
141 "comment": section_comment, |
144 "comment": section_comment, |
142 } |
145 } |
143 |
146 |
150 section_end = "$" |
153 section_end = "$" |
151 section_infos["pattern"] = re.compile( |
154 section_infos["pattern"] = re.compile( |
152 section_infos["comment"] + "(.*)" + |
155 section_infos["comment"] + "(.*)" + |
153 section_end, re.DOTALL) |
156 section_end, re.DOTALL) |
154 |
157 |
155 self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) |
158 self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT | wx.stc.STC_MOD_BEFOREDELETE) |
156 |
159 |
157 self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop) |
160 self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop) |
158 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
161 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
159 self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification) |
162 self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification) |
160 |
163 |
168 self.CurrentFindHighlight = None |
171 self.CurrentFindHighlight = None |
169 |
172 |
170 def OnModification(self, event): |
173 def OnModification(self, event): |
171 if not self.DisableEvents: |
174 if not self.DisableEvents: |
172 mod_type = event.GetModificationType() |
175 mod_type = event.GetModificationType() |
173 if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO): |
176 if not (mod_type & wx.stc.STC_PERFORMED_UNDO or mod_type & wx.stc.STC_PERFORMED_REDO): |
174 if mod_type&wx.stc.STC_MOD_BEFOREINSERT: |
177 if mod_type & wx.stc.STC_MOD_BEFOREINSERT: |
175 if self.CurrentAction == None: |
178 if self.CurrentAction is None: |
176 self.StartBuffering() |
179 self.StartBuffering() |
177 elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: |
180 elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1: |
178 self.Controler.EndBuffering() |
181 self.Controler.EndBuffering() |
179 self.StartBuffering() |
182 self.StartBuffering() |
180 self.CurrentAction = ("Add", event.GetPosition()) |
183 self.CurrentAction = ("Add", event.GetPosition()) |
181 wx.CallAfter(self.RefreshModel) |
184 wx.CallAfter(self.RefreshModel) |
182 elif mod_type&wx.stc.STC_MOD_BEFOREDELETE: |
185 elif mod_type & wx.stc.STC_MOD_BEFOREDELETE: |
183 if self.CurrentAction == None: |
186 if self.CurrentAction is None: |
184 self.StartBuffering() |
187 self.StartBuffering() |
185 elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: |
188 elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1: |
186 self.Controler.EndBuffering() |
189 self.Controler.EndBuffering() |
187 self.StartBuffering() |
190 self.StartBuffering() |
188 self.CurrentAction = ("Delete", event.GetPosition()) |
191 self.CurrentAction = ("Delete", event.GetPosition()) |
191 event.Skip() |
194 event.Skip() |
192 |
195 |
193 def OnDoDrop(self, event): |
196 def OnDoDrop(self, event): |
194 try: |
197 try: |
195 values = eval(event.GetDragText()) |
198 values = eval(event.GetDragText()) |
196 except: |
199 except Exception: |
197 values = event.GetDragText() |
200 values = event.GetDragText() |
198 if isinstance(values, tuple): |
201 if isinstance(values, tuple): |
199 message = None |
202 message = None |
200 if values[3] == self.Controler.GetCurrentLocation(): |
203 if values[3] == self.Controler.GetCurrentLocation(): |
201 self.ResetBuffer() |
204 self.ResetBuffer() |
224 self.ParentWindow.RefreshFileMenu() |
227 self.ParentWindow.RefreshFileMenu() |
225 self.ParentWindow.RefreshEditMenu() |
228 self.ParentWindow.RefreshEditMenu() |
226 self.ParentWindow.RefreshPageTitles() |
229 self.ParentWindow.RefreshPageTitles() |
227 |
230 |
228 def ResetBuffer(self): |
231 def ResetBuffer(self): |
229 if self.CurrentAction != None: |
232 if self.CurrentAction is not None: |
230 self.Controler.EndBuffering() |
233 self.Controler.EndBuffering() |
231 self.CurrentAction = None |
234 self.CurrentAction = None |
232 |
235 |
233 def GetCodeText(self): |
236 def GetCodeText(self): |
234 parts = self.Controler.GetTextParts() |
237 parts = self.Controler.GetTextParts() |
256 new_text = self.GetCodeText() |
259 new_text = self.GetCodeText() |
257 if old_text != new_text: |
260 if old_text != new_text: |
258 self.SetText(new_text) |
261 self.SetText(new_text) |
259 new_cursor_pos = GetCursorPos(old_text, new_text) |
262 new_cursor_pos = GetCursorPos(old_text, new_text) |
260 self.LineScroll(column, line) |
263 self.LineScroll(column, line) |
261 if new_cursor_pos != None: |
264 if new_cursor_pos is not None: |
262 self.GotoPos(new_cursor_pos) |
265 self.GotoPos(new_cursor_pos) |
263 else: |
266 else: |
264 self.GotoPos(old_cursor_pos) |
267 self.GotoPos(old_cursor_pos) |
265 self.EmptyUndoBuffer() |
268 self.EmptyUndoBuffer() |
266 self.DisableEvents = False |
269 self.DisableEvents = False |
379 braceAtCaret = caretPos |
382 braceAtCaret = caretPos |
380 |
383 |
381 if braceAtCaret >= 0: |
384 if braceAtCaret >= 0: |
382 braceOpposite = self.BraceMatch(braceAtCaret) |
385 braceOpposite = self.BraceMatch(braceAtCaret) |
383 |
386 |
384 if braceAtCaret != -1 and braceOpposite == -1: |
387 if braceAtCaret != -1 and braceOpposite == -1: |
385 self.BraceBadLight(braceAtCaret) |
388 self.BraceBadLight(braceAtCaret) |
386 else: |
389 else: |
387 self.BraceHighlight(braceAtCaret, braceOpposite) |
390 self.BraceHighlight(braceAtCaret, braceOpposite) |
388 |
391 |
389 selected_text = self.GetSelectedText() |
392 selected_text = self.GetSelectedText() |
440 |
443 |
441 if lastChild > lineNum: |
444 if lastChild > lineNum: |
442 self.HideLines(lineNum+1, lastChild) |
445 self.HideLines(lineNum+1, lastChild) |
443 |
446 |
444 lineNum = lineNum + 1 |
447 lineNum = lineNum + 1 |
445 |
|
446 |
|
447 |
448 |
448 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): |
449 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): |
449 lastChild = self.GetLastChild(line, level) |
450 lastChild = self.GetLastChild(line, level) |
450 line = line + 1 |
451 line = line + 1 |
451 |
452 |
546 else: |
547 else: |
547 if self.CurrentFindHighlight is not None: |
548 if self.CurrentFindHighlight is not None: |
548 self.RemoveHighlight(*self.CurrentFindHighlight) |
549 self.RemoveHighlight(*self.CurrentFindHighlight) |
549 self.CurrentFindHighlight = None |
550 self.CurrentFindHighlight = None |
550 |
551 |
551 #------------------------------------------------------------------------------- |
552 # ------------------------------------------------------------------------------- |
552 # Highlights showing functions |
553 # Highlights showing functions |
553 #------------------------------------------------------------------------------- |
554 # ------------------------------------------------------------------------------- |
554 |
555 |
555 def OnRefreshHighlightsTimer(self, event): |
556 def OnRefreshHighlightsTimer(self, event): |
556 self.RefreshView(True) |
557 self.RefreshView(True) |
557 event.Skip() |
558 event.Skip() |
558 |
559 |
573 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
574 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
574 self.RefreshView() |
575 self.RefreshView() |
575 |
576 |
576 def RemoveHighlight(self, start, end, highlight_type): |
577 def RemoveHighlight(self, start, end, highlight_type): |
577 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
578 highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None) |
578 if (highlight_type is not None and |
579 if highlight_type is not None and \ |
579 (start, end, highlight_type) in self.Highlights): |
580 (start, end, highlight_type) in self.Highlights: |
580 self.Highlights.remove((start, end, highlight_type)) |
581 self.Highlights.remove((start, end, highlight_type)) |
581 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
582 self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) |
582 |
583 |
583 def ShowHighlights(self): |
584 def ShowHighlights(self): |
584 for start, end, highlight_type in self.Highlights: |
585 for start, end, highlight_type in self.Highlights: |
594 self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type) |
595 self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type) |
595 self.StartStyling(highlight_end_pos, 0x00) |
596 self.StartStyling(highlight_end_pos, 0x00) |
596 self.SetStyling(len(self.GetText()) - highlight_end_pos, stc.STC_STYLE_DEFAULT) |
597 self.SetStyling(len(self.GetText()) - highlight_end_pos, stc.STC_STYLE_DEFAULT) |
597 |
598 |
598 |
599 |
599 #------------------------------------------------------------------------------- |
600 # ------------------------------------------------------------------------------- |
600 # Helper for VariablesGrid values |
601 # Helper for VariablesGrid values |
601 #------------------------------------------------------------------------------- |
602 # ------------------------------------------------------------------------------- |
602 |
603 |
603 class VariablesTable(CustomTable): |
604 class VariablesTable(CustomTable): |
604 |
605 |
605 def GetValue(self, row, col): |
606 def GetValue(self, row, col): |
606 if row < self.GetNumberRows(): |
607 if row < self.GetNumberRows(): |
658 ("AddVariableButton", "add_element", _("Add variable")), |
659 ("AddVariableButton", "add_element", _("Add variable")), |
659 ("DeleteVariableButton", "remove_element", _("Remove variable")), |
660 ("DeleteVariableButton", "remove_element", _("Remove variable")), |
660 ("UpVariableButton", "up", _("Move variable up")), |
661 ("UpVariableButton", "up", _("Move variable up")), |
661 ("DownVariableButton", "down", _("Move variable down"))]: |
662 ("DownVariableButton", "down", _("Move variable down"))]: |
662 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
663 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
663 size=wx.Size(28, 28), style=wx.NO_BORDER) |
664 size=wx.Size(28, 28), style=wx.NO_BORDER) |
664 button.SetToolTipString(help) |
665 button.SetToolTipString(help) |
665 setattr(self, name, button) |
666 setattr(self, name, button) |
666 controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM) |
667 controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM) |
667 |
668 |
668 self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL) |
669 self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL) |
674 self.SetSizer(main_sizer) |
675 self.SetSizer(main_sizer) |
675 |
676 |
676 self.ParentWindow = window |
677 self.ParentWindow = window |
677 self.Controler = controler |
678 self.Controler = controler |
678 |
679 |
679 self.VariablesDefaultValue = {"Name" : "", "Type" : DefaultType, "Initial": "", |
680 self.VariablesDefaultValue = { |
680 "Description":"", "OnChange":"", "Options":""} |
681 "Name": "", |
|
682 "Type": DefaultType, |
|
683 "Initial": "", |
|
684 "Description": "", |
|
685 "OnChange": "", |
|
686 "Options": "" |
|
687 } |
681 self.Table = VariablesTable(self, [], self.GetVariableTableColnames()) |
688 self.Table = VariablesTable(self, [], self.GetVariableTableColnames()) |
682 self.ColAlignements = [wx.ALIGN_RIGHT] + \ |
689 self.ColAlignements = [wx.ALIGN_RIGHT] + \ |
683 [wx.ALIGN_LEFT]*(len(self.VariablesDefaultValue)) |
690 [wx.ALIGN_LEFT]*(len(self.VariablesDefaultValue)) |
684 self.ColSizes = [20, 150] + [130]*(len(self.VariablesDefaultValue)-1) |
691 self.ColSizes = [20, 150] + [130]*(len(self.VariablesDefaultValue)-1) |
685 self.VariablesGrid.SetTable(self.Table) |
692 self.VariablesGrid.SetTable(self.Table) |
733 self.VariablesGrid.SetColAttr(col, attr) |
740 self.VariablesGrid.SetColAttr(col, attr) |
734 self.VariablesGrid.SetColSize(col, self.ColSizes[col]) |
741 self.VariablesGrid.SetColSize(col, self.ColSizes[col]) |
735 self.Table.ResetView(self.VariablesGrid) |
742 self.Table.ResetView(self.VariablesGrid) |
736 |
743 |
737 def GetVariableTableColnames(self): |
744 def GetVariableTableColnames(self): |
738 _ = lambda x : x |
745 _ = NoTranslate |
739 return ["#", _("Name"),_("Type"), _("Initial"), _("Description"), _("OnChange"), _("Options")] |
746 return ["#", |
|
747 _("Name"), |
|
748 _("Type"), |
|
749 _("Initial"), |
|
750 _("Description"), |
|
751 _("OnChange"), |
|
752 _("Options")] |
740 |
753 |
741 def RefreshModel(self): |
754 def RefreshModel(self): |
742 self.Controler.SetVariables(self.Table.GetData()) |
755 self.Controler.SetVariables(self.Table.GetData()) |
743 self.RefreshBuffer() |
756 self.RefreshBuffer() |
744 |
757 |
757 |
770 |
758 def DoGetBestSize(self): |
771 def DoGetBestSize(self): |
759 return self.ParentWindow.GetPanelBestSize() |
772 return self.ParentWindow.GetPanelBestSize() |
760 |
773 |
761 def ShowErrorMessage(self, message): |
774 def ShowErrorMessage(self, message): |
762 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) |
775 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR) |
763 dialog.ShowModal() |
776 dialog.ShowModal() |
764 dialog.Destroy() |
777 dialog.Destroy() |
765 |
778 |
766 def OnVariablesGridCellChange(self, event): |
779 def OnVariablesGridCellChange(self, event): |
767 row, col = event.GetRow(), event.GetCol() |
780 row, col = event.GetRow(), event.GetCol() |
829 if event.GetCol() == 0: |
842 if event.GetCol() == 0: |
830 row = event.GetRow() |
843 row = event.GetRow() |
831 data_type = self.Table.GetValueByName(row, "Type") |
844 data_type = self.Table.GetValueByName(row, "Type") |
832 var_name = self.Table.GetValueByName(row, "Name") |
845 var_name = self.Table.GetValueByName(row, "Name") |
833 data = wx.TextDataObject(str((var_name, "Global", data_type, |
846 data = wx.TextDataObject(str((var_name, "Global", data_type, |
834 self.Controler.GetCurrentLocation()))) |
847 self.Controler.GetCurrentLocation()))) |
835 dragSource = wx.DropSource(self.VariablesGrid) |
848 dragSource = wx.DropSource(self.VariablesGrid) |
836 dragSource.SetData(data) |
849 dragSource.SetData(data) |
837 dragSource.DoDragDrop() |
850 dragSource.DoDragDrop() |
838 return |
851 return |
839 event.Skip() |
852 event.Skip() |
840 |
853 |
841 |
854 |
842 #------------------------------------------------------------------------------- |
855 # ------------------------------------------------------------------------------- |
843 # CodeFileEditor Main Frame Class |
856 # CodeFileEditor Main Frame Class |
844 #------------------------------------------------------------------------------- |
857 # ------------------------------------------------------------------------------- |
845 |
858 |
846 class CodeFileEditor(ConfTreeNodeEditor): |
859 class CodeFileEditor(ConfTreeNodeEditor): |
847 |
860 |
848 CONFNODEEDITOR_TABS = [] |
861 CONFNODEEDITOR_TABS = [] |
849 CODE_EDITOR = None |
862 CODE_EDITOR = None |
851 def _create_CodePanel(self, prnt): |
864 def _create_CodePanel(self, prnt): |
852 self.CodeEditorPanel = wx.SplitterWindow(prnt) |
865 self.CodeEditorPanel = wx.SplitterWindow(prnt) |
853 self.CodeEditorPanel.SetMinimumPaneSize(1) |
866 self.CodeEditorPanel.SetMinimumPaneSize(1) |
854 |
867 |
855 self.VariablesPanel = VariablesEditor(self.CodeEditorPanel, |
868 self.VariablesPanel = VariablesEditor(self.CodeEditorPanel, |
856 self.ParentWindow, self.Controler) |
869 self.ParentWindow, |
|
870 self.Controler) |
857 |
871 |
858 if self.CODE_EDITOR is not None: |
872 if self.CODE_EDITOR is not None: |
859 self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel, |
873 self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel, |
860 self.ParentWindow, self.Controler) |
874 self.ParentWindow, self.Controler) |
861 |
875 |
862 self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel, |
876 self.CodeEditorPanel.SplitHorizontally(self.VariablesPanel, |
863 self.CodeEditor, 150) |
877 self.CodeEditor, 150) |
864 else: |
878 else: |
865 self.CodeEditorPanel.Initialize(self.VariablesPanel) |
879 self.CodeEditorPanel.Initialize(self.VariablesPanel) |
866 |
880 |
867 return self.CodeEditorPanel |
881 return self.CodeEditorPanel |
868 |
882 |
888 self.VariablesPanel.RefreshView() |
902 self.VariablesPanel.RefreshView() |
889 self.CodeEditor.RefreshView() |
903 self.CodeEditor.RefreshView() |
890 |
904 |
891 def Find(self, direction, search_params): |
905 def Find(self, direction, search_params): |
892 self.CodeEditor.Find(direction, search_params) |
906 self.CodeEditor.Find(direction, search_params) |
893 |
|