]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/editor/editor.py
bfae39281720bb9b1bd4f2c173c926611c28d38d
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
)
114 EVT_CHAR(self
, self
.OnChar
)
115 EVT_PAINT(self
, self
.OnPaint
)
121 self
.o_line
= self
.line
128 self
.in_scroll
=FALSE
129 self
.inUpdate
= FALSE
132 bw
,bh
= self
.GetSizeTuple()
134 self
.mdc
= wxMemoryDC()
135 self
.mdc
.SelectObject(wxEmptyBitmap(bw
,bh
))
136 # disable physical scrolling because invisible parts are not drawn
137 self
.EnableScrolling(FALSE
, FALSE
)
139 # the ordinary text as it is
144 #---------------------------------------------------------------------------
147 ###############################################################
150 for line
in self
.text
:
154 if len(line
.text
) >maxlen
:
155 maxlen
=len(line
.text
)
157 self
.len = len(self
.lines
)
158 self
.max_linelength
=maxlen
161 def SetFontTab(self
, fonttab
):
162 ###############################################################
163 """ Fonttabelle zum schnellen Zugriff """
167 def SetText(self
, text
= [""]):
168 ###############################################################
169 """ Text mittels Liste setzen """
175 self
.text
.append(Line(t
))
177 for l
in range(0,len(text
)-1):
178 #self.UpdateSyntax(l)
179 self
.OnUpdateHighlight(l
)
184 self
.UpdateView(None, true
)
189 ###############################################################
190 """ Der gesamte Text als Liste """
192 for line
in self
.text
:
193 text
.append(line
.text
)
198 ###############################################################
199 """see if at least one text line is not empty"""
200 for line
in self
.text
:
201 if line
.text
: return 0
205 def IsLine(self
, line
):
206 ###############################################################
207 """ Schauen, ob alles im grünen Bereich ist """
208 return (line
>=0) and (line
<self
.len)
211 def IsEditable(self
, line
):
212 ###############################################################
213 return self
.text
[self
.GetLine(line
)].editable
216 def GetLine(self
, line
):
217 ###############################################################
218 return self
.lines
[line
]
221 def GetTextLine(self
, line
):
222 ###############################################################
224 if self
.IsLine(line
):
225 return self
.text
[self
.GetLine(line
)].text
229 def SetTextLine(self
, line
, text
):
230 ###############################################################
231 """ Nur den Text ändern """
232 if self
.IsLine(line
):
233 l
= self
.GetLine(line
)
234 self
.text
[l
].text
= text
235 #self.UpdateSyntax(l)
236 self
.OnUpdateHighlight(l
)
240 #---------------------------------------------------------------------------
242 def OnMouseClick(self
, event
):
243 ###############################################################
245 Wenn es Click gemacht hat => Cursor setzen
249 self
.cy
= self
.sy
+ (event
.GetY() / self
.fh
)
250 if self
.cy
>= self
.len: self
.cy
=max(self
.len -1, 0)
251 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
252 self
.cx
= self
.sx
+ (event
.GetX() / self
.fw
)
253 # allow positioning right behind the last character
254 if self
.cx
> linelen
: self
.cx
=linelen
255 if event
.GetEventType() ==wxEVT_RIGHT_DOWN
:
261 def DrawCursor(self
, dc
= None):
262 ###############################################################
264 Auch der Cursor muß ja irgendwie gezeichnet werden
267 dc
= wxClientDC(self
)
269 if (self
.len)<self
.cy
: #-1 ?
271 s
= self
.text
[self
.GetLine(self
.cy
)].text
273 x
= self
.cx
- self
.sx
274 y
= self
.cy
- self
.sy
275 self
.DrawSimpleCursor(x
, y
, dc
)
278 def DrawSimpleCursor(self
, xp
, yp
, dc
= None, old
=false
):
279 ###############################################################
281 Auch der Cursor muß ja irgendwie gezeichnet werden
284 dc
= wxClientDC(self
)
294 dc
.Blit(x
,y
,szx
,szy
,dc
,x
,y
,wxSRC_INVERT
)
299 def OnScroll(self
, event
):
300 dir =event
.GetOrientation()
301 evt
=event
.GetEventType()
302 if dir ==wxHORIZONTAL
:
303 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sx
=self
.sx
-1
304 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sx
=self
.sx
+1
305 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sx
=self
.sx
-self
.sw
306 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sx
=self
.sx
+self
.sw
307 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sx
=self
.cx
=0
308 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
309 self
.sx
=self
.max_linelength
-self
.sw
310 self
.cx
=self
.max_linelength
312 self
.sx
=event
.GetPosition()
314 if self
.sx
>(self
.max_linelength
-self
.sw
+1):
315 self
.sx
=self
.max_linelength
-self
.sw
+1
316 if self
.sx
<0: self
.sx
=0
317 if self
.cx
>(self
.sx
+self
.sw
-1): self
.cx
=self
.sx
+self
.sw
-1
318 if self
.cx
<self
.sx
: self
.cx
=self
.sx
321 if evt
==wxEVT_SCROLLWIN_LINEUP
: self
.sy
=self
.sy
-1
322 elif evt
==wxEVT_SCROLLWIN_LINEDOWN
: self
.sy
=self
.sy
+1
323 elif evt
==wxEVT_SCROLLWIN_PAGEUP
: self
.sy
=self
.sy
-self
.sh
324 elif evt
==wxEVT_SCROLLWIN_PAGEDOWN
: self
.sy
=self
.sy
+self
.sh
325 elif evt
==wxEVT_SCROLLWIN_TOP
: self
.sy
=self
.cy
=0
326 elif evt
==wxEVT_SCROLLWIN_BOTTOM
:
327 self
.sy
=self
.len -self
.sh
330 self
.sy
=event
.GetPosition()
332 if self
.sy
>(self
.len -self
.sh
+1):
333 self
.sy
=self
.len -self
.sh
+1
334 if self
.sy
<0: self
.sy
=0
335 if self
.cy
>(self
.sy
+self
.sh
-1): self
.cy
=self
.sy
+self
.sh
-1
336 if self
.cy
<self
.sy
: self
.cy
=self
.sy
341 def AdjustScrollbars(self
):
342 # there appears to be endless recursion:
343 # SetScrollbars issue EvtPaint which calls UpdateView
344 # which calls AdjustScrollbars
345 if not self
.in_scroll
:
347 self
.SetScrollbars(self
.fw
, self
.fh
, self
.max_linelength
+1,
348 # it seem to be a bug in scrollbars:
349 # the scrollbar is hidden
350 # even if current position >0
351 max(self
.len +1, self
.sy
+self
.sh
),
353 self
.osx
, self
.osy
= self
.sx
, self
.sy
354 self
.in_scroll
=FALSE
357 # adapts the output to what it should be
358 def UpdateView(self
, dc
= None, doup
=false
):
359 ###############################################################
361 Diese Routine wird immer dann aufgerufen, wenn
362 sich etwas verändert hat
371 dc
= wxClientDC(self
)
373 self
.bw
,self
.bh
= self
.GetSizeTuple()
374 self
.sw
= self
.bw
/ self
.fw
375 self
.sh
= self
.bh
/ self
.fh
379 elif self
.cy
>(self
.sy
+self
.sh
-1):
380 self
.sy
= self
.cy
-self
.sh
+1
384 elif self
.cx
>(self
.sx
+self
.sw
-1):
385 self
.sx
= self
.cx
-self
.sw
+1
387 # left line? change syntax!
388 if self
.ocy
!=self
.cy
:
389 self
.OnUpdateSyntax(self
.ocy
)
393 if self
.osx
!= self
.sx
or self
.osy
!= self
.sy
:
394 self
.AdjustScrollbars()
396 self
.DrawSimpleCursor(0,0,dc
, true
)
397 # [als] i don't really understand how the following condition works
398 #if self.update or doup:
400 # self.update = false
402 # self.DrawCursor(dc)
408 self
.o_line
= self
.line
409 self
.inUpdate
= false
414 def DrawEditText(self
, t
, x
, y
, dc
= None):
415 ###############################################################
416 """ Einfache Hilfsroutine um Text zu schreiben
419 dc
= wxClientDC(self
)
420 dc
.SetFont(self
.font
)
421 dc
.DrawText(t
, x
* self
.fw
, y
* self
.fh
)
424 def DrawLine(self
, line
, dc
=None):
425 ###############################################################
427 Hier wird einfach die Ansicht der ganzen Seite
429 !!! Kann modifiziert werden !!!
433 dc
= wxClientDC(self
)
435 dc
.SetBackgroundMode(wxSOLID
)
436 dc
.SetTextBackground(self
.bcol
)
437 dc
.SetTextForeground(self
.fcol
)
442 lr
= self
.sx
+ self
.sw
446 if self
.IsLine(line
):
447 l
= self
.GetLine(line
)
448 t
= self
.text
[l
].text
449 syn
= self
.text
[l
].syntax
451 if not self
.text
[l
].editable
:
452 dc
.SetTextBackground(self
.nedcol
)
454 dc
.SetTextBackground(self
.bcol
)
456 dc
.SetTextForeground(self
.fcol
)
462 self
.DrawEditText(t
[pos
:xp
], (pos
-ll
), y
, dc
)
464 dc
.SetTextForeground(self
.ftab
[col
])
465 self
.DrawEditText(t
[pos
:], (pos
-ll
), y
, dc
)
468 def Draw(self
, odc
=None):
469 ###############################################################
471 Hier wird einfach die Ansicht der ganzen Seite
473 !!! Kann modifiziert werden !!!
477 odc
= wxClientDC(self
)
480 dc
.SelectObject(wxEmptyBitmap(self
.bw
,self
.bh
))
481 dc
.SetBackgroundMode(wxSOLID
)
482 dc
.SetTextBackground(self
.bcol
)
483 dc
.SetTextForeground(self
.fcol
)
485 for line
in range(self
.sy
, self
.sy
+ self
.sh
): self
.DrawLine(line
, dc
)
486 odc
.Blit(0,0,self
.bw
,self
.bh
,dc
,0,0,wxCOPY
)
490 def cVert(self
, num
):
491 ###############################################################
492 """ Vertikale Cursorverschiebung
496 elif cy
>(self
.len -1): cy
=self
.len -1
497 # scroll when edge hit
498 if cy
>(self
.sy
+self
.sh
-1): self
.sy
=cy
-self
.sh
+1
499 elif cy
<self
.sy
: self
.sy
=cy
501 # disallow positioning behind the end of the line
502 linelen
=len(self
.text
[self
.GetLine(cy
)].text
)
503 if self
.cx
>linelen
: self
.cx
=linelen
506 def cHoriz(self
, num
):
507 ###############################################################
508 """ Horizontale Cursorverschiebung
511 linelen
=len(self
.text
[self
.GetLine(self
.cy
)].text
)
513 elif cx
>linelen
: cx
=linelen
514 # scroll when edge hit
515 if cx
>(self
.sx
+self
.sw
-2): self
.sx
=cx
-self
.sw
+2
516 elif cx
<self
.sx
: self
.sx
=cx
520 def InsertText(self
, text
):
521 ###############################################################
523 Simple Routine um Text - auch über mehrere
527 if self
.IsEditable(self
.cy
):
528 tis
= split(text
, "\n")
530 t
= self
.GetTextLine(self
.cy
)
533 t
= t
[:self
.cx
] + text
+ t
[self
.cx
:]
534 self
.SetTextLine(self
.cy
, t
)
535 self
.cHoriz(len(text
))
538 t
= t
[:self
.cx
] + tis
[0]
539 self
.SetTextLine(self
.cy
, t
)
540 for i
in range(1,len(tis
)):
541 self
.text
.insert(self
.GetLine(self
.cy
)+1, Line())
542 self
.lines
.insert(self
.cy
+1,self
.GetLine(self
.cy
)+1)
544 self
.SetTextLine(self
.cy
, tis
[i
])
545 t
= self
.GetTextLine(self
.cy
)
548 self
.SetTextLine(self
.cy
, t
)
552 #-----------------------------------------------------------------------------------------
554 def RemoveLine(self
, line
):
558 def OnChar(self
, event
):
559 ###############################################################
561 Wenn eine Taste gedrückt wird,
562 kann an dieser Stelle die Auswertung stattfinden
566 key
= event
.KeyCode()
568 # if event.ControlDown:
591 self
.cx
= len(self
.GetTextLine(self
.cy
))
594 t
= self
.GetTextLine(self
.cy
)
596 t
= t
[:self
.cx
-1] + t
[self
.cx
:]
597 self
.SetTextLine(self
.cy
, t
)
600 elif key
==WXK_DELETE
:
601 t
= self
.GetTextLine(self
.cy
)
603 t
= t
[:self
.cx
] + t
[self
.cx
+1:]
604 self
.SetTextLine(self
.cy
, t
)
606 elif key
==WXK_RETURN
:
607 self
.InsertText("\n")
610 self
.OnTabulator(event
)
614 if wxTheClipboard
.Open():
615 data
= wxTheClipboard
.GetData()
616 wxTheClipboard
.Close()
625 elif (key
>31) and (key
<256):
626 self
.InsertText(chr(key
))
632 def OnPaint(self
, event
):
634 self
.bw
,self
.bh
= self
.GetSizeTuple()
635 self
.UpdateView(dc
, true
)
638 #-----------------------------------------------------------------------------------------
640 def GetIndent(self
, line
):
644 elif c
=="\t": p
=(p
/self
.tabsize
+1) *self
.tabsize
650 self
.cVert(pos
-self
.cy
-1)
653 # --------------------------------------------------------
656 def OnUpdateHighlight(self
, line
= -1):
659 def OnUpdateSyntax(self
, line
= -1):
662 def OnTabulator(self
, event
):