~ubuntu-branches/ubuntu/precise/wxwidgets2.8/precise-proposed

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/src/ed_basestc.py

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-01-07 13:59:25 UTC
  • mfrom: (1.1.9) (5.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120107135925-2601miy9ullcon9j
Tags: 2.8.12.1-6ubuntu1
* Resync from Debian, changes that were kept:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control: Build-dep on libxt-dev for mediactrl.
  - Patches
    + fix-bashism-in-example
* Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to python-wxversion
  to guarantee upgrade ordering when moving from pycentral to dh_python2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
"""
16
16
 
17
17
__author__ = "Cody Precord <cprecord@editra.org>"
18
 
__svnid__ = "$Id: ed_basestc.py 64304 2010-05-13 16:44:35Z CJP $"
19
 
__revision__ = "$Revision: 64304 $"
 
18
__svnid__ = "$Id: ed_basestc.py 67626 2011-04-27 02:51:39Z CJP $"
 
19
__revision__ = "$Revision: 67626 $"
20
20
 
21
21
#-----------------------------------------------------------------------------#
22
22
# Imports
23
23
import wx
24
24
import wx.stc
25
 
import types
26
25
 
27
26
# Editra Imports
28
27
import ed_glob
39
38
import plugin
40
39
import iface
41
40
import util
 
41
import ed_marker
42
42
 
43
43
#-----------------------------------------------------------------------------#
44
44
 
47
47
NUM_MARGIN  = 1
48
48
FOLD_MARGIN = 2
49
49
 
 
50
# Markers (3rd party)
 
51
MARKER_VERT_EDIT = ed_marker.NewMarkerId()
 
52
 
50
53
# Key code additions
51
54
ALT_SHIFT = wx.stc.STC_SCMOD_ALT|wx.stc.STC_SCMOD_SHIFT
52
55
CTRL_SHIFT = wx.stc.STC_SCMOD_CTRL|wx.stc.STC_SCMOD_SHIFT
59
62
 
60
63
    """
61
64
    ED_STC_MASK_MARKERS = ~wx.stc.STC_MASK_FOLDERS
62
 
    def __init__(self, parent, id_,
 
65
    def __init__(self, parent, id_=wx.ID_ANY,
63
66
                 pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
64
67
        wx.stc.StyledTextCtrl.__init__(self, parent, id_, pos, size, style)
65
68
        ed_style.StyleMgr.__init__(self, self.GetStyleSheet())
74
77
                          indenter=None,    # Auto indenter
75
78
                          lang_id=0)        # Language ID from syntax module
76
79
 
77
 
        self.vert_edit = vertedit.VertEdit(self)
 
80
        self.vert_edit = vertedit.VertEdit(self, markerNumber=MARKER_VERT_EDIT)
78
81
        self._line_num = True # Show line numbers
 
82
        self._last_cwidth = 1 # one pixel
79
83
 
80
84
        # Set Up Margins
81
85
        ## Outer Left Margin Bookmarks
82
86
        self.SetMarginType(MARK_MARGIN, wx.stc.STC_MARGIN_SYMBOL)
83
 
        self.SetMarginMask(MARK_MARGIN, self.ED_STC_MASK_MARKERS)
 
87
        self.SetMarginMask(MARK_MARGIN, EditraBaseStc.ED_STC_MASK_MARKERS)
84
88
        self.SetMarginSensitive(MARK_MARGIN, True)
85
 
        self.SetMarginWidth(MARK_MARGIN, 12)
 
89
        self.SetMarginWidth(MARK_MARGIN, 16)
86
90
 
87
91
        ## Middle Left Margin Line Number Indication
88
92
        self.SetMarginType(NUM_MARGIN, wx.stc.STC_MARGIN_NUMBER)
98
102
            for keys in _GetMacKeyBindings():
99
103
                self.CmdKeyAssign(*keys)
100
104
 
101
 
        # Setup Autocomp images
 
105
        # Setup Auto-comp images
102
106
        # TODO: should be called on theme change messages
103
107
        self.RegisterImages()
104
108
 
105
109
        # Event Handlers
 
110
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
106
111
        self.Bind(wx.stc.EVT_STC_CHANGE, self.OnChanged)
107
112
        self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified)
108
113
        self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnAutoCompSel)
