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 *
32 #----------------------------
34 def ForceBetween(min, val
, max):
42 def LineTrimmer(lineOfText
):
43 if len(lineOfText
) == 0:
45 elif lineOfText
[-1] == '\r':
46 return lineOfText
[:-1]
50 def LineSplitter(text
):
51 return map (LineTrimmer
, text
.split('\n'))
54 #----------------------------
57 def __init__(self
, parent
):
64 def SetScrollbars(self
, fw
, fh
, w
, h
, x
, y
):
65 if (self
.ow
!= w
or self
.oh
!= h
or self
.ox
!= x
or self
.oy
!= y
):
66 self
.parent
.SetScrollbars(fw
, fh
, w
, h
, x
, y
)
72 #----------------------------------------------------------------------
74 class wxEditor(wxScrolledWindow
):
76 def __init__(self
, parent
, id,
77 pos
=wxDefaultPosition
, size
=wxDefaultSize
, style
=0):
79 wxScrolledWindow
.__init
__(self
, parent
, id,
88 self
.InitDoubleBuffering()
95 ##------------------ Init stuff
110 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
111 EVT_LEFT_UP(self
, self
.OnLeftUp
)
112 EVT_MOTION(self
, self
.OnMotion
)
113 EVT_SCROLLWIN(self
, self
.OnScroll
)
114 EVT_CHAR(self
, self
.OnChar
)
115 EVT_PAINT(self
, self
.OnPaint
)
116 EVT_SIZE(self
, self
.OnSize
)
117 EVT_WINDOW_DESTROY(self
, self
.OnDestroy
)
118 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
120 ##------------------- Platform-specific stuff
122 def NiceFontForPlatform(self
):
123 if wxPlatform
== "__WXMSW__":
124 return wxFont(10, wxMODERN
, wxNORMAL
, wxNORMAL
)
126 return wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, false
)
128 def UnixKeyHack(self
, key
):
129 # this will be obsolete when we get the new wxWindows patch
134 ##-------------------- UpdateView/Cursor code
136 def OnSize(self
, event
):
137 self
.AdjustScrollbars()
140 def SetCharDimensions(self
):
141 # TODO: We need a code review on this. It appears that Linux
142 # improperly reports window dimensions when the scrollbar's there.
143 self
.bw
, self
.bh
= self
.GetClientSizeTuple()
145 if wxPlatform
== "__WXMSW__":
146 self
.sh
= self
.bh
/ self
.fh
147 self
.sw
= (self
.bw
/ self
.fw
) - 1
149 self
.sh
= self
.bh
/ self
.fh
150 if self
.LinesInFile() >= self
.sh
:
151 self
.bw
= self
.bw
- wxSystemSettings_GetSystemMetric(wxSYS_VSCROLL_X
)
152 self
.sw
= (self
.bw
/ self
.fw
) - 1
154 self
.sw
= (self
.bw
/ self
.fw
) - 1
155 if self
.CalcMaxLineLen() >= self
.sw
:
156 self
.bh
= self
.bh
- wxSystemSettings_GetSystemMetric(wxSYS_HSCROLL_Y
)
157 self
.sh
= self
.bh
/ self
.fh
160 def UpdateView(self
, dc
= None):
162 dc
= wxClientDC(self
)
164 self
.SetCharDimensions()
165 self
.KeepCursorOnScreen()
166 self
.DrawSimpleCursor(0,0,dc
, true
)
169 def OnPaint(self
, event
):
172 self
.AdjustScrollbars()
174 def OnEraseBackground(self
, evt
):
177 ##-------------------- Drawing code
180 dc
= wxClientDC(self
)
181 self
.font
= self
.NiceFontForPlatform()
182 dc
.SetFont(self
.font
)
183 self
.fw
= dc
.GetCharWidth()
184 self
.fh
= dc
.GetCharHeight()
187 self
.fgColor
= wxNamedColour('black')
188 self
.bgColor
= wxNamedColour('white')
189 self
.selectColor
= wxColour(238, 220, 120) # r, g, b = emacsOrange
191 def InitDoubleBuffering(self
):
194 def DrawEditText(self
, t
, x
, y
, dc
):
195 dc
.DrawText(t
, x
* self
.fw
, y
* self
.fh
)
197 def DrawLine(self
, line
, dc
):
198 if self
.IsLine(line
):
201 dc
.SetTextForeground(self
.fgColor
)
202 fragments
= selection
.Selection(
203 self
.SelectBegin
, self
.SelectEnd
,
204 self
.sx
, self
.sw
, line
, t
)
206 for (data
, selected
) in fragments
:
208 dc
.SetTextBackground(self
.selectColor
)
209 if x
== 0 and len(data
) == 0 and len(fragments
) == 1:
212 dc
.SetTextBackground(self
.bgColor
)
213 self
.DrawEditText(data
, x
, line
- self
.sy
, dc
)
216 def Draw(self
, odc
=None):
218 odc
= wxClientDC(self
)
220 bmp
= wxEmptyBitmap(max(1,self
.bw
), max(1,self
.bh
))
221 dc
= wxBufferedDC(odc
, bmp
)
223 dc
.SetFont(self
.font
)
224 dc
.SetBackgroundMode(wxSOLID
)
225 dc
.SetTextBackground(self
.bgColor
)
226 dc
.SetTextForeground(self
.fgColor
)
228 for line
in range(self
.sy
, self
.sy
+ self
.sh
):
229 self
.DrawLine(line
, dc
)
230 if len(self
.lines
) < self
.sh
+ self
.sy
:
231 self
.DrawEofMarker(dc
)
234 ##------------------ eofMarker stuff
236 def LoadImages(self
):
237 self
.eofMarker
= images
.GetBitmap(images
.EofImageData
)
239 def DrawEofMarker(self
,dc
):
241 y
= (len(self
.lines
) - self
.sy
) * self
.fh
243 dc
.DrawBitmap(self
.eofMarker
, x
, y
, hasTransparency
)
245 ##------------------ cursor-related functions
247 def DrawCursor(self
, dc
= None):
249 dc
= wxClientDC(self
)
251 if (self
.LinesInFile())<self
.cy
: #-1 ?
252 self
.cy
= self
.LinesInFile()-1
253 s
= self
.lines
[self
.cy
]
255 x
= self
.cx
- self
.sx
256 y
= self
.cy
- self
.sy
257 self
.DrawSimpleCursor(x
, y
, dc
)
260 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=false
):
262 dc
= wxClientDC(self
)
272 dc
.Blit(x
,y
,szx
,szy
,dc
,x
,y
,wxSRC_INVERT
)
276 ##-------- Enforcing screen boundaries, cursor movement
278 def CalcMaxLineLen(self
):
279 """get length of longest line on screen"""
281 for line
in self
.lines
[self
.sy
:self
.sy
+self
.sh
]:
282 if len(line
) >maxlen
:
286 def KeepCursorOnScreen(self
):
287 self
.sy
= ForceBetween(max(0, self
.cy
-self
.sh
), self
.sy
, self
.cy
)
288 self
.sx
= ForceBetween(max(0, self
.cx
-self
.sw
), self
.sx
, self
.cx
)
289 self
.AdjustScrollbars()
291 def HorizBoundaries(self
):
292 self
.SetCharDimensions()
293 maxLineLen
= self
.CalcMaxLineLen()
294 self
.sx
= ForceBetween(0, self
.sx
, max(self
.sw
, maxLineLen
- self
.sw
+ 1))
295 self
.cx
= ForceBetween(self
.sx
, self
.cx
, self
.sx
+ self
.sw
- 1)
297 def VertBoundaries(self
):
298 self
.SetCharDimensions()
299 self
.sy
= ForceBetween(0, self
.sy
, max(self
.sh
, self
.LinesInFile() - self
.sh
+ 1))
300 self
.cy
= ForceBetween(self
.sy
, self
.cy
, self
.sy
+ self
.sh
- 1)
302 def cVert(self
, num
):
303 self
.cy
= self
.cy
+ num
304 self
.cy
= ForceBetween(0, self
.cy
, self
.LinesInFile() - 1)
305 self
.sy
= ForceBetween(self
.cy
- self
.sh
+ 1, self
.sy
, self
.cy
)
306 self
.cx
= min(self
.cx
, self
.CurrentLineLength())
308 def cHoriz(self
, num
):
309 self
.cx
= self
.cx
+ num
310 self
.cx
= ForceBetween(0, self
.cx
, self
.CurrentLineLength())
311 self
.sx
= ForceBetween(self
.cx
- self
.sw
+ 1, self
.sx
, self
.cx
)
313 def AboveScreen(self
, row
):
316 def BelowScreen(self
, row
):
317 return row
>= self
.sy
+ self
.sh
319 def LeftOfScreen(self
, col
):
322 def RightOfScreen(self
, col
):
323 return col
>= self
.sx
+ self
.sw
325 ##----------------- data structure helper functions
330 def SetText(self
, lines
):
335 self
.AdjustScrollbars()
336 self
.UpdateView(None)
338 def IsLine(self
, lineNum
):
339 return (0<=lineNum
) and (lineNum
<self
.LinesInFile())
341 def GetTextLine(self
, lineNum
):
342 if self
.IsLine(lineNum
):
343 return self
.lines
[lineNum
]
346 def SetTextLine(self
, lineNum
, text
):
347 if self
.IsLine(lineNum
):
348 self
.lines
[lineNum
] = text
350 def CurrentLineLength(self
):
351 return len(self
.lines
[self
.cy
])
353 def LinesInFile(self
):
354 return len(self
.lines
)
356 def UnTouchBuffer(self
):
357 self
.bufferTouched
= FALSE
359 def BufferWasTouched(self
):
360 return self
.bufferTouched
362 def TouchBuffer(self
):
363 self
.bufferTouched
= TRUE
366 ##-------------------------- Mouse scroll timing functions
368 def InitScrolling(self
):
369 # we don't rely on the windows system to scroll for us; we just
370 # redraw the screen manually every time
371 self
.EnableScrolling(FALSE
, FALSE
)
372 self
.nextScrollTime
= 0
373 self
.SCROLLDELAY
= 0.050 # seconds
374 self
.scrollTimer
= wxTimer(self
)
375 self
.scroller
= Scroller(self
)
378 if time
.time() > self
.nextScrollTime
:
379 self
.nextScrollTime
= time
.time() + self
.SCROLLDELAY
384 def SetScrollTimer(self
):
386 self
.scrollTimer
.Start(1000*self
.SCROLLDELAY
/2, oneShot
)
387 EVT_TIMER(self
, -1, self
.OnTimer
)
389 def OnTimer(self
, event
):
390 screenX
, screenY
= wxGetMousePosition()
391 x
, y
= self
.ScreenToClientXY(screenX
, screenY
)
396 ##-------------------------- Mouse off screen functions
398 def HandleAboveScreen(self
, row
):
399 self
.SetScrollTimer()
405 def HandleBelowScreen(self
, row
):
406 self
.SetScrollTimer()
408 row
= self
.sy
+ self
.sh
409 row
= min(row
, self
.LinesInFile() - 1)
412 def HandleLeftOfScreen(self
, col
):
413 self
.SetScrollTimer()
419 def HandleRightOfScreen(self
, col
):
420 self
.SetScrollTimer()
422 col
= self
.sx
+ self
.sw
423 col
= min(col
, self
.CurrentLineLength())
426 ##------------------------ mousing functions
428 def MouseToRow(self
, mouseY
):
429 row
= self
.sy
+ (mouseY
/ self
.fh
)
430 if self
.AboveScreen(row
):
431 self
.HandleAboveScreen(row
)
432 elif self
.BelowScreen(row
):
433 self
.HandleBelowScreen(row
)
435 self
.cy
= min(row
, self
.LinesInFile() - 1)
437 def MouseToCol(self
, mouseX
):
438 col
= self
.sx
+ (mouseX
/ self
.fw
)
439 if self
.LeftOfScreen(col
):
440 self
.HandleLeftOfScreen(col
)
441 elif self
.RightOfScreen(col
):
442 self
.HandleRightOfScreen(col
)
444 self
.cx
= min(col
, self
.CurrentLineLength())
446 def MouseToCursor(self
, event
):
447 self
.MouseToRow(event
.GetY())
448 self
.MouseToCol(event
.GetX())
450 def OnMotion(self
, event
):
451 if event
.LeftIsDown() and self
.HasCapture():
452 self
.Selecting
= true
453 self
.MouseToCursor(event
)
456 def OnLeftDown(self
, event
):
457 self
.MouseToCursor(event
)
458 self
.SelectBegin
= (self
.cy
, self
.cx
)
459 self
.SelectEnd
= None
463 def OnLeftUp(self
, event
):
464 if not self
.HasCapture():
467 if self
.SelectEnd
is None:
470 self
.Selecting
= false
471 self
.SelectNotify(false
, self
.SelectBegin
, self
.SelectEnd
)
474 self
.scrollTimer
.Stop()
477 #------------------------- Scrolling
479 def HorizScroll(self
, event
, eventType
):
480 maxLineLen
= self
.CalcMaxLineLen()
482 if eventType
== wxEVT_SCROLLWIN_LINEUP
:
484 elif eventType
== wxEVT_SCROLLWIN_LINEDOWN
:
486 elif eventType
== wxEVT_SCROLLWIN_PAGEUP
:
488 elif eventType
== wxEVT_SCROLLWIN_PAGEDOWN
:
490 elif eventType
== wxEVT_SCROLLWIN_TOP
:
491 self
.sx
= self
.cx
= 0
492 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
493 self
.sx
= maxLineLen
- self
.sw
496 self
.sx
= event
.GetPosition()
498 self
.HorizBoundaries()
500 def VertScroll(self
, event
, eventType
):
501 if eventType
== wxEVT_SCROLLWIN_LINEUP
:
503 elif eventType
== wxEVT_SCROLLWIN_LINEDOWN
:
505 elif eventType
== wxEVT_SCROLLWIN_PAGEUP
:
507 elif eventType
== wxEVT_SCROLLWIN_PAGEDOWN
:
509 elif eventType
== wxEVT_SCROLLWIN_TOP
:
510 self
.sy
= self
.cy
= 0
511 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
512 self
.sy
= self
.LinesInFile() - self
.sh
513 self
.cy
= self
.LinesInFile()
515 self
.sy
= event
.GetPosition()
517 self
.VertBoundaries()
519 def OnScroll(self
, event
):
520 dir = event
.GetOrientation()
521 eventType
= event
.GetEventType()
522 if dir == wxHORIZONTAL
:
523 self
.HorizScroll(event
, eventType
)
525 self
.VertScroll(event
, eventType
)
529 def AdjustScrollbars(self
):
531 self
.SetCharDimensions()
532 self
.scroller
.SetScrollbars(
534 self
.CalcMaxLineLen()+3, max(self
.LinesInFile()+1, self
.sh
),
537 #------------ backspace, delete, return
539 def BreakLine(self
, event
):
540 if self
.IsLine(self
.cy
):
541 t
= self
.lines
[self
.cy
]
542 self
.lines
= self
.lines
[:self
.cy
] + [t
[:self
.cx
],t
[self
.cx
:]] + self
.lines
[self
.cy
+1:]
547 def InsertChar(self
,char
):
548 if self
.IsLine(self
.cy
):
549 t
= self
.lines
[self
.cy
]
550 t
= t
[:self
.cx
] + char
+ t
[self
.cx
:]
551 self
.SetTextLine(self
.cy
, t
)
556 t1
= self
.lines
[self
.cy
]
557 t2
= self
.lines
[self
.cy
+1]
559 self
.lines
= self
.lines
[:self
.cy
] + [t1
+ t2
] + self
.lines
[self
.cy
+2:]
563 def DeleteChar(self
,x
,y
,oldtext
):
564 newtext
= oldtext
[:x
] + oldtext
[x
+1:]
565 self
.SetTextLine(y
, newtext
)
569 def BackSpace(self
, event
):
570 t
= self
.GetTextLine(self
.cy
)
572 self
.DeleteChar(self
.cx
-1,self
.cy
,t
)
583 def Delete(self
, event
):
584 t
= self
.GetTextLine(self
.cy
)
586 self
.DeleteChar(self
.cx
,self
.cy
,t
)
589 if self
.cy
< len(self
.lines
) - 1:
593 def Escape(self
, event
):
596 def TabKey(self
, event
):
597 numSpaces
= self
.SpacesPerTab
- (self
.cx
% self
.SpacesPerTab
)
598 self
.SingleLineInsert(' ' * numSpaces
)
600 ##----------- selection routines
602 def SelectUpdate(self
):
603 self
.SelectEnd
= (self
.cy
, self
.cx
)
604 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
607 def NormalizedSelect(self
):
608 (begin
, end
) = (self
.SelectBegin
, self
.SelectEnd
)
621 def FindSelection(self
):
622 if self
.SelectEnd
is None or self
.SelectBegin
is None:
625 (begin
, end
) = self
.NormalizedSelect()
628 return (bRow
, bCol
, eRow
, eCol
)
631 self
.SelectBegin
= None
632 self
.SelectEnd
= None
633 self
.Selecting
= false
634 self
.SelectNotify(false
,None,None)
636 def CopySelection(self
, event
):
637 selection
= self
.FindSelection()
638 if selection
is None:
640 (bRow
, bCol
, eRow
, eCol
) = selection
643 self
.SingleLineCopy(bRow
, bCol
, eCol
)
645 self
.MultipleLineCopy(bRow
, bCol
, eRow
, eCol
)
647 def OnCopySelection(self
, event
):
648 self
.CopySelection(event
)
651 def CopyToClipboard(self
, linesOfText
):
652 do
= wxTextDataObject()
653 do
.SetText(string
.join(linesOfText
, os
.linesep
))
654 wxTheClipboard
.Open()
655 wxTheClipboard
.SetData(do
)
656 wxTheClipboard
.Close()
658 def SingleLineCopy(self
, Row
, bCol
, eCol
):
659 Line
= self
.GetTextLine(Row
)
660 self
.CopyToClipboard([Line
[bCol
:eCol
]])
662 def MultipleLineCopy(self
, bRow
, bCol
, eRow
, eCol
):
663 bLine
= self
.GetTextLine(bRow
)[bCol
:]
664 eLine
= self
.GetTextLine(eRow
)[:eCol
]
665 self
.CopyToClipboard([bLine
] + [l
for l
in self
.lines
[bRow
+ 1:eRow
]] + [eLine
])
667 def OnDeleteSelection(self
, event
):
668 selection
= self
.FindSelection()
669 if selection
is None:
671 (bRow
, bCol
, eRow
, eCol
) = selection
674 self
.SingleLineDelete(bRow
, bCol
, eCol
)
676 self
.MultipleLineDelete(bRow
, bCol
, eRow
, eCol
)
686 def SingleLineDelete(self
, Row
, bCol
, eCol
):
687 ModLine
= self
.GetTextLine(Row
)
688 ModLine
= ModLine
[:bCol
] + ModLine
[eCol
:]
689 self
.SetTextLine(Row
,ModLine
)
691 def MultipleLineDelete(self
, bRow
, bCol
, eRow
, eCol
):
692 bLine
= self
.GetTextLine(bRow
)
693 eLine
= self
.GetTextLine(eRow
)
694 ModLine
= bLine
[:bCol
] + eLine
[eCol
:]
695 self
.lines
[bRow
:eRow
+ 1] = [ModLine
]
697 def OnPaste(self
, event
):
698 do
= wxTextDataObject()
699 wxTheClipboard
.Open()
700 success
= wxTheClipboard
.GetData(do
)
701 wxTheClipboard
.Close()
703 pastedLines
= LineSplitter(do
.GetText())
707 if len(pastedLines
) == 0:
710 elif len(pastedLines
) == 1:
711 self
.SingleLineInsert(pastedLines
[0])
713 self
.MultipleLinePaste(pastedLines
)
715 def SingleLineInsert(self
, newText
):
716 ModLine
= self
.GetTextLine(self
.cy
)
717 ModLine
= ModLine
[:self
.cx
] + newText
+ ModLine
[self
.cx
:]
718 self
.SetTextLine(self
.cy
, ModLine
)
719 self
.cHoriz(len(newText
))
723 def MultipleLinePaste(self
, pastedLines
):
724 FirstLine
= LastLine
= self
.GetTextLine(self
.cy
)
725 FirstLine
= FirstLine
[:self
.cx
] + pastedLines
[0]
726 LastLine
= pastedLines
[-1] + LastLine
[self
.cx
:]
728 NewSlice
= [FirstLine
]
729 NewSlice
+= [l
for l
in pastedLines
[1:-1]]
730 NewSlice
+= [LastLine
]
731 self
.lines
[self
.cy
:self
.cy
+ 1] = NewSlice
733 self
.cy
= self
.cy
+ len(pastedLines
)-1
734 self
.cx
= len(pastedLines
[-1])
738 def OnCutSelection(self
,event
):
739 self
.CopySelection(event
)
740 self
.OnDeleteSelection(event
)
742 #-------------- Keyboard movement implementations
744 def MoveDown(self
, event
):
747 def MoveUp(self
, event
):
750 def MoveLeft(self
, event
):
756 self
.cx
= self
.CurrentLineLength()
760 def MoveRight(self
, event
):
761 linelen
= self
.CurrentLineLength()
762 if self
.cx
== linelen
:
763 if self
.cy
== len(self
.lines
) - 1:
772 def MovePageDown(self
, event
):
775 def MovePageUp(self
, event
):
778 def MoveHome(self
, event
):
781 def MoveEnd(self
, event
):
782 self
.cx
= self
.CurrentLineLength()
784 def MoveStartOfFile(self
, event
):
788 def MoveEndOfFile(self
, event
):
789 self
.cy
= len(self
.lines
) - 1
790 self
.cx
= self
.CurrentLineLength()
792 #-------------- Key handler mapping tables
794 def SetMoveSpecialFuncs(self
, action
):
795 action
[WXK_DOWN
] = self
.MoveDown
796 action
[WXK_UP
] = self
.MoveUp
797 action
[WXK_LEFT
] = self
.MoveLeft
798 action
[WXK_RIGHT
] = self
.MoveRight
799 action
[WXK_NEXT
] = self
.MovePageDown
800 action
[WXK_PRIOR
] = self
.MovePageUp
801 action
[WXK_HOME
] = self
.MoveHome
802 action
[WXK_END
] = self
.MoveEnd
804 def SetMoveSpecialControlFuncs(self
, action
):
805 action
[WXK_HOME
] = self
.MoveStartOfFile
806 action
[WXK_END
] = self
.MoveEndOfFile
808 def SetAltFuncs(self
, action
):
809 # subclass implements
812 def SetControlFuncs(self
, action
):
813 action
['c'] = self
.OnCopySelection
814 action
['d'] = self
.OnDeleteSelection
815 action
['v'] = self
.OnPaste
816 action
['x'] = self
.OnCutSelection
818 def SetSpecialControlFuncs(self
, action
):
819 action
[WXK_INSERT
] = self
.OnCopySelection
821 def SetShiftFuncs(self
, action
):
822 action
[WXK_DELETE
] = self
.OnCutSelection
823 action
[WXK_INSERT
] = self
.OnPaste
825 def SetSpecialFuncs(self
, action
):
826 action
[WXK_BACK
] = self
.BackSpace
827 action
[WXK_DELETE
] = self
.Delete
828 action
[WXK_RETURN
] = self
.BreakLine
829 action
[WXK_ESCAPE
] = self
.Escape
830 action
[WXK_TAB
] = self
.TabKey
832 ##-------------- Logic for key handlers
835 def Move(self
, keySettingFunction
, key
, event
):
837 keySettingFunction(action
)
839 if not action
.has_key(key
):
842 if event
.ShiftDown():
843 if not self
.Selecting
:
844 self
.Selecting
= true
845 self
.SelectBegin
= (self
.cy
, self
.cx
)
847 self
.SelectEnd
= (self
.cy
, self
.cx
)
851 self
.Selecting
= false
853 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
857 def MoveSpecialKey(self
, event
, key
):
858 return self
.Move(self
.SetMoveSpecialFuncs
, key
, event
)
860 def MoveSpecialControlKey(self
, event
, key
):
861 if not event
.ControlDown():
863 return self
.Move(self
.SetMoveSpecialControlFuncs
, key
, event
)
865 def Dispatch(self
, keySettingFunction
, key
, event
):
867 keySettingFunction(action
)
868 if action
.has_key(key
):
874 def ModifierKey(self
, key
, event
, modifierKeyDown
, MappingFunc
):
875 if not modifierKeyDown
:
878 key
= self
.UnixKeyHack(key
)
883 if not self
.Dispatch(MappingFunc
, key
, event
):
887 def ControlKey(self
, event
, key
):
888 return self
.ModifierKey(key
, event
, event
.ControlDown(), self
.SetControlFuncs
)
890 def AltKey(self
, event
, key
):
891 return self
.ModifierKey(key
, event
, event
.AltDown(), self
.SetAltFuncs
)
893 def SpecialControlKey(self
, event
, key
):
894 if not event
.ControlDown():
896 if not self
.Dispatch(self
.SetSpecialControlFuncs
, key
, event
):
900 def ShiftKey(self
, event
, key
):
901 if not event
.ShiftDown():
903 return self
.Dispatch(self
.SetShiftFuncs
, key
, event
)
905 def NormalChar(self
, event
, key
):
909 if not self
.Dispatch(self
.SetSpecialFuncs
, key
, event
):
910 if (key
>31) and (key
<256):
911 self
.InsertChar(chr(key
))
916 self
.AdjustScrollbars()
918 def OnChar(self
, event
):
919 key
= event
.KeyCode()
920 filters
= [self
.AltKey
,
921 self
.MoveSpecialControlKey
,
923 self
.SpecialControlKey
,
927 for filter in filters
:
928 if filter(event
,key
):
932 #----------------------- Eliminate memory leaks
934 def OnDestroy(self
, event
):
940 self
.selectColor
= None
941 self
.scrollTimer
= None
942 self
.eofMarker
= None
944 #-------------------- Abstract methods for subclasses
949 def SelectNotify(self
, Selecting
, SelectionBegin
, SelectionEnd
):