]>
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
):