109
114
 
110
 
    def __del__(self):
111
 
        # Cleanup the file object callbacks
112
 
        self.file.RemoveModifiedCallback(self.FireModified)
113
 
        self.file.CleanUp()
 
115
    def OnDestroy(self, evt):
 
116
        if evt.GetId() == self.GetId():
 
117
            # Cleanup the file object callbacks
 
118
            self.file.RemoveModifiedCallback(self.FireModified)
 
119
            self.file.CleanUp()
 
120
        evt.Skip()
114
121
 
115
122
    #---- Public Methods ----#
116
123
 
117
 
    def AddBookmark(self):
118
 
        """Add a bookmark and return its handle"""
119
 
        cline = self.GetCurrentLine()
120
 
        return self.MarkerAdd(cline, MARK_MARGIN)
 
124
    # General marker api
 
125
    def AddMarker(self, marker, line=-1):
 
126
        """Add a bookmark and return its handle
 
127
        @param marker: ed_marker.Marker instance
 
128
        @keyword line: if < 0 bookmark will be added to current line
 
129
 
 
130
        """
 
131
        assert isinstance(marker, ed_marker.Marker)
 
132
        if line < 0:
 
133
            line = self.GetCurrentLine()
 
134
        marker.Set(self, line)
 
135
        return marker.Handle
 
136
 
 
137
    def RemoveMarker(self, marker, line):
 
138
        """Remove the book mark from the given line
 
139
        @param marker: ed_marker.Marker instance
 
140
        @param line: int
 
141
 
 
142
        """
 
143
        assert isinstance(marker, ed_marker.Marker)
 
144
        marker.Set(self, line, delete=True)
 
145
 
 
146
    def RemoveAllMarkers(self, marker):
 
147
        """Remove all the bookmarks in the buffer
 
148
        @param marker: ed_marker.Marker instance
 
149
 
 
150
        """
 
151
        assert isinstance(marker, ed_marker.Marker)
 
152
        marker.DeleteAll(self)
 
153
 
 
154
    #-- Breakpoint marker api --#
 
155
    def DeleteAllBreakpoints(self):
 
156
        """Delete all the breakpoints in the buffer"""
 
157
        ed_marker.Breakpoint().DeleteAll(self)
 
158
        ed_marker.BreakpointDisabled().DeleteAll(self)
 
159
        ed_marker.BreakpointStep().DeleteAll(self)
 
160
 
 
161
    def DeleteBreakpoint(self, line):
 
162
        """Delete the breakpoint from the given line"""
 
163
        ed_marker.Breakpoint().Set(self, line, delete=True)
 
164
        ed_marker.BreakpointDisabled().Set(self, line, delete=True)
 
165
 
 
166
    def _SetBreakpoint(self, mobj, line=-1):
 
167
        """Set the breakpoint state
 
168
        @param mtype: Marker object
 
169
        @return: int (-1 if already set)
 
170
 
 
171
        """
 
172
        handle = -1
 
173
        if line < 0:
 
174
            line = self.GetCurrentLine()
 
175
        if not mobj.IsSet(self, line):
 
176
            # Clear other set breakpoint marker states on same line
 
177
            ed_marker.Breakpoint().Set(self, line, delete=True)
 
178
            ed_marker.BreakpointDisabled().Set(self, line, delete=True)
 
179
            mobj.Set(self, line, delete=False)
 
180
            handle = mobj.Handle
 
181
        return handle
 
182
 
 
183
    def SetBreakpoint(self, line=-1, disabled=False):
 
184
        """Set a breakpoint marker on the given line
 
185
        @keyword line: line number
 
186
        @keyword disabled: bool
 
187
        @return: breakpoint handle
 
188
 
 
189
        """
 
190
        if not disabled:
 
191
            handle = self._SetBreakpoint(ed_marker.Breakpoint(), line)
 
192
        else:
 
193
            handle = self._SetBreakpoint(ed_marker.BreakpointDisabled(), line)
 
194
        return handle
 
195
 
 
196
    def ShowStepMarker(self, line=-1, show=True):
 
197
        """Show the step (arrow) marker to the given line."""
 
198
        if line < 0:
 
