1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.editor.wxEditor
3 # Purpose: An intelligent text editor with colorization capabilities.
5 # Author: Dirk Holtwic, Robin Dunn
9 # Copyright: (c) 1999 by Dirk Holtwick, 1999
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------
13 from wxPython
.wx
import *
17 from tokenizer
import *
19 #---------------------------------------------------------------------------
21 #EDITOR_STD_LINE = ("", [], (0,0,0))
26 def __init__(self
, text
=""):
27 self
.text
= text
# the string itself
28 self
.syntax
= [] # the colors of the line
29 self
.editable
= true
# edit?
30 self
.visible
= 0 # will be incremented if not
31 self
.indent
= 0 # not used yet
33 #----------------------------------------------------------------------
35 class wxEditor(wxScrolledWindow
):
37 def __init__(self
, parent
, id=-1):
38 ###############################################################
40 Alles hat einen Anfang
43 wxScrolledWindow
.__init
__(self
, parent
, id,
44 wxDefaultPosition
, wxSize(500,400),
45 wxSUNKEN_BORDER|wxWANTS_CHARS
)
47 # the syntax informations, if they don't exist,
48 # all syntax stuff will be ignored
54 # the lines that are visible
74 #if wxPlatform == "__WXMSW__":
75 self
.font
= wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
)
77 # self.font = wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, false)
81 self
.fw
= dc
.GetCharWidth()
82 self
.fh
= dc
.GetCharHeight()
85 self
.bcol
= wxNamedColour('white')
86 self
.fcol
= wxNamedColour('black')
88 self
.cfcol
= wxNamedColour('black')
89 self
.cbcol
= wxNamedColour('red')
91 # nicht edierbare zeile (hintergrund)
92 self
.nedcol
= wxNamedColour('grey')
94 self
.SetBackgroundColour(self
.bcol
)
95 #dc.SetForegroundColour(self.fcol)
98 EVT_LEFT_DOWN(self
, self
.OnMouseClick
)
99 EVT_RIGHT_DOWN(self
, self
.OnMouseClick
)
100 EVT_SCROLLWIN(self
, self
.OnScroll
)
106 self
.o_line
= self
.line
113 self
.in_scroll
=FALSE
115 bw
,bh
= self
.GetSizeTuple()
117 self
.mdc
= wxMemoryDC()
118 self
.mdc
.SelectObject(wxEmptyBitmap(bw
,bh
))
119 # disable physical scrolling because invisible parts are not drawn
120 self
.EnableScrolling(FALSE
, FALSE
)
122 # the ordinary text as it is
127 #---------------------------------------------------------------------------
130 ###############################################################
133 for line
in self
.text
:
137 if len(line
.text
) >maxlen
:
138 maxlen
=len(line
.text
)
140 self
.len = len(self
.lines
)
141 self
.max_linelength
=maxlen
143 def SetFontTab(self
, fonttab
):
144 ###############################################################
145 """ Fonttabelle zum schnellen Zugriff """
148 def SetText(self
, text
= [""]):
149 ###############################################################
150 """ Text mittels Liste setzen """
156 self
.text
.append(Line(t
))
158 for l
in range(0,len(text
)-1):
159 #self.UpdateSyntax(l)
160 self
.OnUpdateHighlight(l
)
165 self
.UpdateView(None, true
)
169 ###############################################################
170 """ Der gesamte Text als Liste """
172 for line
in self
.text
:
173 text
.append(line
.text
)
177 ###############################################################
178 """see if at least one text line is not empty"""
179 for line
in self
.text
:
180 if line
.text
: return 0
183 def IsLine(self
, line
):
184 ###############################################################
185 """ Schauen, ob alles im grünen Bereich ist """
186 return (line
>=0) and (line
<self
.len)
188 def IsEditable(self
, line
):
189 ###############################################################
190 return self
.text
[self
.GetLine(line
)].editable
192 def GetLine(self
, line
):
193 ###############################################################
194 return self
.lines
[line
]
196 def GetTextLine(self
, line
):
197 ###############################################################
199 if self
.IsLine(line
):
200 return self
.text
[self
.GetLine(line
)].text
203 def SetTextLine(self
, line
, text
):
204 ###############################################################
205 """ Nur den Text ändern """
206 if self
.IsLine(line
):
207 l
= self
.GetLine(line
)
208 self
.text
[l
].text
= text
209 #self.UpdateSyntax(l)
210 self
.OnUpdateHighlight(l
)
214 #---------------------------------------------------------------------------
216 def OnMouseClick(self
, event
):
217 ###############################################################
219 Wenn es Click gemacht hat => Cursor setzen
223 self
.cy
= self
.sy
+ (event
.GetY() / self
.fh
)
224 if self
.cy
>= self
.len: self
.cy
=max(self
.len -1, 0)
225 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
226 self
.cx
= self
.sx
+ (event
.GetX() / self
.fw
)
227 # allow positioning right behind the last character
228 if self
.cx
> linelen
: self
.cx
=linelen
229 if event
.GetEventType() ==wxEVT_RIGHT_DOWN
:
235 def DrawCursor(self
, dc
= None):
236 ###############################################################
238 Auch der Cursor muß ja irgendwie gezeichnet werden
241 dc
= wxClientDC(self
)
243 if (self
.len)<self
.cy
: #-1 ?
245 s
= self
.text
[self
.GetLine(self
.cy
)].text
247 x
= self
.cx
- self
.sx
248 y
= self
.cy
- self
.sy
249 self
.DrawSimpleCursor(x
, y
, dc
)
252 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=false
):
253 ###############################################################
255 Auch der Cursor muß ja irgendwie gezeichnet werden
258 dc
= wxClientDC(self
)
268 dc
.Blit(x
,y
,szx
,szy
,dc
,x
,y
,wxSRC_INVERT
)
272 def OnScroll(self
, event
):
273 dir =event
.GetOrientation()
274 evt
=event
.GetEventType()
275 if dir ==wxHORIZONTAL
:
276 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sx
=self
.sx
-1
277 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sx
=self
.sx
+1
278 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sx
=self
.sx
-self
.sw
279 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sx
=self
.sx
+self
.sw
280 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sx
=self
.cx
=0
281 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
282 self
.sx
=self
.max_linelength
-self
.sw
283 self
.cx
=self
.max_linelength
284 else: self
.sx
=event
.GetPosition()
285 if self
.sx
>(self
.max_linelength
-self
.sw
+1):
286 self
.sx
=self
.max_linelength
-self
.sw
+1
287 if self
.sx
<0: self
.sx
=0
288 if self
.cx
>(self
.sx
+self
.sw
-1): self
.cx
=self
.sx
+self
.sw
-1
289 if self
.cx
<self
.sx
: self
.cx
=self
.sx
291 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sy
=self
.sy
-1
292 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sy
=self
.sy
+1
293 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sy
=self
.sy
-self
.sh
294 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sy
=self
.sy
+self
.sh
295 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sy
=self
.cy
=0
296 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
297 self
.sy
=self
.len -self
.sh
299 else: self
.sy
=event
.GetPosition()
300 if self
.sy
>(self
.len -self
.sh
+1):
301 self
.sy
=self
.len -self
.sh
+1
302 if self
.sy
<0: self
.sy
=0
303 if self
.cy
>(self
.sy
+self
.sh
-1): self
.cy
=self
.sy
+self
.sh
-1
304 if self
.cy
<self
.sy
: self
.cy
=self
.sy
307 def AdjustScrollbars(self
):
308 # there appears to be endless recursion:
309 # SetScrollbars issue EvtPaint which calls UpdateView
310 # which calls AdjustScrollbars
311 if not self
.in_scroll
:
313 self
.SetScrollbars(self
.fw
, self
.fh
, self
.max_linelength
+1,
314 # it seem to be a bug in scrollbars:
315 # the scrollbar is hidden
316 # even if current position >0
317 max(self
.len +1, self
.sy
+self
.sh
),
319 self
.in_scroll
=FALSE
321 # adapts the output to what it should be
322 def UpdateView(self
, dc
= None, doup
=false
):
323 ###############################################################
325 Diese Routine wird immer dann aufgerufen, wenn
326 sich etwas verändert hat
332 dc
= wxClientDC(self
)
334 self
.bw
,self
.bh
= self
.GetSizeTuple()
335 self
.sw
= self
.bw
/ self
.fw
336 self
.sh
= self
.bh
/ self
.fh
340 elif self
.cy
>(self
.sy
+self
.sh
-1):
341 self
.sy
= self
.cy
-self
.sh
+1
345 elif self
.cx
>(self
.sx
+self
.sw
-1):
346 self
.sx
= self
.cx
-self
.sw
+1
348 # left line? change syntax!
349 if self
.ocy
!=self
.cy
:
350 self
.OnUpdateSyntax(self
.ocy
)
354 self
.AdjustScrollbars()
355 self
.DrawSimpleCursor(0,0,dc
, true
)
356 # [als] i don't really understand how the following condition works
357 if self
.update
or doup
:
367 self
.o_line
= self
.line
370 def DrawEditText(self
, t
, x
, y
, dc
= None):
371 ###############################################################
372 """ Einfache Hilfsroutine um Text zu schreiben
375 dc
= wxClientDC(self
)
376 dc
.SetFont(self
.font
)
377 dc
.DrawText(t
, x
* self
.fw
, y
* self
.fh
)
379 def DrawLine(self
, line
, dc
=None):
380 ###############################################################
382 Hier wird einfach die Ansicht der ganzen Seite
384 !!! Kann modifiziert werden !!!
388 dc
= wxClientDC(self
)
390 dc
.SetBackgroundMode(wxSOLID
)
391 dc
.SetTextBackground(self
.bcol
)
392 dc
.SetTextForeground(self
.fcol
)
397 lr
= self
.sx
+ self
.sw
401 if self
.IsLine(line
):
402 l
= self
.GetLine(line
)
403 t
= self
.text
[l
].text
404 syn
= self
.text
[l
].syntax
406 if not self
.text
[l
].editable
:
407 dc
.SetTextBackground(self
.nedcol
)
409 dc
.SetTextBackground(self
.bcol
)
411 dc
.SetTextForeground(self
.fcol
)
417 self
.DrawEditText(t
[pos
:xp
], (pos
-ll
), y
, dc
)
419 dc
.SetTextForeground(self
.ftab
[col
])
420 self
.DrawEditText(t
[pos
:], (pos
-ll
), y
, dc
)
422 def Draw(self
, odc
=None):
423 ###############################################################
425 Hier wird einfach die Ansicht der ganzen Seite
427 !!! Kann modifiziert werden !!!
431 odc
= wxClientDC(self
)
434 dc
.SelectObject(wxEmptyBitmap(self
.bw
,self
.bh
))
435 dc
.SetBackgroundMode(wxSOLID
)
436 dc
.SetTextBackground(self
.bcol
)
437 dc
.SetTextForeground(self
.fcol
)
439 for line
in range(self
.sy
, self
.sy
+ self
.sh
): self
.DrawLine(line
, dc
)
440 odc
.Blit(0,0,self
.bw
,self
.bh
,dc
,0,0,wxCOPY
)
444 def cVert(self
, num
):
445 ###############################################################
446 """ Vertikale Cursorverschiebung
450 elif cy
>(self
.len -1): cy
=self
.len -1
451 # scroll when edge hit
452 if cy
>(self
.sy
+self
.sh
-1): self
.sy
=cy
-self
.sh
+1
453 elif cy
<self
.sy
: self
.sy
=cy
455 # disallow positioning behind the end of the line
456 linelen
=len(self
.text
[self
.GetLine(cy
)].text
)
457 if self
.cx
>linelen
: self
.cx
=linelen
459 def cHoriz(self
, num
):
460 ###############################################################
461 """ Horizontale Cursorverschiebung
464 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
466 elif cx
>linelen
: cx
=linelen
467 # scroll when edge hit
468 if cx
>(self
.sx
+self
.sw
-2): self
.sx
=cx
-self
.sw
+2
469 elif cx
<self
.sx
: self
.sx
=cx
472 def InsertText(self
, text
):
473 ###############################################################
475 Simple Routine um Text - auch über mehrere
479 if self
.IsEditable(self
.cy
):
480 tis
= split(text
, "\n")
482 t
= self
.GetTextLine(self
.cy
)
485 t
= t
[:self
.cx
] + text
+ t
[self
.cx
:]
486 self
.SetTextLine(self
.cy
, t
)
487 self
.cHoriz(len(text
))
490 t
= t
[:self
.cx
] + tis
[0]
491 self
.SetTextLine(self
.cy
, t
)
492 for i
in range(1,len(tis
)):
493 self
.text
.insert(self
.GetLine(self
.cy
)+1, Line())
494 self
.lines
.insert(self
.cy
+1,self
.GetLine(self
.cy
)+1)
496 self
.SetTextLine(self
.cy
, tis
[i
])
497 t
= self
.GetTextLine(self
.cy
)
500 self
.SetTextLine(self
.cy
, t
)
504 #-----------------------------------------------------------------------------------------
506 def RemoveLine(self
, line
):
510 def OnChar(self
, event
):
511 ###############################################################
513 Wenn eine Taste gedrückt wird,
514 kann an dieser Stelle die Auswertung stattfinden
518 key
= event
.KeyCode()
520 # if event.ControlDown:
543 self
.cx
= len(self
.GetTextLine(self
.cy
))
546 t
= self
.GetTextLine(self
.cy
)
548 t
= t
[:self
.cx
-1] + t
[self
.cx
:]
549 self
.SetTextLine(self
.cy
, t
)
552 elif key
==WXK_DELETE
:
553 t
= self
.GetTextLine(self
.cy
)
555 t
= t
[:self
.cx
] + t
[self
.cx
+1:]
556 self
.SetTextLine(self
.cy
, t
)
558 elif key
==WXK_RETURN
:
559 self
.InsertText("\n")
562 self
.OnTabulator(event
)
566 if wxTheClipboard
.Open():
567 data
= wxTheClipboard
.GetData()
568 wxTheClipboard
.Close()
577 elif (key
>31) and (key
<256):
578 self
.InsertText(chr(key
))
584 def OnPaint(self
, event
):
586 self
.bw
,self
.bh
= self
.GetSizeTuple()
587 self
.UpdateView(dc
, true
)
589 #-----------------------------------------------------------------------------------------
591 def GetIndent(self
, line
):
595 elif c
=="\t": p
=(p
/self
.tabsize
+1) *self
.tabsize
600 self
.cVert(pos
-self
.cy
-1)
603 # --------------------------------------------------------
606 def OnUpdateHighlight(self
, line
= -1):
609 def OnUpdateSyntax(self
, line
= -1):
612 def OnTabulator(self
, event
):