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):
41 #----------------------------
44 def __init__(self
, parent
):
51 def SetScrollbars(self
, fw
, fh
, w
, h
, x
, y
):
52 if (self
.ow
!= w
or self
.oh
!= h
or self
.ox
!= x
or self
.oy
!= y
):
53 self
.parent
.SetScrollbars(fw
, fh
, w
, h
, x
, y
)
59 #----------------------------------------------------------------------
61 class wxEditor(wxScrolledWindow
):
63 def __init__(self
, parent
, id,
64 pos
=wxDefaultPosition
, size
=wxDefaultSize
, style
=0):
66 wxScrolledWindow
.__init
__(self
, parent
, id,
75 self
.InitDoubleBuffering()
78 self
.CopiedData
= None
83 ##------------------ Init stuff
98 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
99 EVT_LEFT_UP(self
, self
.OnLeftUp
)
100 EVT_MOTION(self
, self
.OnMotion
)
101 EVT_SCROLLWIN(self
, self
.OnScroll
)
102 EVT_CHAR(self
, self
.OnChar
)
103 EVT_PAINT(self
, self
.OnPaint
)
104 EVT_SIZE(self
, self
.OnSize
)
105 EVT_WINDOW_DESTROY(self
, self
.OnDestroy
)
106 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
108 ##------------------- Platform-specific stuff
110 def NiceFontForPlatform(self
):
111 if wxPlatform
== "__WXMSW__":
112 return wxFont(10, wxMODERN
, wxNORMAL
, wxNORMAL
)
114 return wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, false
)
116 def UnixKeyHack(self
, key
):
117 # this will be obsolete when we get the new wxWindows patch
122 ##-------------------- UpdateView/Cursor code
124 def OnSize(self
, event
):
125 self
.AdjustScrollbars()
128 def SetCharDimensions(self
):
129 # TODO: We need a code review on this. It appears that Linux
130 # improperly reports window dimensions when the scrollbar's there.
131 self
.bw
, self
.bh
= self
.GetClientSizeTuple()
133 if wxPlatform
== "__WXMSW__":
134 self
.sh
= self
.bh
/ self
.fh
135 self
.sw
= (self
.bw
/ self
.fw
) - 1
137 self
.sh
= self
.bh
/ self
.fh
138 if self
.LinesInFile() >= self
.sh
:
139 self
.bw
= self
.bw
- wxSystemSettings_GetSystemMetric(wxSYS_VSCROLL_X
)
140 self
.sw
= (self
.bw
/ self
.fw
) - 1
142 self
.sw
= (self
.bw
/ self
.fw
) - 1
143 if self
.CalcMaxLineLen() >= self
.sw
:
144 self
.bh
= self
.bh
- wxSystemSettings_GetSystemMetric(wxSYS_HSCROLL_Y
)
145 self
.sh
= self
.bh
/ self
.fh
148 def UpdateView(self
, dc
= None):
150 dc
= wxClientDC(self
)
151 self
.SetCharDimensions()
152 self
.KeepCursorOnScreen()
153 self
.DrawSimpleCursor(0,0,dc
, true
)
156 def OnPaint(self
, event
):
159 self
.AdjustScrollbars()
161 def OnEraseBackground(self
, evt
):
164 ##-------------------- Drawing code
167 dc
= wxClientDC(self
)
168 self
.font
= self
.NiceFontForPlatform()
169 dc
.SetFont(self
.font
)
170 self
.fw
= dc
.GetCharWidth()
171 self
.fh
= dc
.GetCharHeight()
174 self
.fgColor
= wxNamedColour('black')
175 self
.bgColor
= wxNamedColour('white')
176 self
.selectColor
= wxColour(238, 220, 120) # r, g, b = emacsOrange
178 def InitDoubleBuffering(self
):
179 bw
,bh
= self
.GetClientSizeTuple()
180 self
.mdc
= wxMemoryDC()
181 self
.mdc
.SelectObject(wxEmptyBitmap(bw
,bh
))
183 def DrawEditText(self
, t
, x
, y
, dc
):
184 dc
.DrawText(t
, x
* self
.fw
, y
* self
.fh
)
186 def DrawLine(self
, line
, dc
):
187 if self
.IsLine(line
):
190 dc
.SetTextForeground(self
.fgColor
)
191 fragments
= selection
.Selection(
192 self
.SelectBegin
, self
.SelectEnd
,
193 self
.sx
, self
.sw
, line
, t
)
195 for (data
, selected
) in fragments
:
197 dc
.SetTextBackground(self
.selectColor
)
198 if x
== 0 and len(data
) == 0 and len(fragments
) == 1:
201 dc
.SetTextBackground(self
.bgColor
)
202 self
.DrawEditText(data
, x
, line
- self
.sy
, dc
)
205 def Draw(self
, odc
=None):
207 odc
= wxClientDC(self
)
210 dc
.SetFont(self
.font
)
211 dc
.SelectObject(wxEmptyBitmap(self
.bw
,self
.bh
))
212 dc
.SetBackgroundMode(wxSOLID
)
213 dc
.SetTextBackground(self
.bgColor
)
214 dc
.SetTextForeground(self
.fgColor
)
216 for line
in range(self
.sy
, self
.sy
+ self
.sh
):
217 self
.DrawLine(line
, dc
)
218 if len(self
.lines
) < self
.sh
+ self
.sy
:
219 self
.DrawEofMarker(dc
)
220 odc
.Blit(0,0,self
.bw
,self
.bh
,dc
,0,0,wxCOPY
)
223 ##------------------ eofMarker stuff
225 def LoadImages(self
):
226 self
.eofMarker
= images
.GetBitmap(images
.EofImageData
)
228 def DrawEofMarker(self
,dc
):
230 y
= (len(self
.lines
) - self
.sy
) * self
.fh
232 dc
.DrawBitmap(self
.eofMarker
, x
, y
, hasTransparency
)
234 ##------------------ cursor-related functions
236 def DrawCursor(self
, dc
= None):
238 dc
= wxClientDC(self
)
240 if (self
.LinesInFile())<self
.cy
: #-1 ?
241 self
.cy
= self
.LinesInFile()-1
242 s
= self
.lines
[self
.cy
]
244 x
= self
.cx
- self
.sx
245 y
= self
.cy
- self
.sy
246 self
.DrawSimpleCursor(x
, y
, dc
)
249 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=false
):
251 dc
= wxClientDC(self
)
261 dc
.Blit(x
,y
,szx
,szy
,dc
,x
,y
,wxSRC_INVERT
)
265 ##-------- Enforcing screen boundaries, cursor movement
267 def CalcMaxLineLen(self
):
268 """get length of longest line on screen"""
270 for line
in self
.lines
[self
.sy
:self
.sy
+self
.sh
]:
271 if len(line
) >maxlen
:
275 def KeepCursorOnScreen(self
):
276 self
.sy
= ForceBetween(max(0, self
.cy
-self
.sh
), self
.sy
, self
.cy
)
277 self
.sx
= ForceBetween(max(0, self
.cx
-self
.sw
), self
.sx
, self
.cx
)
278 self
.AdjustScrollbars()
280 def HorizBoundaries(self
):
281 self
.SetCharDimensions()
282 maxLineLen
= self
.CalcMaxLineLen()
283 self
.sx
= ForceBetween(0, self
.sx
, max(self
.sw
, maxLineLen
- self
.sw
+ 1))
284 self
.cx
= ForceBetween(self
.sx
, self
.cx
, self
.sx
+ self
.sw
- 1)
286 def VertBoundaries(self
):
287 self
.SetCharDimensions()
288 self
.sy
= ForceBetween(0, self
.sy
, max(self
.sh
, self
.LinesInFile() - self
.sh
+ 1))
289 self
.cy
= ForceBetween(self
.sy
, self
.cy
, self
.sy
+ self
.sh
- 1)
291 def cVert(self
, num
):
292 self
.cy
= self
.cy
+ num
293 self
.cy
= ForceBetween(0, self
.cy
, self
.LinesInFile() - 1)
294 self
.sy
= ForceBetween(self
.cy
- self
.sh
+ 1, self
.sy
, self
.cy
)
295 self
.cx
= min(self
.cx
, self
.CurrentLineLength())
297 def cHoriz(self
, num
):
298 self
.cx
= self
.cx
+ num
299 self
.cx
= ForceBetween(0, self
.cx
, self
.CurrentLineLength())
300 self
.sx
= ForceBetween(self
.cx
- self
.sw
+ 1, self
.sx
, self
.cx
)
302 def AboveScreen(self
, row
):
305 def BelowScreen(self
, row
):
306 return row
>= self
.sy
+ self
.sh
308 def LeftOfScreen(self
, col
):
311 def RightOfScreen(self
, col
):
312 return col
>= self
.sx
+ self
.sw
314 ##----------------- data structure helper functions
319 def SetText(self
, lines
):
324 self
.AdjustScrollbars()
325 self
.UpdateView(None)
327 def IsLine(self
, lineNum
):
328 return (0<=lineNum
) and (lineNum
<self
.LinesInFile())
330 def GetTextLine(self
, lineNum
):
331 if self
.IsLine(lineNum
):
332 return self
.lines
[lineNum
]
335 def SetTextLine(self
, lineNum
, text
):
336 if self
.IsLine(lineNum
):
337 self
.lines
[lineNum
] = text
339 def CurrentLineLength(self
):
340 return len(self
.lines
[self
.cy
])
342 def LinesInFile(self
):
343 return len(self
.lines
)
345 def UnTouchBuffer(self
):
346 self
.bufferTouched
= FALSE
348 def BufferWasTouched(self
):
349 return self
.bufferTouched
351 def TouchBuffer(self
):
352 self
.bufferTouched
= TRUE
355 ##-------------------------- Mouse scroll timing functions
357 def InitScrolling(self
):
358 # we don't rely on the windows system to scroll for us; we just
359 # redraw the screen manually every time
360 self
.EnableScrolling(FALSE
, FALSE
)
361 self
.nextScrollTime
= 0
362 self
.SCROLLDELAY
= 0.050 # seconds
363 self
.scrollTimer
= wxTimer(self
)
364 self
.scroller
= Scroller(self
)
367 if time
.time() > self
.nextScrollTime
:
368 self
.nextScrollTime
= time
.time() + self
.SCROLLDELAY
373 def SetScrollTimer(self
):
375 self
.scrollTimer
.Start(1000*self
.SCROLLDELAY
/2, oneShot
)
376 EVT_TIMER(self
, -1, self
.OnTimer
)
378 def OnTimer(self
, event
):
379 screenX
, screenY
= wxGetMousePosition()
380 x
, y
= self
.ScreenToClientXY(screenX
, screenY
)
385 ##-------------------------- Mouse off screen functions
387 def HandleAboveScreen(self
, row
):
388 self
.SetScrollTimer()
394 def HandleBelowScreen(self
, row
):
395 self
.SetScrollTimer()
397 row
= self
.sy
+ self
.sh
398 row
= min(row
, self
.LinesInFile() - 1)
401 def HandleLeftOfScreen(self
, col
):
402 self
.SetScrollTimer()
408 def HandleRightOfScreen(self
, col
):
409 self
.SetScrollTimer()
411 col
= self
.sx
+ self
.sw
412 col
= min(col
, self
.CurrentLineLength())
415 ##------------------------ mousing functions
417 def MouseToRow(self
, mouseY
):
418 row
= self
.sy
+ (mouseY
/ self
.fh
)
419 if self
.AboveScreen(row
):
420 self
.HandleAboveScreen(row
)
421 elif self
.BelowScreen(row
):
422 self
.HandleBelowScreen(row
)
424 self
.cy
= min(row
, self
.LinesInFile() - 1)
426 def MouseToCol(self
, mouseX
):
427 col
= self
.sx
+ (mouseX
/ self
.fw
)
428 if self
.LeftOfScreen(col
):
429 self
.HandleLeftOfScreen(col
)
430 elif self
.RightOfScreen(col
):
431 self
.HandleRightOfScreen(col
)
433 self
.cx
= min(col
, self
.CurrentLineLength())
435 def MouseToCursor(self
, event
):
436 self
.MouseToRow(event
.GetY())
437 self
.MouseToCol(event
.GetX())
439 def OnMotion(self
, event
):
440 if event
.LeftIsDown():
441 self
.Selecting
= true
442 self
.MouseToCursor(event
)
445 def OnLeftDown(self
, event
):
446 self
.MouseToCursor(event
)
447 self
.SelectBegin
= (self
.cy
, self
.cx
)
448 self
.SelectEnd
= None
452 def OnLeftUp(self
, event
):
453 if self
.SelectEnd
is None:
456 self
.Selecting
= false
457 self
.SelectNotify(false
, self
.SelectBegin
, self
.SelectEnd
)
460 self
.scrollTimer
.Stop()
463 #------------------------- Scrolling
465 def HorizScroll(self
, event
, eventType
):
466 maxLineLen
= self
.CalcMaxLineLen()
468 if eventType
== wxEVT_SCROLLWIN_LINEUP
:
470 elif eventType
== wxEVT_SCROLLWIN_LINEDOWN
:
472 elif eventType
== wxEVT_SCROLLWIN_PAGEUP
:
474 elif eventType
== wxEVT_SCROLLWIN_PAGEDOWN
:
476 elif eventType
== wxEVT_SCROLLWIN_TOP
:
477 self
.sx
= self
.cx
= 0
478 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
479 self
.sx
= maxLineLen
- self
.sw
482 self
.sx
= event
.GetPosition()
484 self
.HorizBoundaries()
486 def VertScroll(self
, event
, eventType
):
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
.sy
= self
.cy
= 0
497 elif eventType
== wxEVT_SCROLLWIN_BOTTOM
:
498 self
.sy
= self
.LinesInFile() - self
.sh
499 self
.cy
= self
.LinesInFile()
501 self
.sy
= event
.GetPosition()
503 self
.VertBoundaries()
505 def OnScroll(self
, event
):
506 dir = event
.GetOrientation()
507 eventType
= event
.GetEventType()
508 if dir == wxHORIZONTAL
:
509 self
.HorizScroll(event
, eventType
)
511 self
.VertScroll(event
, eventType
)
515 def AdjustScrollbars(self
):
517 self
.SetCharDimensions()
518 self
.scroller
.SetScrollbars(
520 self
.CalcMaxLineLen()+3, max(self
.LinesInFile()+1, self
.sh
),
523 #------------ backspace, delete, return
525 def BreakLine(self
, event
):
526 if self
.IsLine(self
.cy
):
527 t
= self
.lines
[self
.cy
]
528 self
.lines
= self
.lines
[:self
.cy
] + [t
[:self
.cx
],t
[self
.cx
:]] + self
.lines
[self
.cy
+1:]
533 def InsertChar(self
,char
):
534 if self
.IsLine(self
.cy
):
535 t
= self
.lines
[self
.cy
]
536 t
= t
[:self
.cx
] + char
+ t
[self
.cx
:]
537 self
.SetTextLine(self
.cy
, t
)
542 t1
= self
.lines
[self
.cy
]
543 t2
= self
.lines
[self
.cy
+1]
545 self
.lines
= self
.lines
[:self
.cy
] + [t1
+ t2
] + self
.lines
[self
.cy
+2:]
549 def DeleteChar(self
,x
,y
,oldtext
):
550 newtext
= oldtext
[:x
] + oldtext
[x
+1:]
551 self
.SetTextLine(y
, newtext
)
555 def BackSpace(self
, event
):
556 t
= self
.GetTextLine(self
.cy
)
558 self
.DeleteChar(self
.cx
-1,self
.cy
,t
)
569 def Delete(self
, event
):
570 t
= self
.GetTextLine(self
.cy
)
572 self
.DeleteChar(self
.cx
,self
.cy
,t
)
575 if self
.cy
< len(self
.lines
) - 1:
579 def Escape(self
, event
):
582 def TabKey(self
, event
):
583 numSpaces
= self
.SpacesPerTab
- (self
.cx
% self
.SpacesPerTab
)
584 self
.SingleLineInsert(' ' * numSpaces
)
586 ##----------- selection routines
588 def SelectUpdate(self
):
589 self
.SelectEnd
= (self
.cy
, self
.cx
)
590 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
593 def NormalizedSelect(self
):
594 (begin
, end
) = (self
.SelectBegin
, self
.SelectEnd
)
607 def FindSelection(self
):
608 if self
.SelectEnd
is None or self
.SelectBegin
is None:
611 (begin
, end
) = self
.NormalizedSelect()
614 return (bRow
, bCol
, eRow
, eCol
)
617 self
.SelectBegin
= None
618 self
.SelectEnd
= None
619 self
.Selecting
= false
620 self
.SelectNotify(false
,None,None)
622 def CopySelection(self
, event
):
623 selection
= self
.FindSelection()
624 if selection
is None:
626 (bRow
, bCol
, eRow
, eCol
) = selection
629 self
.SingleLineCopy(bRow
, bCol
, eCol
)
631 self
.MultipleLineCopy(bRow
, bCol
, eRow
, eCol
)
633 def OnCopySelection(self
, event
):
634 self
.CopySelection(event
)
637 def CopyData(self
, data
):
638 self
.CopiedData
= data
640 def SingleLineCopy(self
, Row
, bCol
, eCol
):
641 Line
= self
.GetTextLine(Row
)
642 self
.CopyData([Line
[bCol
:eCol
]])
644 def MultipleLineCopy(self
, bRow
, bCol
, eRow
, eCol
):
645 bLine
= self
.GetTextLine(bRow
)[bCol
:]
646 eLine
= self
.GetTextLine(eRow
)[:eCol
]
647 self
.CopyData([bLine
] + [l
for l
in self
.lines
[bRow
+ 1:eRow
]] + [eLine
])
649 def OnDeleteSelection(self
, event
):
650 selection
= self
.FindSelection()
651 if selection
is None:
653 (bRow
, bCol
, eRow
, eCol
) = selection
656 self
.SingleLineDelete(bRow
, bCol
, eCol
)
658 self
.MultipleLineDelete(bRow
, bCol
, eRow
, eCol
)
668 def SingleLineDelete(self
, Row
, bCol
, eCol
):
669 ModLine
= self
.GetTextLine(Row
)
670 ModLine
= ModLine
[:bCol
] + ModLine
[eCol
:]
671 self
.SetTextLine(Row
,ModLine
)
673 def MultipleLineDelete(self
, bRow
, bCol
, eRow
, eCol
):
674 bLine
= self
.GetTextLine(bRow
)
675 eLine
= self
.GetTextLine(eRow
)
676 ModLine
= bLine
[:bCol
] + eLine
[eCol
:]
677 self
.lines
[bRow
:eRow
+ 1] = [ModLine
]
679 def OnPaste(self
, event
):
680 if self
.CopiedData
is None:
683 elif len(self
.CopiedData
) == 0:
686 elif len(self
.CopiedData
) == 1:
687 self
.SingleLineInsert(self
.CopiedData
[0])
689 self
.MultipleLinePaste()
691 def SingleLineInsert(self
, newText
):
692 ModLine
= self
.GetTextLine(self
.cy
)
693 ModLine
= ModLine
[:self
.cx
] + newText
+ ModLine
[self
.cx
:]
694 self
.SetTextLine(self
.cy
, ModLine
)
695 self
.cHoriz(len(newText
))
699 def MultipleLinePaste(self
):
700 FirstLine
= LastLine
= self
.GetTextLine(self
.cy
)
701 FirstLine
= FirstLine
[:self
.cx
] + self
.CopiedData
[0]
702 LastLine
= self
.CopiedData
[-1] + LastLine
[self
.cx
:]
704 NewSlice
= [FirstLine
]
705 NewSlice
+= [l
for l
in self
.CopiedData
[1:-1]]
706 NewSlice
+= [LastLine
]
707 self
.lines
[self
.cy
:self
.cy
+ 1] = NewSlice
709 self
.cy
= self
.cy
+ len(self
.CopiedData
)-1
710 self
.cx
= len(self
.CopiedData
[-1])
714 def OnCutSelection(self
,event
):
715 self
.CopySelection(event
)
716 self
.OnDeleteSelection(event
)
718 #-------------- Keyboard movement implementations
720 def MoveDown(self
, event
):
723 def MoveUp(self
, event
):
726 def MoveLeft(self
, event
):
732 self
.cx
= self
.CurrentLineLength()
736 def MoveRight(self
, event
):
737 linelen
= self
.CurrentLineLength()
738 if self
.cx
== linelen
:
739 if self
.cy
== len(self
.lines
) - 1:
748 def MovePageDown(self
, event
):
751 def MovePageUp(self
, event
):
754 def MoveHome(self
, event
):
757 def MoveEnd(self
, event
):
758 self
.cx
= self
.CurrentLineLength()
760 def MoveStartOfFile(self
, event
):
764 def MoveEndOfFile(self
, event
):
765 self
.cy
= len(self
.lines
) - 1
766 self
.cx
= self
.CurrentLineLength()
768 #-------------- Key handler mapping tables
770 def SetMoveSpecialFuncs(self
, action
):
771 action
[WXK_DOWN
] = self
.MoveDown
772 action
[WXK_UP
] = self
.MoveUp
773 action
[WXK_LEFT
] = self
.MoveLeft
774 action
[WXK_RIGHT
] = self
.MoveRight
775 action
[WXK_NEXT
] = self
.MovePageDown
776 action
[WXK_PRIOR
] = self
.MovePageUp
777 action
[WXK_HOME
] = self
.MoveHome
778 action
[WXK_END
] = self
.MoveEnd
780 def SetMoveSpecialControlFuncs(self
, action
):
781 action
[WXK_HOME
] = self
.MoveStartOfFile
782 action
[WXK_END
] = self
.MoveEndOfFile
784 def SetAltFuncs(self
, action
):
785 # subclass implements
788 def SetControlFuncs(self
, action
):
789 action
['c'] = self
.OnCopySelection
790 action
['d'] = self
.OnDeleteSelection
791 action
['v'] = self
.OnPaste
792 action
['x'] = self
.OnCutSelection
794 def SetSpecialControlFuncs(self
, action
):
795 action
[WXK_INSERT
] = self
.OnCopySelection
797 def SetShiftFuncs(self
, action
):
798 action
[WXK_DELETE
] = self
.OnCutSelection
799 action
[WXK_INSERT
] = self
.OnPaste
801 def SetSpecialFuncs(self
, action
):
802 action
[WXK_BACK
] = self
.BackSpace
803 action
[WXK_DELETE
] = self
.Delete
804 action
[WXK_RETURN
] = self
.BreakLine
805 action
[WXK_ESCAPE
] = self
.Escape
806 action
[WXK_TAB
] = self
.TabKey
808 ##-------------- Logic for key handlers
811 def Move(self
, keySettingFunction
, key
, event
):
813 keySettingFunction(action
)
815 if not action
.has_key(key
):
818 if event
.ShiftDown():
819 if not self
.Selecting
:
820 self
.Selecting
= true
821 self
.SelectBegin
= (self
.cy
, self
.cx
)
823 self
.SelectEnd
= (self
.cy
, self
.cx
)
827 self
.Selecting
= false
829 self
.SelectNotify(self
.Selecting
, self
.SelectBegin
, self
.SelectEnd
)
833 def MoveSpecialKey(self
, event
, key
):
834 return self
.Move(self
.SetMoveSpecialFuncs
, key
, event
)
836 def MoveSpecialControlKey(self
, event
, key
):
837 if not event
.ControlDown():
839 return self
.Move(self
.SetMoveSpecialControlFuncs
, key
, event
)
841 def Dispatch(self
, keySettingFunction
, key
, event
):
843 keySettingFunction(action
)
844 if action
.has_key(key
):
850 def ModifierKey(self
, key
, event
, modifierKeyDown
, MappingFunc
):
851 if not modifierKeyDown
:
854 key
= self
.UnixKeyHack(key
)
859 if not self
.Dispatch(MappingFunc
, key
, event
):
863 def ControlKey(self
, event
, key
):
864 return self
.ModifierKey(key
, event
, event
.ControlDown(), self
.SetControlFuncs
)
866 def AltKey(self
, event
, key
):
867 return self
.ModifierKey(key
, event
, event
.AltDown(), self
.SetAltFuncs
)
869 def SpecialControlKey(self
, event
, key
):
870 if not event
.ControlDown():
872 if not self
.Dispatch(self
.SetSpecialControlFuncs
, key
, event
):
876 def ShiftKey(self
, event
, key
):
877 if not event
.ShiftDown():
879 return self
.Dispatch(self
.SetShiftFuncs
, key
, event
)
881 def NormalChar(self
, event
, key
):
885 if not self
.Dispatch(self
.SetSpecialFuncs
, key
, event
):
886 if (key
>31) and (key
<256):
887 self
.InsertChar(chr(key
))
892 self
.AdjustScrollbars()
894 def OnChar(self
, event
):
895 key
= event
.KeyCode()
896 filters
= [self
.AltKey
,
897 self
.MoveSpecialControlKey
,
899 self
.SpecialControlKey
,
903 for filter in filters
:
904 if filter(event
,key
):
908 #----------------------- Eliminate memory leaks
910 def OnDestroy(self
, event
):
916 self
.selectColor
= None
917 self
.scrollTimer
= None
918 self
.eofMarker
= None
920 #-------------------- Abstract methods for subclasses
925 def SelectNotify(self
, Selecting
, SelectionBegin
, SelectionEnd
):