199
            line = self.GetCurrentLine()
 
200
        mark = ed_marker.BreakpointStep()
 
201
        if show:
 
202
            mark.Set(self, line, delete=False)
 
203
        else:
 
204
            mark.DeleteAll(self)
121
205
 
122
206
    def AddLine(self, before=False, indent=False):
123
207
        """Add a new line to the document
139
223
 
140
224
    def AutoIndent(self):
141
225
        """Indent from the current position to match the indentation
142
 
        of the previous line.
143
 
        @postcondition: proper type of white space is added from current pos
144
 
                        to match that of indentation in above line
 
226
        of the previous line. Unless the current file type has registered
 
227
        a custom AutoIndenter in which case it will implement its own
 
228
        behavior.
 
229
 
145
230
        """
146
231
        cpos = self.GetCurrentPos()
147
232
 
148
233
        # Check if a special purpose indenter has been registered
149
234
        if self._code['indenter'] is not None:
150
 
            txt = self._code['indenter'](self, cpos, self.GetIndentChar())
151
 
            txt = txt.replace('\n', self.GetEOLChar())
 
235
            self.BeginUndoAction()
 
236
            self._code['indenter'](self, cpos, self.GetIndentChar())
 
237
            self.EndUndoAction()
152
238
        else:
153
239
            # Default Indenter
154
240
            line = self.GetCurrentLine()
161
247
            i_space = indent / self.GetTabWidth()
162
248
            ndent = self.GetEOLChar() + self.GetIndentChar() * i_space
163
249
            txt = ndent + ((indent - (self.GetTabWidth() * i_space)) * u' ')
 
250
            self.AddText(txt)
164
251
 
165
 
        self.AddText(txt)
166
252
        self.EnsureCaretVisible()
167
253
 
168
254
    def BackTab(self):
217
303
            # There is a selection
218
304
            super(EditraBaseStc, self).BackTab()
219
305
 
220
 
    def BraceBadLight(self, pos):
221
 
        """Highlight the character at the given position
222
 
        @param pos: position of character to highlight with STC_STYLE_BRACEBAD
223
 
 
224
 
        """
225
 
        # Check if we are still alive or not, as this may be called
226
 
        # after we have been deleted.
227
 
        if isinstance(self, wx.stc.StyledTextCtrl):
228
 
            super(EditraBaseStc, self).BraceBadLight(pos)
229
 
 
230
306
    def SetBlockCaret(self):
231
307
        """Change caret style to block"""
232
308
        # XXX: This doesn't seem to be working with this wxPython version.
239
315
        self.SetCaretWidth(1)
240
316
#        self.SendMsg(2512, 1)
241
317
 
 
318
    def BraceBadLight(self, pos):
 
319
        """Highlight the character at the given position
 
320
        @param pos: position of character to highlight with STC_STYLE_BRACEBAD
 
321
 
 
322
        """
 
323
        # Check if we are still alive or not, as this may be called
 
324
        # after we have been deleted.
 
325
        if self:
 
326
            super(EditraBaseStc, self).BraceBadLight(pos)
 
327
 
242
328
    def BraceHighlight(self, pos1, pos2):
243
329
        """Highlight characters at pos1 and pos2
244
330
        @param pos1: position of char 1
247
333
        """
248
334
        # Check if we are still alive or not, as this may be called
249
335
        # after we have been deleted.
250
 
        if isinstance(self, wx.stc.StyledTextCtrl):
 
336
        if self:
251
337
            super(EditraBaseStc, self).BraceHighlight(pos1, pos2)
252
338
 
253
339
    def CanCopy(self):
373
459
        @postcondition: all margin markers are defined
374
460
 
375
461
        """
 
462
        # Get the colours for the various markers
376
463
        style = self.GetItemByName('foldmargin_style')
377
 
        # The foreground/background settings for the marker column seem to
378
 
        # backwards from what the parameters take so use our Fore color for
379
 
        # the stcs back and visa versa for our Back color.
380
464
        back = style.GetFore()
381
465
        rgb = eclib.HexToRGB(back[1:])
382
466
        back = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
385
469
        rgb = eclib.HexToRGB(fore[1:])
386
470
        fore = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2])
387
471
 
