1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.editor.wxEditor
3 # Purpose: An intelligent text editor with colorization capabilities.
6 # Authors: Dirk Holtwic, Robin Dunn
9 # Authors: Adam Feuer, Steve Howell
12 # This code used to support a fairly complex subclass that did
13 # syntax coloring and outliner collapse mode. Adam and Steve
14 # inherited the code, and added a lot of basic editor
15 # functionality that had not been there before, such as cut-and-paste.
18 # Created: 15-Dec-1999
20 # Copyright: (c) 1999 by Dirk Holtwick, 1999
21 # Licence: wxWindows license
22 #----------------------------------------------------------------------
26 from wxPython
.wx
import *
31 #----------------------------
33 def ForceBetween(min, val
, max):
41 def LineTrimmer(lineOfText
):
42 if len(lineOfText
) == 0:
44 elif lineOfText
[-1] == '\r':
45 return lineOfText
[:-1]
49 def LineSplitter(text
):
50 return map (LineTrimmer
, text
.split('\n'))
53 #----------------------------
56 def __init__(self
, parent
):
63 def SetScrollbars(self
, fw
, fh
, w
, h
, x
, y
):
64 if (self
.ow
!= w
or self
.oh
!= h
or self
.ox
!= x
or self
.oy
!= y
):
65 self
.parent
.SetScrollbars(fw
, fh
, w
, h
, x
, y
)
71 #----------------------------------------------------------------------
73 class wxEditor(wxScrolledWindow
):
75 def __init__(self
, parent
, id,
76 pos
=wxDefaultPosition
, size
=wxDefaultSize
, style
=0):
78 wxScrolledWindow
.__init
__(self
, parent
, id,
82 self
.isDrawing
= False
89 self
.InitDoubleBuffering()
96 ##------------------ Init stuff
111 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
112 EVT_LEFT_UP(self
, self
.OnLeftUp
)
113 EVT_MOTION(self
, self
.OnMotion
)
114 EVT_SCROLLWIN(self
, self
.OnScroll
)
115 EVT_CHAR(self
, self
.OnChar
)
116 EVT_PAINT(self
, self
.OnPaint
)
117 EVT_SIZE(self
, self
.OnSize
)
118 EVT_WINDOW_DESTROY(self
, self
.OnDestroy
)
119 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
121 ##------------------- Platform-specific stuff
123 def NiceFontForPlatform(self
):
124 if wxPlatform
== "__WXMSW__":
125 return wxFont(10, wxMODERN
, wxNORMAL
, wxNORMAL
)
127 return wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, False)
129 def UnixKeyHack(self
, key
):
130 # this will be obsolete when we get the new wxWindows patch
135 ##-------------------- UpdateView/Cursor code
137 def OnSize(self
, event
):
138 self
.AdjustScrollbars()
141 def SetCharDimensions(self
):
142 # TODO: We need a code review on this. It appears that Linux
143 # improperly reports window dimensions when the scrollbar's there.
144 self
.bw
, self
.bh
= self
.GetClientSizeTuple()
146 if wxPlatform
== "__WXMSW__":
147 self
.sh
= self
.bh
/ self
.fh
148 self
.sw
= (self
.bw
/ self
.fw
) - 1
150 self
.sh
= self
.bh
/ self
.fh
151 if self
.LinesInFile() >= self
.sh
:
152 self
.bw
= self
.bw
- wxSystemSettings_GetMetric(wxSYS_VSCROLL_X
)
153 self
.sw
= (self
.bw
/ self
.fw
) - 1
155 self
.sw
= (self
.bw
/ self
.fw
) - 1
156 if self
.CalcMaxLineLen() >= self
.sw
:
157 self
.bh
= self
.bh
- wxSystemSettings_GetMetric(wxSYS_HSCROLL_Y
)
158 self
.sh
= self
.bh
/ self
.fh
161 def UpdateView(self
, dc
= None):
163 dc
= wxClientDC(self
)
165 self
.SetCharDimensions()
166 self
.KeepCursorOnScreen()
167 self
.DrawSimpleCursor(0,0,dc
, True)
170 def OnPaint(self
, event
):
174 self
.isDrawing
= True
176 wxCallAfter(self
.AdjustScrollbars
)
177 self
.isDrawing
= False
179 def OnEraseBackground(self
, evt
):
182 ##-------------------- Drawing code
185 dc
= wxClientDC(self
)
186 self
.font
= self
.NiceFontForPlatform()
187 dc
.SetFont(self
.font
)
188 self
.fw
= dc
.GetCharWidth()
189 self
.fh
= dc
.GetCharHeight()
192 self
.fgColor
= wxNamedColour('black')
193 self
.bgColor
= wxNamedColour('white')
194 self
.selectColor
= wxColour(238, 220, 120) # r, g, b = emacsOrange
196 def InitDoubleBuffering(self
):
199 def DrawEditText(self
, t
, x
, y
, dc
):
200 dc
.DrawText(t
, (x
* self
.fw
, y
* self
.fh
))
202 def DrawLine(self
, line
, dc
):
203 if self
.IsLine(line
):
206 dc
.SetTextForeground(self
.fgColor
)
207 fragments
= selection
.Selection(
208 self
.SelectBegin
, self
.SelectEnd
,
209 self
.sx
, self
.sw
, line
, t
)
211 for (data
, selected
) in fragments
:
213 dc
.SetTextBackground(self
.selectColor
)
214 if x
== 0 and len(data
) == 0 and len(fragments
) == 1:
217 dc
.SetTextBackground(self
.bgColor
)
218 self
.DrawEditText(data
, x
, line
- self
.sy
, dc
)
221 def Draw(self
, odc
=None):
223 odc
= wxClientDC(self
)
225 bmp
= wxEmptyBitmap(max(1,self
.bw
), max(1,self
.bh
))
226 dc
= wxBufferedDC(odc
, bmp
)
228 dc
.SetFont(self
.font
)
229 dc
.SetBackgroundMode(wxSOLID
)
230 dc
.SetTextBackground(self
.bgColor
)
231 dc
.SetTextForeground(self
.fgColor
)
233 for line
in range(self
.sy
, self
.sy
+ self
.sh
):
234 self
.DrawLine(line
, dc
)
235 if len(self
.lines
) < self
.sh
+ self
.sy
:
236 self
.DrawEofMarker(dc
)
239 ##------------------ eofMarker stuff
241 def LoadImages(self
):
242 self
.eofMarker
= images
.GetBitmap(images
.EofImageData
)
244 def DrawEofMarker(self
,dc
):
246 y
= (len(self
.lines
) - self
.sy
) * self
.fh
248 dc
.DrawBitmap(self
.eofMarker
, (x
, y
), hasTransparency
)
250 ##------------------ cursor-related functions
252 def DrawCursor(self
, dc
= None):
254 dc
= wxClientDC(self
)
256 if (self
.LinesInFile())<self
.cy
: #-1 ?
257 self
.cy
= self
.LinesInFile()-1
258 s
= self
.lines
[self
.cy
]
260 x
= self
.cx
- self
.sx
261 y
= self
.cy
- self
.sy
262 self
.DrawSimpleCursor(x
, y
, dc
)
265 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=False):
267 dc
= wxClientDC(self
)
277 dc
.Blit((x
,y
), (szx
,szy
), dc
, (x
,y
), wxSRC_INVERT
)
281 ##-------- Enforcing screen boundaries, cursor movement
283 def CalcMaxLineLen(self
):
284 """get length of longest line on screen"""
286 for line
in self
.lines
[self
.sy
:self
.sy
+self
.sh
]:
287 if len(line
) >maxlen
:
291 def KeepCursorOnScreen(self
):
292 self
.sy
= ForceBetween(max(0, self
.cy
-self
.sh
), self
.sy
, self
.cy
)
293 self
.sx
= ForceBetween(max(0, self
.cx
-self
.sw
), self
.sx
, self
.cx
)
294 self
.AdjustScrollbars()
296 def HorizBoundaries(self
):
297 self
.SetCharDimensions()
298 maxLineLen
= self
.CalcMaxLineLen()
299 self
.sx
= ForceBetween(0, self
.sx
, max(self
.sw
, maxLineLen
- self
.sw
+ 1))
300 self
.cx
= ForceBetween(self
.sx
, self
.cx
, self
.sx
+ self
.sw
- 1)
302 def VertBoundaries(self
):
303 self
.SetCharDimensions()
304 self
.sy
= ForceBetween(0, self
.sy
, max(self
.sh
, self
.LinesInFile() - self
.sh
+ 1))
305 self
.cy
= ForceBetween(self
.sy
, self
.cy
, self
.sy
+ self
.sh
- 1)
307 def cVert(self
, num
):
308 self
.cy
= self
.cy
+ num
309 self
.cy
= ForceBetween(0, self
.cy
, self
.LinesInFile() - 1)
310 self
.sy
= ForceBetween(self
.cy
- self
.sh
+ 1, self
.sy
, self
.cy
)
311 self
.cx
= min(self
.cx
, self
.CurrentLineLength())
313 def cHoriz(self
, num
):
314 self
.cx
= self
.cx
+ num
315 self
.cx
= ForceBetween(0, self
.cx
, self
.CurrentLineLength())
316 self
.sx
= ForceBetween(self
.cx
- self
.sw
+ 1, self
.sx
, self
.cx
)
318 def AboveScreen(self
, row
):
321 def BelowScreen(self
, row
):
322 return row
>= self
.sy
+ self
.sh
324 def LeftOfScreen(self
, col
):
327 def RightOfScreen(self
, col
):
328 return col
>= self
.sx
+ self
.sw
330 ##----------------- data structure helper functions
335 def SetText(self
, lines
):
340 self
.AdjustScrollbars()
341 self
.UpdateView(None)
343 def IsLine(self
, lineNum
):
344 return (0<=lineNum
) and (lineNum
<self
.LinesInFile())
346 def GetTextLine(self
, lineNum
):
347 if self
.IsLine(lineNum
):
348 return self
.lines
[lineNum
]
351 def SetTextLine(self
, lineNum
, text
):
352 if self
.IsLine(lineNum
):
353 self
.lines
[lineNum
] = text
355 def CurrentLineLength(self
):
356 return len(self
.lines
[self
.cy
])
358 def LinesInFile(self
):
359 return len(self
.lines
)
361 def UnTouchBuffer(self
):
362 self
.bufferTouched
= False
364 def BufferWasTouched(self
):
365 return self
.bufferTouched
367 def TouchBuffer(self
):
368 self
.bufferTouched
= True
371 ##-------------------------- Mouse scroll timing functions
373 def InitScrolling(self
):
374 # we don't rely on the windows system to scroll for us; we just
375 # redraw the screen manually every time
376 self
.EnableScrolling(False, False)
377 self
.nextScrollTime
= 0
378 self
.SCROLLDELAY
= 0.050 # seconds
379 self
.scrollTimer
= wxTimer(self
)
380 self
.scroller
= Scroller(self
)
383 if time
.time() > self
.nextScrollTime
:
384 self
.nextScrollTime
= time
.time() + self
.SCROLLDELAY
389 def SetScrollTimer(self
):
391 self
.scrollTimer
.Start(1000*self
.SCROLLDELAY
/2, oneShot
)
392 EVT_TIMER(self
, -1, self
.OnTimer
)
394 def OnTimer(self
, event
):
395 screenX
, screenY
= wxGetMousePosition()
396 x
, y
= self
.ScreenToClientXY(screenX
, screenY
)
401 ##-------------------------- Mouse off screen functions
403 def HandleAboveScreen(self
, row
):
404 self
.SetScrollTimer()
410 def HandleBelowScreen(self
, row
):
411 self
.SetScrollTimer()
413 row
= self
.sy
+ self
.sh
414 row
= min(row
, self
.LinesInFile() - 1)
417 def HandleLeftOfScreen(self
, col
):
418 self
.SetScrollTimer()
424 def HandleRightOfScreen(self
, col
):
425 self
.SetScrollTimer()
427 col
= self
.sx
+ self
.sw
428 col
= min(col
, self
.CurrentLineLength())
431 ##------------------------ mousing functions
433 def MouseToRow(self
, mouseY
):
434 row
= self
.sy
+ (mouseY
/ self
.fh
)
435 if self
.AboveScreen(row
):
436 self
.HandleAboveScreen(row
)
437 elif self
.BelowScreen(row
):
438 self
.HandleBelowScreen(row
)
440 self
.cy
= min(row
, self
.LinesInFile() - 1)
442 def MouseToCol(self
, mouseX
):
443 col
= self
.sx
+ (mouseX
/ self
.fw
)
444 if self
.LeftOfScreen(col
):
445 self
.HandleLeftOfScreen(col
)
446 elif self
.RightOfScreen(col
):
447 self
.HandleRightOfScreen(col
)
449 self
.cx
= min(col
, self
.CurrentLineLength())
451 def MouseToCursor(self
, event
):
452 self
.MouseToRow(event
.GetY())
453 self
.MouseToCol(event
.GetX())
455 def OnMotion(self
, event
):
456 if event
.LeftIsDown() and self
.HasCapture():
457 self
.Selecting
= True
458 self
.MouseToCursor(event
)
461 def OnLeftDown(self
, event
):
462 self
.MouseToCursor(event
)
463 self
.SelectBegin
= (self
.cy
, self
.cx
)
464 self
.SelectEnd
= None
468 def OnLeftUp(self
, event
):
469 if not self
.HasCapture():
472 if self
.SelectEnd
is None:
475 self
.Selecting
= False
476 self
.SelectNotify(False, self
.SelectBegin
, self
.SelectEnd
)
479 self
.scrollTimer
.Stop()
482 #------------------------- Scrolling
484 def HorizScroll(self
, event
, eventType
):
485 maxLineLen
= self
.CalcMaxLineLen()
487 if eventType
== wxEVT_SCROLLWIN_LINEUP
:
489 elif eventType
== wxEVT_SCROLLWIN_LINEDOWN
:
491 elif eventType
== wxEVT_SCROLLWIN_PAGEUP
:
493 elif eventType
== wxEVT_SCROLLWIN_PAGEDOWN
:
495 elif eventType
== wxEVT_SCROLLWIN_TOP
:
496 self
.sx
= self
.cx
= 0
497 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
498 self
.sx
= maxLineLen
- self
.sw
501 self
.sx
= event
.GetPosition()
503 self
.HorizBoundaries()
505 def VertScroll(self
, event
, eventType
):
506 if eventType
== wxEVT_SCROLLWIN_LINEUP
:
508 elif eventType
== wxEVT_SCROLLWIN_LINEDOWN
:
510 elif eventType
== wxEVT_SCROLLWIN_PAGEUP
:
512 elif eventType
== wxEVT_SCROLLWIN_PAGEDOWN
:
514 elif eventType
== wxEVT_SCROLLWIN_TOP
:
515 self
.sy
= self
.cy
= 0
516 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
517 self
.sy
= self
.LinesInFile() - self
.sh
518 self
.cy
= self
.LinesInFile()
520 self
.sy
= event
.GetPosition()
522 self
.VertBoundaries()
524 def OnScroll(self
, event
):
525 dir = event
.GetOrientation()
526 eventType
= event
.GetEventType()
527 if dir == wxHORIZONTAL
:
528 self
.HorizScroll(event
, eventType
)
530 self
.VertScroll(event
, eventType
)
534 def AdjustScrollbars(self
):
536 self
.SetCharDimensions()
537 self
.scroller
.SetScrollbars(
539 self
.CalcMaxLineLen()+3, max(self
.LinesInFile()+1, self
.sh
),
542 #------------ backspace, delete, return
544 def BreakLine(self
, event
):
545 if self
.IsLine(self
.cy
):
546 t
= self
.lines
[self
.cy
]
547 self
.lines
= self
.lines
[:self
.cy
] + [t
[:self
.cx
],t
[self
.cx
:]] + self
.lines
[self
.cy
+1:]
552 def InsertChar(self
,char
):
553 if self
.IsLine(self
.cy
):
554 t
= self
.lines
[self
.cy
]
555 t
= t
[:self
.cx
] + char
+ t
[self
.cx
:]
556 self
.SetTextLine(self
.cy
, t
)
561 t1
= self
.lines
[self
.cy
]
562 t2
= self
.lines
[self
.cy
+1]
564 self
.lines
= self
.lines
[:self
.cy
] + [t1
+ t2
] + self
.lines
[self
.cy
+2:]
568 def DeleteChar(self
,x
,y
,oldtext
):
569 newtext
= oldtext
[:x
] + oldtext
[x
+1:]
570 self
.SetTextLine(y
, newtext
)
574 def BackSpace(self
, event
):
575 t
= self
.GetTextLine(self
.cy
)
577 self
.DeleteChar(self
.cx
-1,self
.cy
,t
)
588 def Delete(self
, event
):
589 t
= self
.GetTextLine(self
.cy
)
591 self
.DeleteChar(self
.cx
,self
.cy
,t
)
594 if self
.cy
< len(self
.lines
) - 1:
598 def Escape(self
, event
):
601 def TabKey(self
, event
):
602 numSpaces
= self
.SpacesPerTab
- (self
.cx
% self
.SpacesPerTab
)
603 self
.SingleLineInsert(' ' * numSpaces
)
605 ##----------- selection routines
607 def SelectUpdate(self
):
608 self
.SelectEnd
= (self
.cy
, self
.cx
)
609 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
612 def NormalizedSelect(self
):
613 (begin
, end
) = (self
.SelectBegin
, self
.SelectEnd
)
626 def FindSelection(self
):
627 if self
.SelectEnd
is None or self
.SelectBegin
is None:
630 (begin
, end
) = self
.NormalizedSelect()
633 return (bRow
, bCol
, eRow
, eCol
)
636 self
.SelectBegin
= None
637 self
.SelectEnd
= None
638 self
.Selecting
= False
639 self
.SelectNotify(False,None,None)
641 def CopySelection(self
, event
):
642 selection
= self
.FindSelection()
643 if selection
is None:
645 (bRow
, bCol
, eRow
, eCol
) = selection
648 self
.SingleLineCopy(bRow
, bCol
, eCol
)
650 self
.MultipleLineCopy(bRow
, bCol
, eRow
, eCol
)
652 def OnCopySelection(self
, event
):
653 self
.CopySelection(event
)
656 def CopyToClipboard(self
, linesOfText
):
657 do
= wxTextDataObject()
658 do
.SetText(os
.linesep
.join(linesOfText
))
659 wxTheClipboard
.Open()
660 wxTheClipboard
.SetData(do
)
661 wxTheClipboard
.Close()
663 def SingleLineCopy(self
, Row
, bCol
, eCol
):
664 Line
= self
.GetTextLine(Row
)
665 self
.CopyToClipboard([Line
[bCol
:eCol
]])
667 def MultipleLineCopy(self
, bRow
, bCol
, eRow
, eCol
):
668 bLine
= self
.GetTextLine(bRow
)[bCol
:]
669 eLine
= self
.GetTextLine(eRow
)[:eCol
]
670 self
.CopyToClipboard([bLine
] + [l
for l
in self
.lines
[bRow
+ 1:eRow
]] + [eLine
])
672 def OnDeleteSelection(self
, event
):
673 selection
= self
.FindSelection()
674 if selection
is None:
676 (bRow
, bCol
, eRow
, eCol
) = selection
679 self
.SingleLineDelete(bRow
, bCol
, eCol
)
681 self
.MultipleLineDelete(bRow
, bCol
, eRow
, eCol
)
691 def SingleLineDelete(self
, Row
, bCol
, eCol
):
692 ModLine
= self
.GetTextLine(Row
)
693 ModLine
= ModLine
[:bCol
] + ModLine
[eCol
:]
694 self
.SetTextLine(Row
,ModLine
)
696 def MultipleLineDelete(self
, bRow
, bCol
, eRow
, eCol
):
697 bLine
= self
.GetTextLine(bRow
)
698 eLine
= self
.GetTextLine(eRow
)
699 ModLine
= bLine
[:bCol
] + eLine
[eCol
:]
700 self
.lines
[bRow
:eRow
+ 1] = [ModLine
]
702 def OnPaste(self
, event
):
703 do
= wxTextDataObject()
704 wxTheClipboard
.Open()
705 success
= wxTheClipboard
.GetData(do
)
706 wxTheClipboard
.Close()
708 pastedLines
= LineSplitter(do
.GetText())
712 if len(pastedLines
) == 0:
715 elif len(pastedLines
) == 1:
716 self
.SingleLineInsert(pastedLines
[0])
718 self
.MultipleLinePaste(pastedLines
)
720 def SingleLineInsert(self
, newText
):
721 ModLine
= self
.GetTextLine(self
.cy
)
722 ModLine
= ModLine
[:self
.cx
] + newText
+ ModLine
[self
.cx
:]
723 self
.SetTextLine(self
.cy
, ModLine
)
724 self
.cHoriz(len(newText
))
728 def MultipleLinePaste(self
, pastedLines
):
729 FirstLine
= LastLine
= self
.GetTextLine(self
.cy
)
730 FirstLine
= FirstLine
[:self
.cx
] + pastedLines
[0]
731 LastLine
= pastedLines
[-1] + LastLine
[self
.cx
:]
733 NewSlice
= [FirstLine
]
734 NewSlice
+= [l
for l
in pastedLines
[1:-1]]
735 NewSlice
+= [LastLine
]
736 self
.lines
[self
.cy
:self
.cy
+ 1] = NewSlice
738 self
.cy
= self
.cy
+ len(pastedLines
)-1
739 self
.cx
= len(pastedLines
[-1])
743 def OnCutSelection(self
,event
):
744 self
.CopySelection(event
)
745 self
.OnDeleteSelection(event
)
747 #-------------- Keyboard movement implementations
749 def MoveDown(self
, event
):
752 def MoveUp(self
, event
):
755 def MoveLeft(self
, event
):
761 self
.cx
= self
.CurrentLineLength()
765 def MoveRight(self
, event
):
766 linelen
= self
.CurrentLineLength()
767 if self
.cx
== linelen
:
768 if self
.cy
== len(self
.lines
) - 1:
777 def MovePageDown(self
, event
):
780 def MovePageUp(self
, event
):
783 def MoveHome(self
, event
):
786 def MoveEnd(self
, event
):
787 self
.cx
= self
.CurrentLineLength()
789 def MoveStartOfFile(self
, event
):
793 def MoveEndOfFile(self
, event
):
794 self
.cy
= len(self
.lines
) - 1
795 self
.cx
= self
.CurrentLineLength()
797 #-------------- Key handler mapping tables
799 def SetMoveSpecialFuncs(self
, action
):
800 action
[WXK_DOWN
] = self
.MoveDown
801 action
[WXK_UP
] = self
.MoveUp
802 action
[WXK_LEFT
] = self
.MoveLeft
803 action
[WXK_RIGHT
] = self
.MoveRight
804 action
[WXK_NEXT
] = self
.MovePageDown
805 action
[WXK_PRIOR
] = self
.MovePageUp
806 action
[WXK_HOME
] = self
.MoveHome
807 action
[WXK_END
] = self
.MoveEnd
809 def SetMoveSpecialControlFuncs(self
, action
):
810 action
[WXK_HOME
] = self
.MoveStartOfFile
811 action
[WXK_END
] = self
.MoveEndOfFile
813 def SetAltFuncs(self
, action
):
814 # subclass implements
817 def SetControlFuncs(self
, action
):
818 action
['c'] = self
.OnCopySelection
819 action
['d'] = self
.OnDeleteSelection
820 action
['v'] = self
.OnPaste
821 action
['x'] = self
.OnCutSelection
823 def SetSpecialControlFuncs(self
, action
):
824 action
[WXK_INSERT
] = self
.OnCopySelection
826 def SetShiftFuncs(self
, action
):
827 action
[WXK_DELETE
] = self
.OnCutSelection
828 action
[WXK_INSERT
] = self
.OnPaste
830 def SetSpecialFuncs(self
, action
):
831 action
[WXK_BACK
] = self
.BackSpace
832 action
[WXK_DELETE
] = self
.Delete
833 action
[WXK_RETURN
] = self
.BreakLine
834 action
[WXK_ESCAPE
] = self
.Escape
835 action
[WXK_TAB
] = self
.TabKey
837 ##-------------- Logic for key handlers
840 def Move(self
, keySettingFunction
, key
, event
):
842 keySettingFunction(action
)
844 if not action
.has_key(key
):
847 if event
.ShiftDown():
848 if not self
.Selecting
:
849 self
.Selecting
= True
850 self
.SelectBegin
= (self
.cy
, self
.cx
)
852 self
.SelectEnd
= (self
.cy
, self
.cx
)
856 self
.Selecting
= False
858 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
862 def MoveSpecialKey(self
, event
, key
):
863 return self
.Move(self
.SetMoveSpecialFuncs
, key
, event
)
865 def MoveSpecialControlKey(self
, event
, key
):
866 if not event
.ControlDown():
868 return self
.Move(self
.SetMoveSpecialControlFuncs
, key
, event
)
870 def Dispatch(self
, keySettingFunction
, key
, event
):
872 keySettingFunction(action
)
873 if action
.has_key(key
):
879 def ModifierKey(self
, key
, event
, modifierKeyDown
, MappingFunc
):
880 if not modifierKeyDown
:
883 key
= self
.UnixKeyHack(key
)
888 if not self
.Dispatch(MappingFunc
, key
, event
):
892 def ControlKey(self
, event
, key
):
893 return self
.ModifierKey(key
, event
, event
.ControlDown(), self
.SetControlFuncs
)
895 def AltKey(self
, event
, key
):
896 return self
.ModifierKey(key
, event
, event
.AltDown(), self
.SetAltFuncs
)
898 def SpecialControlKey(self
, event
, key
):
899 if not event
.ControlDown():
901 if not self
.Dispatch(self
.SetSpecialControlFuncs
, key
, event
):
905 def ShiftKey(self
, event
, key
):
906 if not event
.ShiftDown():
908 return self
.Dispatch(self
.SetShiftFuncs
, key
, event
)
910 def NormalChar(self
, event
, key
):
914 if not self
.Dispatch(self
.SetSpecialFuncs
, key
, event
):
915 if (key
>31) and (key
<256):
916 self
.InsertChar(chr(key
))
921 self
.AdjustScrollbars()
923 def OnChar(self
, event
):
924 key
= event
.KeyCode()
925 filters
= [self
.AltKey
,
926 self
.MoveSpecialControlKey
,
928 self
.SpecialControlKey
,
932 for filter in filters
:
933 if filter(event
,key
):
937 #----------------------- Eliminate memory leaks
939 def OnDestroy(self
, event
):
945 self
.selectColor
= None
946 self
.scrollTimer
= None
947 self
.eofMarker
= None
949 #-------------------- Abstract methods for subclasses
954 def SelectNotify(self
, Selecting
, SelectionBegin
, SelectionEnd
):