root/branch/twedit/code_editor.py

Revision 1248, 28.2 kB (checked in by mswat, 2 years ago)

Added twedit editor

Line 
1#------------------------------------------------------------------------------
2# Copyright (c) 2007, Riverbank Computing Limited
3# All rights reserved.
4#
5# This software is provided without warranty under the terms of the BSD license.
6# However, when used with the GPL version of PyQt the additional terms described in the PyQt GPL exception also apply
7
8#
9# Author: Riverbank Computing Limited
10#------------------------------------------------------------------------------
11
12""" Defines a source code editor and code editor factory, for the PyQt user
13interface toolkit, useful for tools such as debuggers.
14"""
15
16#-------------------------------------------------------------------------------
17#  Imports:
18#-------------------------------------------------------------------------------
19
20from PyQt4 import QtCore, QtGui, Qsci
21from PyQt4.Qsci import QsciScintillaBase as QsciBase
22
23# Only QScintilla version 2.3+ has support for custom lexing
24if Qsci.QSCINTILLA_VERSION < 0x20300:
25    raise RuntimeError, "QScintilla version 2.3 or higher needed for CodeEditor"
26
27from enthought.traits.api import Str, Unicode, List, Int, Event, Bool, \
28    TraitError, on_trait_change
29from enthought.traits.trait_base import SequenceTypes
30
31# FIXME: ToolkitEditorFactory is a proxy class defined here just for backward
32# compatibility. The class has been moved to the
33# enthought.traits.ui.editors.code_editor file.
34from enthought.traits.ui.editors.code_editor import ToolkitEditorFactory
35
36from enthought.pyface.key_pressed_event import KeyPressedEvent
37from enthought.pyface.ui.qt4.python_editor import _Scintilla
38
39from constants import OKColor, ErrorColor   
40from editor import Editor
41from helper import pixmap_cache
42
43#-------------------------------------------------------------------------------
44#  Constants: 
45#-------------------------------------------------------------------------------
46       
47# Marker line constants:
48MARK_MARKER = 0 # Marks a marked line
49SEARCH_MARKER = 1 # Marks a line matching the current search
50SELECTED_MARKER = 2 # Marks the currently selected line
51
52# A map from Qt lexer constants to the corresponding concrete lexer:
53LEXER_MAP = { QsciBase.SCLEX_BASH: Qsci.QsciLexerBash,
54              QsciBase.SCLEX_BATCH: Qsci.QsciLexerBatch,
55              QsciBase.SCLEX_CMAKE: Qsci.QsciLexerCMake,
56              QsciBase.SCLEX_CPP: Qsci.QsciLexerCPP,
57              QsciBase.SCLEX_CSS: Qsci.QsciLexerCSS,
58              QsciBase.SCLEX_D: Qsci.QsciLexerD,
59              QsciBase.SCLEX_DIFF: Qsci.QsciLexerDiff,
60              QsciBase.SCLEX_FORTRAN: Qsci.QsciLexerFortran,
61              QsciBase.SCLEX_HTML: Qsci.QsciLexerHTML,
62              QsciBase.SCLEX_LUA: Qsci.QsciLexerLua,
63              QsciBase.SCLEX_MAKEFILE: Qsci.QsciLexerMakefile,
64              QsciBase.SCLEX_PASCAL: Qsci.QsciLexerPascal,
65              QsciBase.SCLEX_PERL: Qsci.QsciLexerPerl,
66              QsciBase.SCLEX_POV: Qsci.QsciLexerPOV,
67              QsciBase.SCLEX_PROPERTIES: Qsci.QsciLexerProperties,
68              QsciBase.SCLEX_PYTHON: Qsci.QsciLexerPython,
69              QsciBase.SCLEX_RUBY: Qsci.QsciLexerRuby,
70              QsciBase.SCLEX_SQL: Qsci.QsciLexerSQL,
71              QsciBase.SCLEX_TCL: Qsci.QsciLexerTCL,
72              QsciBase.SCLEX_TEX: Qsci.QsciLexerTeX,
73              QsciBase.SCLEX_VHDL: Qsci.QsciLexerVHDL,
74              QsciBase.SCLEX_XML: Qsci.QsciLexerXML,
75              QsciBase.SCLEX_YAML: Qsci.QsciLexerYAML }
76
77#-------------------------------------------------------------------------------
78#  'FindWidget' class:
79#-------------------------------------------------------------------------------
80
81class FindWidget ( QtGui.QWidget ):
82    """ A find widget a la the find bar in Firefox.
83    """
84
85    def __init__(self, callback, parent=None):
86        """ Creates a FindWidget. 'callback' should be function of signature:
87            (string text, bool forward, bool match_case).
88        """
89        QtGui.QWidget.__init__(self, parent)
90        self._callback = callback
91       
92        layout = QtGui.QHBoxLayout(self)
93        layout.setSpacing(5)
94        layout.setMargin(0)
95
96        self.close_button = QtGui.QToolButton(self)
97        self.close_button.setAutoRaise(True)
98        self.close_button.setIcon(QtGui.QIcon(pixmap_cache('closetab.png')))
99        QtCore.QObject.connect(self.close_button, QtCore.SIGNAL('clicked()'),
100                               self, QtCore.SLOT('hide()'))
101        layout.addWidget(self.close_button)
102
103        self.find_edit = QtGui.QLineEdit(self)
104        self.find_edit.setMinimumSize(QtCore.QSize(100, 0))
105        signal = QtCore.SIGNAL('textChanged(QString)')
106        QtCore.QObject.connect(self.find_edit, signal, self.update_buttons)
107        signal = QtCore.SIGNAL('returnPressed()')
108        QtCore.QObject.connect(self.find_edit, signal, self._next_clicked)
109        layout.addWidget(self.find_edit)
110
111        self.previous_button = QtGui.QToolButton(self)
112        self.previous_button.setAutoRaise(True)
113        self.previous_button.setIcon(QtGui.QIcon(pixmap_cache('previous.png')))
114        self.previous_button.setText('Previous')
115        self.previous_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
116        signal = QtCore.SIGNAL('clicked()')
117        QtCore.QObject.connect(self.previous_button, signal, self._previous_clicked)
118        layout.addWidget(self.previous_button)
119
120        self.next_button = QtGui.QToolButton(self)
121        self.next_button.setAutoRaise(True)
122        self.next_button.setIcon(QtGui.QIcon(pixmap_cache('next.png')))
123        self.next_button.setText('Next')
124        self.next_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
125        signal = QtCore.SIGNAL('clicked()')
126        QtCore.QObject.connect(self.next_button, signal, self._next_clicked)
127        layout.addWidget(self.next_button)
128
129        self.case_box = QtGui.QCheckBox('Match case', self)
130        layout.addWidget(self.case_box)
131
132        # Align items to left and prevent text field from growing too large
133        layout.addItem(QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Expanding,
134                                         QtGui.QSizePolicy.Minimum))
135
136        self.update_buttons()
137   
138    #---------------------------------------------------------------------------
139    #  QWidget interface: 
140    #---------------------------------------------------------------------------
141
142    def keyPressEvent(self, event):
143        """ Reimplemented to process Escape key.
144        """
145        if event.key() == QtCore.Qt.Key_Escape:
146            event.accept()
147            self.emit(QtCore.SIGNAL('hidden()'))
148            self.hide()
149        else:
150            QtGui.QWidget.keyPressEvent(self, event)
151
152    def showEvent(self, event):
153        """ Reimplemented to select all in text field and grab focus.
154        """
155        QtGui.QWidget.showEvent(self, event)
156
157        self.find_edit.selectAll()
158        self.find_edit.setFocus()
159
160    #---------------------------------------------------------------------------
161    #  FindWidget interface:
162    #---------------------------------------------------------------------------
163
164    def update_buttons(self, event=None):
165        """ Enable or disable buttons depending on state of text field.
166        """
167        if self.find_edit.text() == '':
168            self.previous_button.setEnabled(False)
169            self.next_button.setEnabled(False)
170        else:
171            self.previous_button.setEnabled(True)
172            self.next_button.setEnabled(True)
173
174    def _previous_clicked(self):
175        """ Handle the previous button being clicked.
176        """
177        self._callback(self.find_edit.text(), False, self.case_box.isChecked())
178
179    def _next_clicked(self):
180        """ Handle the previous button being clicked.
181        """
182        self._callback(self.find_edit.text(), True, self.case_box.isChecked())
183
184#-------------------------------------------------------------------------------
185#  'SourceLexer' class:
186#-------------------------------------------------------------------------------
187
188class SourceLexer ( Qsci.QsciLexerCustom ):
189    """ A custom lexer that first lexes according to an existing lexer (by
190        default the Python lexer), then dim and underlines lines as appropriate.
191    """
192   
193    def __init__(self, editor):
194        """ Store the editor.
195        """
196        Qsci.QsciLexerCustom.__init__(self, editor.control)
197        self._editor = editor
198   
199    def description(self, style):
200        """ Overriden because Qt balks if it is not. This is indended to be used
201            to store style preferences, but we don't care about that.
202        """
203        return QtCore.QString()
204
205    def styleText(self, start, end):
206        """ Overriden to perform custom styling.
207        """
208        control = self._editor._scintilla
209        start_line = control.lineIndexFromPosition(start)[0]
210        end_line = control.lineIndexFromPosition(end)[0]
211
212        # Fixes a strange a bug with the STC widget where creating a new line
213        # after a dimmed line causes it to mysteriously lose its styling
214        if start_line in self._editor.dim_lines:
215            start_line -= 1
216
217        # Trying to Colourise only the lines that we want does not seem to work
218        # so we do the whole area and then override the styling on certain lines
219        if self._editor.lexer != QsciBase.SCLEX_NULL:
220            control.SendScintilla(QsciBase.SCI_SETLEXER, self._editor.lexer)
221            control.SendScintilla(QsciBase.SCI_COLOURISE, start, end)
222            control.SendScintilla(QsciBase.SCI_SETLEXER,
223                                  QsciBase.SCLEX_CONTAINER)
224
225        for line in xrange(start_line, end_line+1):
226            # We don't use lineLength here because it includes newline
227            # characters. Styling these leads to strange behavior.
228            position = control.positionFromLineIndex(line, 0)
229            style_length = control.SendScintilla(
230                QsciBase.SCI_GETLINEENDPOSITION, line) - position
231
232            if line+1 in self._editor.dim_lines:
233                # Set styling mask to only style text bits, not indicator bits
234                self.startStyling(position, 0x1f)
235                self.setStyling(style_length, self._editor.dim_style_number)
236            elif self._editor.lexer == QsciBase.SCLEX_NULL:
237                self.startStyling(position, 0x1f)
238                self.setStyling(style_length, QsciBase.STYLE_DEFAULT)
239               
240            if line+1 in self._editor.squiggle_lines:
241                self.startStyling(position, QsciBase.INDIC2_MASK)
242                self.setStyling(style_length, QsciBase.INDIC2_MASK)
243            else:
244                self.startStyling(position, QsciBase.INDIC2_MASK)
245                self.setStyling(style_length, QsciBase.STYLE_DEFAULT)
246
247#-------------------------------------------------------------------------------
248#  'SourceEditor' class:
249#-------------------------------------------------------------------------------
250                               
251class SourceEditor ( Editor ):
252    """ Editor for source code which uses the QScintilla widget.
253    """
254
255    #---------------------------------------------------------------------------
256    #  PyFace PythonEditor interface:
257    #---------------------------------------------------------------------------
258
259    # Event that is fired on keypresses:
260    key_pressed = Event(KeyPressedEvent)
261
262    #---------------------------------------------------------------------------
263    #  Editor interface:
264    #---------------------------------------------------------------------------
265
266    # The code editor is scrollable. This value overrides the default.
267    scrollable = True
268   
269    #---------------------------------------------------------------------------
270    #  SoureEditor interface:
271    #---------------------------------------------------------------------------
272   
273    # Is the editor read only?
274    readonly = Bool( False )
275   
276    # The currently selected line
277    selected_line = Int
278   
279    # The currently selected text
280    selected_text = Unicode
281   
282    # The list of line numbers to mark
283    mark_lines = List( Int )
284   
285    # The current line number
286    line = Event
287   
288    # The current column
289    column = Event
290
291    # The Scintilla lexer to use
292    lexer = Int
293
294    # The lines to be dimmed
295    dim_lines = List(Int)
296    dim_color = Str
297    dim_style_number = Int(16) # 0-15 are reserved for the python lexer
298   
299    # The lines to have squiggles drawn under them
300    squiggle_lines = List(Int)
301    squiggle_color = Str
302       
303    #---------------------------------------------------------------------------
304    #  Finishes initializing the editor by creating the underlying toolkit
305    #  widget:
306    #---------------------------------------------------------------------------
307       
308    def init ( self, parent ):
309        """ Finishes initializing the editor by creating the underlying toolkit
310            widget.
311        """
312        self.control = QtGui.QWidget()
313        layout = QtGui.QVBoxLayout(self.control)
314        layout.setMargin(0)
315
316        # Create the QScintilla widget
317        factory = self.factory
318        self._scintilla = control = _Scintilla(self, None)
319        layout.addWidget(control)
320
321        # Connect to the QScintilla signals that we care about
322        if not self.readonly:
323            QtCore.QObject.connect(control, QtCore.SIGNAL('lostFocus'),
324                                   self.update_object)
325            if factory.auto_set:
326                control.connect(control, QtCore.SIGNAL('textChanged()'),
327                                self.update_object)
328        if (factory.line != '') or (factory.column != ''):
329            # We need to monitor the line or column position being changed
330            control.connect(control,
331                    QtCore.SIGNAL('cursorPositionChanged(int, int)'),
332                    self._position_changed)
333
334        # Create the find bar
335        self._find_widget = FindWidget(self.find, self.control)
336        self._find_widget.hide()
337        layout.addWidget(self._find_widget)
338       
339        # Make sure that the find bar will fit in the editor
340        min_width = self._find_widget.minimumSizeHint().width()
341        self.control.setMinimumWidth(min_width)
342
343        # Grab keyboard focus whenever the find bar is closed
344        QtCore.QObject.connect(self._find_widget, QtCore.SIGNAL('hidden()'),
345                               self._scintilla, QtCore.SLOT('setFocus()'))
346       
347        # Set up the lexer. Before we set our custom lexer, we call setLexer
348        # with the QSciLexer that will set the keywords and styles for the
349        # basic syntax lexing. We save and then restore these keywords/styles
350        # because they get nuked when we call setLexer again.
351        self.lexer = getattr(QsciBase, 'SCLEX_' + self.factory.lexer.upper(),
352                             QsciBase.SCLEX_NULL)
353        base_lexer_class = LEXER_MAP.get(self.lexer)
354        if base_lexer_class:
355            lexer = base_lexer_class(control)
356            control.setLexer(lexer)
357            keywords = lexer.keywords(1)
358            styles = []
359            attr_names = ['FORE', 'BACK', 'BOLD', 'ITALIC', 'SIZE', 'UNDERLINE']
360            for style in xrange(128):
361                attrs = [ control.SendScintilla(getattr(QsciBase,'SCI_STYLEGET'+a), style)
362                          for a in attr_names ]
363                styles.append(attrs)
364        lexer = SourceLexer(self)
365        control.setLexer(lexer)
366        if base_lexer_class:
367            if keywords:
368                control.SendScintilla(QsciBase.SCI_SETKEYWORDS, 0, keywords)
369            for style, attrs in enumerate(styles):
370                for attr_num, attr in enumerate(attrs):
371                    msg = getattr(QsciBase, 'SCI_STYLESET' + attr_names[attr_num])
372                    control.SendScintilla(msg, style, attr)
373
374        # Set a monspaced font. Use the (supposedly) same font and size as the
375        # wx version.
376        for style in xrange(128):
377            f = lexer.font(style)
378            f.setFamily('courier new')
379            f.setPointSize(10)
380            lexer.setFont(f, style)
381
382        # Mark the maximum line size.
383        control.setEdgeMode(Qsci.QsciScintilla.EdgeLine)
384        control.setEdgeColumn(79)
385
386        # Display line numbers in the margin.
387        if factory.show_line_numbers:
388            control.setMarginLineNumbers(1, True)
389            control.setMarginWidth(1, 45)
390        else:
391            control.setMarginWidth(1, 4)
392            control.setMarginsBackgroundColor(QtCore.Qt.white)
393
394        # Configure indentation and tabs.
395        control.setIndentationsUseTabs(False)
396        control.setTabWidth(4)
397
398        # Configure miscellaneous control settings:
399        control.setEolMode(Qsci.QsciScintilla.EolUnix)
400
401        if self.readonly:
402            control.setReadOnly(True)
403                                     
404        # Define the markers we use:
405        control.markerDefine(Qsci.QsciScintilla.Background, MARK_MARKER)
406        control.setMarkerBackgroundColor(factory.mark_color_, MARK_MARKER)
407
408        control.markerDefine(Qsci.QsciScintilla.Background, SEARCH_MARKER)
409        control.setMarkerBackgroundColor(factory.search_color_, SEARCH_MARKER)
410
411        control.markerDefine(Qsci.QsciScintilla.Background, SELECTED_MARKER)
412        control.setMarkerBackgroundColor(factory.selected_color_, SELECTED_MARKER)
413
414        # Make sure the editor has been initialized:
415        self.update_editor()
416       
417        # Set up any event listeners:
418        self.sync_value( factory.mark_lines, 'mark_lines', 'from',
419                         is_list = True )
420        self.sync_value( factory.selected_line, 'selected_line', 'from' )
421        self.sync_value( factory.selected_text, 'selected_text', 'to' )
422        self.sync_value( factory.line, 'line' )
423        self.sync_value( factory.column, 'column' )
424
425        self.sync_value(factory.dim_lines, 'dim_lines', 'from', is_list=True)
426        if self.factory.dim_color == '':
427            self.dim_color = 'grey'
428        else:
429            self.sync_value(factory.dim_color, 'dim_color', 'from')
430
431        self.sync_value(factory.squiggle_lines, 'squiggle_lines', 'from',
432                        is_list=True)
433        if factory.squiggle_color == '':
434            self.squiggle_color = 'red'
435        else:
436            self.sync_value(factory.squiggle_color, 'squiggle_color', 'from')
437
438        # Set the control tooltip:
439        self.set_tooltip()
440
441    #---------------------------------------------------------------------------
442    #  Disposes of the contents of an editor:   
443    #---------------------------------------------------------------------------
444               
445    def dispose ( self ):
446        """ Disposes of the contents of an editor.
447        """
448        # Make sure that the editor does not try to update as the control is
449        # being destroyed:
450        QtCore.QObject.disconnect(self._scintilla, QtCore.SIGNAL('lostFocus'),
451                                  self.update_object)
452
453        super( SourceEditor, self ).dispose()
454   
455    #---------------------------------------------------------------------------
456    #  Handles the user entering input data in the edit control:
457    #---------------------------------------------------------------------------
458
459    def update_object ( self ):
460        """ Handles the user entering input data in the edit control.
461        """
462        if not self._locked:
463            try:
464                value = unicode(self._scintilla.text())
465                if isinstance( self.value, SequenceTypes ):
466                    value = value.split()
467                self.value = value
468                self._scintilla.lexer().setPaper(OKColor)
469            except TraitError, excp:
470                pass
471       
472    #---------------------------------------------------------------------------
473    #  Updates the editor when the object trait changes external to the editor:
474    #---------------------------------------------------------------------------
475       
476    def update_editor ( self ):
477        """ Updates the editor when the object trait changes externally to the
478            editor.
479        """
480        self._locked = True
481        new_value = self.value
482        if isinstance( new_value, SequenceTypes ):
483            new_value = '\n'.join( [ line.rstrip() for line in new_value ] )
484        control = self._scintilla
485        if control.text() != new_value:
486            readonly = control.isReadOnly()
487            control.setReadOnly(False)
488            vsb = control.verticalScrollBar()
489            l1 = vsb.value()
490            line, column = control.getCursorPosition()
491            control.setText(new_value)
492            control.setCursorPosition(line, column)
493            vsb.setValue(l1)
494            control.setReadOnly(readonly)
495            self._mark_lines_changed()
496            if self.factory.selected_line:
497                self._selected_line_changed()
498        self._locked = False
499
500    #---------------------------------------------------------------------------
501    #  Handles an error that occurs while setting the object's trait value:
502    #---------------------------------------------------------------------------
503       
504    def error ( self, excp ):
505        """ Handles an error that occurs while setting the object's trait value.
506        """
507        self._scintilla.lexer().setPaper(ErrorColor)
508
509    #---------------------------------------------------------------------------
510    #  Finds and selects the next or previous match of text:
511    #---------------------------------------------------------------------------
512       
513    def find ( self, text, forward, match_case ):
514        """ Finds and selects the next or previous match of text.
515        """
516        line, index = self._scintilla.getCursorPosition()
517        if not forward:
518            index -= len(self._scintilla.selectedText())
519
520        # Arguments: expr, is regex, case_sensitive, whole words only, wrap
521        #            around, is forward, line, index in line
522        self._scintilla.findFirst(text, False, match_case, False, True, forward,
523                                  line, index)
524
525    #-- UI preference save/restore interface -----------------------------------
526
527    #---------------------------------------------------------------------------
528    #  Restores any saved user preference information associated with the
529    #  editor:
530    #---------------------------------------------------------------------------
531           
532    def restore_prefs ( self, prefs ):
533        """ Restores any saved user preference information associated with the
534            editor.
535        """
536        if self.factory.key_bindings is not None:
537            key_bindings = prefs.get( 'key_bindings' )
538            if key_bindings is not None:
539                self.factory.key_bindings.merge( key_bindings )
540           
541    #---------------------------------------------------------------------------
542    #  Returns any user preference information associated with the editor:
543    #---------------------------------------------------------------------------
544           
545    def save_prefs ( self ):
546        """ Returns any user preference information associated with the editor.
547        """
548        return { 'key_bindings': self.factory.key_bindings }
549       
550    #---------------------------------------------------------------------------
551    #  Handles the set of 'marked lines' being changed: 
552    #---------------------------------------------------------------------------
553               
554    def _mark_lines_changed ( self ):
555        """ Handles the set of marked lines being changed.
556        """
557        lines   = self.mark_lines
558        control = self._scintilla
559        lc      = control.lines()
560        control.markerDeleteAll(MARK_MARKER)
561        for line in lines:
562            if 0 < line <= lc:
563                control.markerAdd(line - 1, MARK_MARKER)
564
565    def _mark_lines_items_changed ( self ):
566        self._mark_lines_changed()
567       
568    #---------------------------------------------------------------------------
569    #  Handles the currently 'selected line' being changed: 
570    #---------------------------------------------------------------------------
571               
572    def _selected_line_changed ( self ):
573        """ Handles a change in which line is currently selected.
574        """
575        line    = self.selected_line
576        control = self._scintilla
577        line    = max(1, min(control.lines(), line)) - 1
578        control.markerDeleteAll(SELECTED_MARKER)
579        control.markerAdd(line, SELECTED_MARKER)
580        _, column = control.getCursorPosition()
581        control.setCursorPosition(line, column)
582        if self.factory.auto_scroll:
583            control.ensureLineVisible(line)
584
585    #---------------------------------------------------------------------------
586    #  Handles the 'line' trait being changed: 
587    #---------------------------------------------------------------------------
588                                             
589    def _line_changed ( self, line ):
590        if not self._locked:
591            control = self._scintilla
592            _, column = control.getCursorPosition()
593            self._scintilla.setCursorPosition(line - 1, column)
594                                 
595    #---------------------------------------------------------------------------
596    #  Handles the 'column' trait being changed: 
597    #---------------------------------------------------------------------------
598                                             
599    def _column_changed ( self, column ):
600        if not self._locked:
601            control = self._scintilla
602            line, _ = control.getCursorPosition()
603            self._scintilla.setCursorPosition(line, column - 1)
604
605    #---------------------------------------------------------------------------
606    #  Handles the cursor position being changed: 
607    #---------------------------------------------------------------------------
608                       
609    def _position_changed(self, line, column):
610        """ Handles the cursor position being changed.
611        """
612        control = self._scintilla
613        self._locked = True
614        self.line = line
615        self.column = column
616        self._locked = False
617        self.selected_text = unicode(control.selectedText())
618       
619    #---------------------------------------------------------------------------
620    #  Handles a key being pressed within the editor:   
621    #---------------------------------------------------------------------------
622               
623    def _key_pressed_changed ( self, event ):
624        """ Handles a key being pressed within the editor.
625        """
626        key_bindings = self.factory.key_bindings
627        if key_bindings:
628            processed = key_bindings.do(event.event, self.ui.handler,
629                                        self.ui.info)
630        else:
631            processed = False
632        if not processed and event.event.matches(QtGui.QKeySequence.Find):
633            self._find_widget.show()
634
635    #---------------------------------------------------------------------------
636    #  Handles the styling of the editor:
637    #---------------------------------------------------------------------------
638
639    def _dim_color_changed(self):
640        self._scintilla.SendScintilla(QsciBase.SCI_STYLESETFORE,
641                                      self.dim_style_number,
642                                      QtGui.QColor(self.dim_color))
643
644    def _squiggle_color_changed(self):
645        self._scintilla.SendScintilla(QsciBase.SCI_INDICSETSTYLE, 2,
646                                      QsciBase.INDIC_SQUIGGLE)
647        self._scintilla.SendScintilla(QsciBase.SCI_INDICSETFORE, 2,
648                                      QtGui.QColor(self.squiggle_color))
649
650    @on_trait_change('dim_lines, squiggle_lines')
651    def _style_document(self):
652        self._scintilla.recolor()
653
654
655# Define the simple, custom, text and readonly editors, which will be accessed
656# by the editor factory for code editors.
657
658CustomEditor = SimpleEditor = TextEditor = SourceEditor
659
660class ReadonlyEditor(SourceEditor):
661
662    # Set the value of the readonly trait.
663    readonly = True
Note: See TracBrowser for help on using the browser.