388
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,
389
 
                          wx.stc.STC_MARK_BOXMINUS, fore, back)
390
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,
391
 
                          wx.stc.STC_MARK_BOXPLUS,  fore, back)
392
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,
393
 
                          wx.stc.STC_MARK_VLINE, fore, back)
394
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,
395
 
                          wx.stc.STC_MARK_LCORNER, fore, back)
396
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,
397
 
                          wx.stc.STC_MARK_BOXPLUSCONNECTED, fore, back)
398
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID,
399
 
                          wx.stc.STC_MARK_BOXMINUSCONNECTED, fore, back)
400
 
        self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL,
401
 
                          wx.stc.STC_MARK_TCORNER, fore, back)
402
 
        self.MarkerDefine(0, wx.stc.STC_MARK_SHORTARROW, fore, back)
403
 
        self.SetFoldMarginHiColour(True, fore)
404
 
        self.SetFoldMarginColour(True, fore)
 
472
        # Buffer background highlight
 
473
        caret_line = self.GetItemByName('caret_line').GetBack()
 
474
        rgb = eclib.HexToRGB(caret_line[1:])
 
475
        clback = wx.Colour(*rgb)
 
476
 
 
477
        # Code Folding markers
 
478
        folder = ed_marker.FoldMarker()
 
479
        folder.Foreground = fore
 
480
        folder.Background = back
 
481
        folder.RegisterWithStc(self)
 
482
 
 
483
        # Bookmarks
 
484
        ed_marker.Bookmark().RegisterWithStc(self)
 
485
 
 
486
        # Breakpoints
 
487
        ed_marker.Breakpoint().RegisterWithStc(self)
 
488
        ed_marker.BreakpointDisabled().RegisterWithStc(self)
 
489
        step = ed_marker.BreakpointStep()
 
490
        step.Background = clback
 
491
        step.RegisterWithStc(self)
 
492
        ed_marker.StackMarker().RegisterWithStc(self)
 
493
 
 
494
        # Other markers
 
495
        errmk = ed_marker.ErrorMarker()
 
496
        errsty = self.GetItemByName('error_style')
 
497
        rgb = eclib.HexToRGB(errsty.GetBack()[1:])
 
498
        errmk.Background = wx.Colour(*rgb)
 
499
        rgb = eclib.HexToRGB(errsty.GetFore()[1:])
 
500
        errmk.Foreground = wx.Colour(*rgb)
 
501
        errmk.RegisterWithStc(self)
 
502
        # Lint Marker
 
503
        ed_marker.LintMarker().RegisterWithStc(self)
 
504
        ed_marker.LintMarkerWarning().RegisterWithStc(self)
 
505
        ed_marker.LintMarkerError().RegisterWithStc(self)
405
506
 
406
507
    def DoZoom(self, mode):
407
508
        """Zoom control in or out
464
565
 
465
566
    @property
466
567
    def File(self):
 
568
        """Reference to this buffers file object"""
467
569
        return self.file
468
570
 
469
571
    def FindLexer(self, set_ext=u''):
475
577
        if set_ext != u'':
476
578
            ext = set_ext.lower()
477
579
        else:
478
 
            ext = self.file.GetExtension()
 
580
            ext = self.file.GetExtension().lower()
 
581
 
 
582
        if ext == u'':
 
583
            fname = self.GetFileName()
 
584
            ext = ebmlib.GetFileName(fname).lower()
 
585
 
479
586
        self.ClearDocumentStyle()
480
587
 
481
588
        # Configure Lexer from File Extension
488
595
            if interp != wx.EmptyString:
489
596
                interp = interp.split(u"/")[-1]
490
597
                interp = interp.strip().split()
491
 
                if len(interp) and interp[-1][0] != "-":
 
598
                if len(interp) and interp[-1][0] != u"-":
492
599
                    interp = interp[-1]
493
600
                elif len(interp):
494
601
                    interp = interp[0]
495
602
                else:
496
603
                    interp = u''
 
604
                # TODO: should check user config to ensure the explict
 
605
                #       extension is still associated with the expected
 
606
                #       file type.
497
607
                ex_map = { "python" : "py", "wish" : "tcl", "ruby" : "rb",
498
608
                           "bash" : "sh", "csh" : "csh", "perl" : "pl",
499
609
                           "ksh" : "ksh", "php" : "php", "booi" : "boo",
506
616
        self.OnChanged(wx.stc.StyledTextEvent(wx.stc.wxEVT_STC_CHANGE,
507
617
                                              self.GetId()))
508
618
 
509
 
    def GetCommandStr(self):
 
619
    def GetCommandStr(self, line=None, col=None):
510
620
        """Gets the command string to the left of the autocomp
