]>
git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/lib/editor/editor.py
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 #----------------------------------------------------------------------
14 # PLEASE NOTE: This is experimental code. It needs an overhall in the
15 # drawing and update code, and there is occasionally a
16 # mysteriously disappearing line...
18 # I am working on a StyledTextEditor that will likely
19 # render this editor obsolete... But this one is at
20 # least somewhat functional now while the other is still
26 from wxPython
.wx
import *
30 from tokenizer
import *
32 #---------------------------------------------------------------------------
36 def __init__(self
, text
=""):
37 self
.text
= text
# the string itself
38 self
.syntax
= [] # the colors of the line
39 self
.editable
= true
# edit?
40 self
.visible
= 0 # will be incremented if not
41 self
.indent
= 0 # not used yet
43 #----------------------------------------------------------------------
45 class wxEditor(wxScrolledWindow
):
47 def __init__(self
, parent
, id,
48 pos
=wxDefaultPosition
, size
=wxDefaultSize
, style
=0):
49 ###############################################################
51 Alles hat einen Anfang
54 wxScrolledWindow
.__init
__(self
, parent
, id,
58 # the syntax informations, if they don't exist,
59 # all syntax stuff will be ignored
65 # the lines that are visible
87 if wxPlatform
== "__WXMSW__":
88 self
.font
= wxFont(10, wxMODERN
, wxNORMAL
, wxNORMAL
)
90 self
.font
= wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, false
)
94 self
.fw
= dc
.GetCharWidth()
95 self
.fh
= dc
.GetCharHeight()
98 self
.bcol
= wxNamedColour('white')
99 self
.fcol
= wxNamedColour('black')
101 self
.cfcol
= wxNamedColour('black')
102 self
.cbcol
= wxNamedColour('red')
104 # nicht edierbare zeile (hintergrund)
105 self
.nedcol
= wxNamedColour('grey')
107 self
.SetBackgroundColour(self
.bcol
)
108 #dc.SetForegroundColour(self.fcol)
111 EVT_LEFT_DOWN(self
, self
.OnMouseClick
)
112 EVT_RIGHT_DOWN(self
, self
.OnMouseClick
)
113 EVT_SCROLLWIN(self
, self
.OnScroll
)
119 self
.o_line
= self
.line
126 self
.in_scroll
=FALSE
127 self
.inUpdate
= FALSE
130 bw
,bh
= self
.GetSizeTuple()
132 self
.mdc
= wxMemoryDC()
133 self
.mdc
.SelectObject(wxEmptyBitmap(bw
,bh
))
134 # disable physical scrolling because invisible parts are not drawn
135 self
.EnableScrolling(FALSE
, FALSE
)
137 # the ordinary text as it is
142 #---------------------------------------------------------------------------
145 ###############################################################
148 for line
in self
.text
:
152 if len(line
.text
) >maxlen
:
153 maxlen
=len(line
.text
)
155 self
.len = len(self
.lines
)
156 self
.max_linelength
=maxlen
159 def SetFontTab(self
, fonttab
):
160 ###############################################################
161 """ Fonttabelle zum schnellen Zugriff """
165 def SetText(self
, text
= [""]):
166 ###############################################################
167 """ Text mittels Liste setzen """
173 self
.text
.append(Line(t
))
175 for l
in range(0,len(text
)-1):
176 #self.UpdateSyntax(l)
177 self
.OnUpdateHighlight(l
)
182 self
.UpdateView(None, true
)
187 ###############################################################
188 """ Der gesamte Text als Liste """
190 for line
in self
.text
:
191 text
.append(line
.text
)
196 ###############################################################
197 """see if at least one text line is not empty"""
198 for line
in self
.text
:
199 if line
.text
: return 0
203 def IsLine(self
, line
):
204 ###############################################################
205 """ Schauen, ob alles im grünen Bereich ist """
206 return (line
>=0) and (line
<self
.len)
209 def IsEditable(self
, line
):
210 ###############################################################
211 return self
.text
[self
.GetLine(line
)].editable
214 def GetLine(self
, line
):
215 ###############################################################
216 return self
.lines
[line
]
219 def GetTextLine(self
, line
):
220 ###############################################################
222 if self
.IsLine(line
):
223 return self
.text
[self
.GetLine(line
)].text
227 def SetTextLine(self
, line
, text
):
228 ###############################################################
229 """ Nur den Text ändern """
230 if self
.IsLine(line
):
231 l
= self
.GetLine(line
)
232 self
.text
[l
].text
= text
233 #self.UpdateSyntax(l)
234 self
.OnUpdateHighlight(l
)
238 #---------------------------------------------------------------------------
240 def OnMouseClick(self
, event
):
241 ###############################################################
243 Wenn es Click gemacht hat => Cursor setzen
247 self
.cy
= self
.sy
+ (event
.GetY() / self
.fh
)
248 if self
.cy
>= self
.len: self
.cy
=max(self
.len -1, 0)
249 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
250 self
.cx
= self
.sx
+ (event
.GetX() / self
.fw
)
251 # allow positioning right behind the last character
252 if self
.cx
> linelen
: self
.cx
=linelen
253 if event
.GetEventType() ==wxEVT_RIGHT_DOWN
:
259 def DrawCursor(self
, dc
= None):
260 ###############################################################
262 Auch der Cursor muß ja irgendwie gezeichnet werden
265 dc
= wxClientDC(self
)
267 if (self
.len)<self
.cy
: #-1 ?
269 s
= self
.text
[self
.GetLine(self
.cy
)].text
271 x
= self
.cx
- self
.sx
272 y
= self
.cy
- self
.sy
273 self
.DrawSimpleCursor(x
, y
, dc
)
276 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=false
):
277 ###############################################################
279 Auch der Cursor muß ja irgendwie gezeichnet werden
282 dc
= wxClientDC(self
)
292 dc
.Blit(x
,y
,szx
,szy
,dc
,x
,y
,wxSRC_INVERT
)
297 def OnScroll(self
, event
):
298 dir =event
.GetOrientation()
299 evt
=event
.GetEventType()
300 if dir ==wxHORIZONTAL
:
301 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sx
=self
.sx
-1
302 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sx
=self
.sx
+1
303 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sx
=self
.sx
-self
.sw
304 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sx
=self
.sx
+self
.sw
305 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sx
=self
.cx
=0
306 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
307 self
.sx
=self
.max_linelength
-self
.sw
308 self
.cx
=self
.max_linelength
310 self
.sx
=event
.GetPosition()
312 if self
.sx
>(self
.max_linelength
-self
.sw
+1):
313 self
.sx
=self
.max_linelength
-self
.sw
+1
314 if self
.sx
<0: self
.sx
=0
315 if self
.cx
>(self
.sx
+self
.sw
-1): self
.cx
=self
.sx
+self
.sw
-1
316 if self
.cx
<self
.sx
: self
.cx
=self
.sx
319 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sy
=self
.sy
-1
320 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sy
=self
.sy
+1
321 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sy
=self
.sy
-self
.sh
322 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sy
=self
.sy
+self
.sh
323 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sy
=self
.cy
=0
324 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
325 self
.sy
=self
.len -self
.sh
328 self
.sy
=event
.GetPosition()
330 if self
.sy
>(self
.len -self
.sh
+1):
331 self
.sy
=self
.len -self
.sh
+1
332 if self
.sy
<0: self
.sy
=0
333 if self
.cy
>(self
.sy
+self
.sh
-1): self
.cy
=self
.sy
+self
.sh
-1
334 if self
.cy
<self
.sy
: self
.cy
=self
.sy
339 def AdjustScrollbars(self
):
340 # there appears to be endless recursion:
341 # SetScrollbars issue EvtPaint which calls UpdateView
342 # which calls AdjustScrollbars
343 if not self
.in_scroll
:
345 self
.SetScrollbars(self
.fw
, self
.fh
, self
.max_linelength
+1,
346 # it seem to be a bug in scrollbars:
347 # the scrollbar is hidden
348 # even if current position >0
349 max(self
.len +1, self
.sy
+self
.sh
),
351 self
.osx
, self
.osy
= self
.sx
, self
.sy
352 self
.in_scroll
=FALSE
355 # adapts the output to what it should be
356 def UpdateView(self
, dc
= None, doup
=false
):
357 ###############################################################
359 Diese Routine wird immer dann aufgerufen, wenn
360 sich etwas verändert hat
369 dc
= wxClientDC(self
)
371 self
.bw
,self
.bh
= self
.GetSizeTuple()
372 self
.sw
= self
.bw
/ self
.fw
373 self
.sh
= self
.bh
/ self
.fh
377 elif self
.cy
>(self
.sy
+self
.sh
-1):
378 self
.sy
= self
.cy
-self
.sh
+1
382 elif self
.cx
>(self
.sx
+self
.sw
-1):
383 self
.sx
= self
.cx
-self
.sw
+1
385 # left line? change syntax!
386 if self
.ocy
!=self
.cy
:
387 self
.OnUpdateSyntax(self
.ocy
)
391 if self
.osx
!= self
.sx
or self
.osy
!= self
.sy
:
392 self
.AdjustScrollbars()
394 self
.DrawSimpleCursor(0,0,dc
, true
)
395 # [als] i don't really understand how the following condition works
396 #if self.update or doup:
398 # self.update = false
400 # self.DrawCursor(dc)
406 self
.o_line
= self
.line
407 self
.inUpdate
= false
412 def DrawEditText(self
, t
, x
, y
, dc
= None):
413 ###############################################################
414 """ Einfache Hilfsroutine um Text zu schreiben
417 dc
= wxClientDC(self
)
418 dc
.SetFont(self
.font
)
419 dc
.DrawText(t
, x
* self
.fw
, y
* self
.fh
)
422 def DrawLine(self
, line
, dc
=None):
423 ###############################################################
425 Hier wird einfach die Ansicht der ganzen Seite
427 !!! Kann modifiziert werden !!!
431 dc
= wxClientDC(self
)
433 dc
.SetBackgroundMode(wxSOLID
)
434 dc
.SetTextBackground(self
.bcol
)
435 dc
.SetTextForeground(self
.fcol
)
440 lr
= self
.sx
+ self
.sw
444 if self
.IsLine(line
):
445 l
= self
.GetLine(line
)
446 t
= self
.text
[l
].text
447 syn
= self
.text
[l
].syntax
449 if not self
.text
[l
].editable
:
450 dc
.SetTextBackground(self
.nedcol
)
452 dc
.SetTextBackground(self
.bcol
)
454 dc
.SetTextForeground(self
.fcol
)
460 self
.DrawEditText(t
[pos
:xp
], (pos
-ll
), y
, dc
)
462 dc
.SetTextForeground(self
.ftab
[col
])
463 self
.DrawEditText(t
[pos
:], (pos
-ll
), y
, dc
)
466 def Draw(self
, odc
=None):
467 ###############################################################
469 Hier wird einfach die Ansicht der ganzen Seite
471 !!! Kann modifiziert werden !!!
475 odc
= wxClientDC(self
)
478 dc
.SelectObject(wxEmptyBitmap(self
.bw
,self
.bh
))
479 dc
.SetBackgroundMode(wxSOLID
)
480 dc
.SetTextBackground(self
.bcol
)
481 dc
.SetTextForeground(self
.fcol
)
483 for line
in range(self
.sy
, self
.sy
+ self
.sh
): self
.DrawLine(line
, dc
)
484 odc
.Blit(0,0,self
.bw
,self
.bh
,dc
,0,0,wxCOPY
)
488 def cVert(self
, num
):
489 ###############################################################
490 """ Vertikale Cursorverschiebung
494 elif cy
>(self
.len -1): cy
=self
.len -1
495 # scroll when edge hit
496 if cy
>(self
.sy
+self
.sh
-1): self
.sy
=cy
-self
.sh
+1
497 elif cy
<self
.sy
: self
.sy
=cy
499 # disallow positioning behind the end of the line
500 linelen
=len(self
.text
[self
.GetLine(cy
)].text
)
501 if self
.cx
>linelen
: self
.cx
=linelen
504 def cHoriz(self
, num
):
505 ###############################################################
506 """ Horizontale Cursorverschiebung
509 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
511 elif cx
>linelen
: cx
=linelen
512 # scroll when edge hit
513 if cx
>(self
.sx
+self
.sw
-2): self
.sx
=cx
-self
.sw
+2
514 elif cx
<self
.sx
: self
.sx
=cx
518 def InsertText(self
, text
):
519 ###############################################################
521 Simple Routine um Text - auch über mehrere
525 if self
.IsEditable(self
.cy
):
526 tis
= split(text
, "\n")
528 t
= self
.GetTextLine(self
.cy
)
531 t
= t
[:self
.cx
] + text
+ t
[self
.cx
:]
532 self
.SetTextLine(self
.cy
, t
)
533 self
.cHoriz(len(text
))
536 t
= t
[:self
.cx
] + tis
[0]
537 self
.SetTextLine(self
.cy
, t
)
538 for i
in range(1,len(tis
)):
539 self
.text
.insert(self
.GetLine(self
.cy
)+1, Line())
540 self
.lines
.insert(self
.cy
+1,self
.GetLine(self
.cy
)+1)
542 self
.SetTextLine(self
.cy
, tis
[i
])
543 t
= self
.GetTextLine(self
.cy
)
546 self
.SetTextLine(self
.cy
, t
)
550 #-----------------------------------------------------------------------------------------
552 def RemoveLine(self
, line
):
556 def OnChar(self
, event
):
557 ###############################################################
559 Wenn eine Taste gedrückt wird,
560 kann an dieser Stelle die Auswertung stattfinden
564 key
= event
.KeyCode()
566 # if event.ControlDown:
589 self
.cx
= len(self
.GetTextLine(self
.cy
))
592 t
= self
.GetTextLine(self
.cy
)
594 t
= t
[:self
.cx
-1] + t
[self
.cx
:]
595 self
.SetTextLine(self
.cy
, t
)
598 elif key
==WXK_DELETE
:
599 t
= self
.GetTextLine(self
.cy
)
601 t
= t
[:self
.cx
] + t
[self
.cx
+1:]
602 self
.SetTextLine(self
.cy
, t
)
604 elif key
==WXK_RETURN
:
605 self
.InsertText("\n")
608 self
.OnTabulator(event
)
612 if wxTheClipboard
.Open():
613 data
= wxTheClipboard
.GetData()
614 wxTheClipboard
.Close()
623 elif (key
>31) and (key
<256):
624 self
.InsertText(chr(key
))
630 def OnPaint(self
, event
):
632 self
.bw
,self
.bh
= self
.GetSizeTuple()
633 self
.UpdateView(dc
, true
)
636 #-----------------------------------------------------------------------------------------
638 def GetIndent(self
, line
):
642 elif c
=="\t": p
=(p
/self
.tabsize
+1) *self
.tabsize
648 self
.cVert(pos
-self
.cy
-1)
651 # --------------------------------------------------------
654 def OnUpdateHighlight(self
, line
= -1):
657 def OnUpdateSyntax(self
, line
= -1):
660 def OnTabulator(self
, event
):