511
621
        activation character.
 
622
        @keyword line: optional if None current cursor position used
 
623
        @keyword col: optional if None current cursor position used
512
624
        @return: the command string to the left of the autocomp char
513
625
        @todo: fillups are currently disabled. See note in Configure.
514
626
 
515
627
        """
516
 
        # NOTE: the column position returned by GetCurLine is not correct
517
 
        #       for multibyte characters.
518
 
        line, col = self.GetCurLine()
519
 
        col = self.GetColumn(self.GetCurrentPos())
 
628
        if None in (line, col):
 
629
            # NOTE: the column position returned by GetCurLine is not correct
 
630
            #       for multibyte characters.
 
631
            line, col = self.GetCurLine()
 
632
            col = self.GetColumn(self.GetCurrentPos())
 
633
        line = line.expandtabs(self.GetTabWidth())
520
634
        cmd_lmt = list(self._code['compsvc'].GetAutoCompStops() + \
521
635
                       self._code['compsvc'].GetAutoCompFillups())
522
636
        for key in self._code['compsvc'].GetAutoCompKeys():
646
760
        pos = max(0, pos-1)
647
761
        return 'comment' in self.FindTagById(self.GetStyleAt(pos))
648
762
 
 
763
    def HasMarker(self, line, marker):
 
764
        """Check if the given line has the given marker set
 
765
        @param line: line number
 
766
        @param marker: marker id
 
767
 
 
768
        """
 
769
        mask = self.MarkerGet(line)
 
770
        return bool(1<<marker & mask)
 
771
 
649
772
    def HasSelection(self):
650
773
        """Check if there is a selection in the buffer
651
774
        @return: bool
667
790
            bMulti = sline != eline
668
791
        return bMulti
669
792
 
 
793
    def CallTipCancel(self):
 
794
        """Cancel any active calltip(s)"""
 
795
        if self.CallTipActive():
 
796
            super(EditraBaseStc, self).CallTipCancel()
 
797
 
 
798
    def CallTipShow(self, position, tip):
 
799
        """Show a calltip at the given position in the control
 
800
        @param position: int
 
801
        @param tip: unicode
 
802
 
 
803
        """
 
804
        self.CallTipCancel()
 
805
        super(EditraBaseStc, self).CallTipShow(position, tip)
 
806
 
670
807
    def HidePopups(self):
671
808
        """Hide autocomp/calltip popup windows if any are active"""
672
809
        if self.AutoCompActive():
673
810
            self.AutoCompCancel()
674
811
 
675
 
        if self.CallTipActive():
676
 
            self.CallTipCancel()
 
812
        self.CallTipCancel()
677
813
 
678
814
    def InitCompleter(self):
679
815
        """(Re)Initialize a completer object for this buffer
973
1109
        @param command: command to  look for calltips for
974
1110
 
975
1111
        """
976
 
        if self.CallTipActive():
977
 
            self.CallTipCancel()
 
1112
        self.CallTipCancel()
978
1113
 
979
1114
        tip = self._code['compsvc'].GetCallTip(command)
980
1115
        if len(tip):
1033
1168
        return self.vert_edit
1034
1169
 
1035
1170
    #---- Style Function Definitions ----#
 
1171
 
1036
1172
    def RefreshStyles(self):
1037
1173
        """Refreshes the colorization of the window by reloading any
1038
1174
        style tags that may have been modified.
1056
1192
            sback = sback.GetBack()
1057
1193
        else:
1058
1194
            sback = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
1059
 
        self.vert_edit.SetBlockColor(sback)
 
1195
        self.VertEdit.SetBlockColor(sback)
1060
1196
        self.DefineMarkers()
1061
1197
 
1062
1198
#-----------------------------------------------------------------------------#