1 from Carbon
import Evt
, Events
, Fm
, Fonts
2 from Carbon
import Qd
, Res
, Scrap
3 from Carbon
import TE
, TextEdit
, Win
5 from Carbon
.Appearance
import kThemeStateActive
, kThemeStateInactive
13 from types
import TupleType
, StringType
16 class TextBox(Wbase
.Widget
):
18 """A static text widget"""
20 def __init__(self
, possize
, text
="", align
=TextEdit
.teJustLeft
,
22 backgroundcolor
=(0xffff, 0xffff, 0xffff)
24 if fontsettings
is None:
26 fontsettings
= W
.getdefaultfont()
27 Wbase
.Widget
.__init
__(self
, possize
)
28 self
.fontsettings
= fontsettings
31 self
._backgroundcolor
= backgroundcolor
33 def draw(self
, visRgn
= None):
35 (font
, style
, size
, color
) = self
.fontsettings
36 fontid
= GetFNum(font
)
37 savestate
= Qd
.GetPenState()
41 Qd
.RGBForeColor(color
)
42 Qd
.RGBBackColor(self
._backgroundcolor
)
43 TE
.TETextBox(self
.text
, self
._bounds
, self
.align
)
44 Qd
.RGBBackColor((0xffff, 0xffff, 0xffff))
45 Qd
.SetPenState(savestate
)
52 if self
._parentwindow
and self
._parentwindow
.wid
:
60 def getscrollrects(self
):
61 """Return (destrect, viewrect)."""
66 def updatescrollbars(self
):
67 (dl
, dt
, dr
, db
), (vl
, vt
, vr
, vb
) = self
.getscrollrects()
68 if self
._parent
._barx
:
71 bar
= self
._parent
._barx
72 bar
.setmax(destwidth
- viewwidth
)
74 # MacOS 8.1 doesn't automatically disable
75 # scrollbars whose max <= min
76 bar
.enable(destwidth
> viewwidth
)
78 bar
.setviewsize(viewwidth
)
80 if self
._parent
._bary
:
83 bar
= self
._parent
._bary
84 bar
.setmax(destheight
- viewheight
)
86 # MacOS 8.1 doesn't automatically disable
87 # scrollbars whose max <= min
88 bar
.enable(destheight
> viewheight
)
90 bar
.setviewsize(viewheight
)
94 UNDOLABELS
= [ # Indexed by WEGetUndoInfo() value
95 None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style",
96 "Ruler", "backspace", "delete", "transform", "resize"]
99 class EditText(Wbase
.SelectableWidget
, _ScrollWidget
):
101 """A text edit widget, mainly for simple entry fields."""
103 def __init__(self
, possize
, text
="",
104 callback
=None, inset
=(3, 3),
106 tabsettings
= (32, 0),
108 if fontsettings
is None:
110 fontsettings
= W
.getdefaultfont()
111 Wbase
.SelectableWidget
.__init
__(self
, possize
)
114 self
.selection
= None
115 self
.oldselection
= None
116 self
._callback
= callback
122 self
.readonly
= readonly
123 self
.fontsettings
= fontsettings
124 self
.tabsettings
= tabsettings
125 if type(inset
) <> TupleType
:
126 self
.inset
= (inset
, inset
)
131 if not hasattr(self
._parent
, "_barx"):
132 self
._parent
._barx
= None
133 if not hasattr(self
._parent
, "_bary"):
134 self
._parent
._bary
= None
137 viewrect
, destrect
= self
._calctextbounds
()
138 flags
= self
._getflags
()
139 self
.ted
= waste
.WENew(destrect
, viewrect
, flags
)
140 self
.ted
.WEInstallTabHooks()
141 self
.ted
.WESetAlignment(WASTEconst
.weFlushLeft
)
142 self
.setfontsettings(self
.fontsettings
)
143 self
.settabsettings(self
.tabsettings
)
144 self
.ted
.WEUseText(Res
.Resource(self
.temptext
))
147 self
.setselection(self
.selection
[0], self
.selection
[1])
148 self
.selection
= None
152 self
.updatescrollbars()
153 self
.bind("pageup", self
.scrollpageup
)
154 self
.bind("pagedown", self
.scrollpagedown
)
155 self
.bind("top", self
.scrolltop
)
156 self
.bind("bottom", self
.scrollbottom
)
160 self
._parent
._barx
= None
161 self
._parent
._bary
= None
164 Wbase
.SelectableWidget
.close(self
)
166 def textchanged(self
, all
=0):
169 def selectionchanged(self
):
171 self
.oldselection
= self
.getselection()
173 def gettabsettings(self
):
174 return self
.tabsettings
176 def settabsettings(self
, (tabsize
, tabmode
)):
177 self
.tabsettings
= (tabsize
, tabmode
)
178 if hasattr(self
.ted
, "WESetTabSize"):
179 port
= self
._parentwindow
.wid
.GetWindowPort()
181 (font
, style
, size
, color
) = self
.getfontsettings()
182 savesettings
= GetPortFontSettings(port
)
183 SetPortFontSettings(port
, (font
, style
, size
))
184 tabsize
= Qd
.StringWidth(' ' * tabsize
)
185 SetPortFontSettings(port
, savesettings
)
186 tabsize
= max(tabsize
, 1)
187 self
.ted
.WESetTabSize(tabsize
)
189 Qd
.EraseRect(self
.ted
.WEGetViewRect())
190 self
.ted
.WEUpdate(port
.visRgn
)
192 def getfontsettings(self
):
193 from Carbon
import Res
194 (font
, style
, size
, color
) = self
.ted
.WEGetRunInfo(0)[4]
195 font
= Fm
.GetFontName(font
)
196 return (font
, style
, size
, color
)
198 def setfontsettings(self
, (font
, style
, size
, color
)):
200 if type(font
) <> StringType
:
201 font
= Fm
.GetFontName(font
)
202 self
.fontsettings
= (font
, style
, size
, color
)
203 fontid
= GetFNum(font
)
204 readonly
= self
.ted
.WEFeatureFlag(WASTEconst
.weFReadOnly
, -1)
206 self
.ted
.WEFeatureFlag(WASTEconst
.weFReadOnly
, 0)
208 self
.ted
.WEFeatureFlag(WASTEconst
.weFInhibitRecal
, 1)
209 selstart
, selend
= self
.ted
.WEGetSelection()
210 self
.ted
.WESetSelection(0, self
.ted
.WEGetTextLength())
211 self
.ted
.WESetStyle(WASTEconst
.weDoFace
, (0, 0, 0, (0, 0, 0)))
212 self
.ted
.WESetStyle(WASTEconst
.weDoFace |
213 WASTEconst
.weDoColor |
214 WASTEconst
.weDoFont |
216 (fontid
, style
, size
, color
))
217 self
.ted
.WEFeatureFlag(WASTEconst
.weFInhibitRecal
, 0)
219 self
.ted
.WESetSelection(selstart
, selend
)
222 self
.ted
.WEFeatureFlag(WASTEconst
.weFReadOnly
, 1)
223 viewrect
= self
.ted
.WEGetViewRect()
224 Qd
.EraseRect(viewrect
)
225 self
.ted
.WEUpdate(self
._parentwindow
.wid
.GetWindowPort().visRgn
)
226 self
.selectionchanged()
227 self
.updatescrollbars()
229 def adjust(self
, oldbounds
):
231 # Note: if App.DrawThemeEditTextFrame is ever used, it will be necessary
232 # to unconditionally outset the invalidated rectangles, since Appearance
233 # frames are drawn outside the bounds.
234 if self
._selected
and self
._parentwindow
._hasselframes
:
235 self
.GetWindow().InvalWindowRect(Qd
.InsetRect(oldbounds
, -3, -3))
236 self
.GetWindow().InvalWindowRect(Qd
.InsetRect(self
._bounds
, -3, -3))
238 self
.GetWindow().InvalWindowRect(oldbounds
)
239 self
.GetWindow().InvalWindowRect(self
._bounds
)
240 viewrect
, destrect
= self
._calctextbounds
()
241 self
.ted
.WESetViewRect(viewrect
)
242 self
.ted
.WESetDestRect(destrect
)
245 if self
.ted
.WEGetDestRect()[3] < viewrect
[1]:
247 self
.updatescrollbars()
249 # interface -----------------------
255 self
.ted
.WESetSelection(0, self
.ted
.WEGetTextLength())
256 self
.selectionchanged()
257 self
.updatescrollbars()
259 def selectline(self
, lineno
, charoffset
= 0):
260 newselstart
, newselend
= self
.ted
.WEGetLineRange(lineno
)
261 # Autoscroll makes the *end* of the selection visible, which,
262 # in the case of a whole line, is the beginning of the *next* line.
263 # So sometimes it leaves our line just above the view rect.
264 # Let's fool Waste by initially selecting one char less:
265 self
.ted
.WESetSelection(newselstart
+ charoffset
, newselend
-1)
266 self
.ted
.WESetSelection(newselstart
+ charoffset
, newselend
)
267 self
.selectionchanged()
268 self
.updatescrollbars()
270 def getselection(self
):
272 return self
.ted
.WEGetSelection()
274 return self
.selection
276 def setselection(self
, selstart
, selend
):
277 self
.selectionchanged()
279 self
.ted
.WESetSelection(selstart
, selend
)
281 self
.updatescrollbars()
283 self
.selection
= selstart
, selend
285 def offsettoline(self
, offset
):
286 return self
.ted
.WEOffsetToLine(offset
)
288 def countlines(self
):
289 return self
.ted
.WECountLines()
291 def getselectedtext(self
):
292 selstart
, selend
= self
.ted
.WEGetSelection()
293 return self
.ted
.WEGetText().data
[selstart
:selend
]
295 def expandselection(self
):
296 oldselstart
, oldselend
= self
.ted
.WEGetSelection()
297 selstart
, selend
= min(oldselstart
, oldselend
), max(oldselstart
, oldselend
)
298 if selstart
<> selend
and chr(self
.ted
.WEGetChar(selend
-1)) == '\r':
300 newselstart
, dummy
= self
.ted
.WEFindLine(selstart
, 1)
301 dummy
, newselend
= self
.ted
.WEFindLine(selend
, 1)
302 if oldselstart
<> newselstart
or oldselend
<> newselend
:
303 self
.ted
.WESetSelection(newselstart
, newselend
)
304 self
.updatescrollbars()
305 self
.selectionchanged()
307 def insert(self
, text
):
308 self
.ted
.WEInsert(text
, None, None)
310 self
.selectionchanged()
317 self
.ted
.WEUseText(Res
.Resource(text
))
320 viewrect
, destrect
= self
._calctextbounds
()
321 self
.ted
.WESetViewRect(viewrect
)
322 self
.ted
.WESetDestRect(destrect
)
324 Qd
.RectRgn(rgn
, viewrect
)
325 Qd
.EraseRect(viewrect
)
327 self
.updatescrollbars()
334 return self
.ted
.WEGetText().data
337 def key(self
, char
, event
):
338 (what
, message
, when
, where
, modifiers
) = event
339 if self
._enabled
and not modifiers
& Events
.cmdKey
or char
in Wkeys
.arrowkeys
:
340 self
.ted
.WEKey(ord(char
), modifiers
)
341 if char
not in Wkeys
.navigationkeys
:
343 if char
not in Wkeys
.scrollkeys
:
344 self
.selectionchanged()
345 self
.updatescrollbars()
347 Wbase
.CallbackCall(self
._callback
, 0, char
, modifiers
)
349 def click(self
, point
, modifiers
):
350 if not self
._enabled
:
352 self
.ted
.WEClick(point
, modifiers
, Evt
.TickCount())
353 self
.selectionchanged()
354 self
.updatescrollbars()
361 def rollover(self
, point
, onoff
):
363 Wbase
.SetCursor("iBeam")
365 def activate(self
, onoff
):
366 self
._activated
= onoff
370 # DISABLED! There are too many places where it is assumed that
371 # the frame of an EditText item is 1 pixel, inside the bounds.
372 #state = [kThemeStateActive, kThemeStateInactive][not onoff]
373 #App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
377 self
.ted
.WEActivate()
379 self
.ted
.WEDeactivate()
380 self
.drawselframe(onoff
)
382 def select(self
, onoff
, isclick
= 0):
383 if Wbase
.SelectableWidget
.select(self
, onoff
):
387 self
.ted
.WEActivate()
388 if self
._parentwindow
._tabbable
and not isclick
:
391 self
.ted
.WEDeactivate()
392 self
.drawselframe(onoff
)
394 def draw(self
, visRgn
= None):
397 visRgn
= self
._parentwindow
.wid
.GetWindowPort().visRgn
398 self
.ted
.WEUpdate(visRgn
)
400 # DISABLED! There are too many places where it is assumed that
401 # the frame of an EditText item is 1 pixel, inside the bounds.
402 #state = [kThemeStateActive, kThemeStateInactive][not self._activated]
403 #App.DrawThemeEditTextFrame(Qd.InsetRect(self._bounds, 1, 1), state)
404 Qd
.FrameRect(self
._bounds
)
406 if self
._selected
and self
._activated
:
410 def scrollpageup(self
):
411 if self
._parent
._bary
and self
._parent
._bary
._enabled
:
414 def scrollpagedown(self
):
415 if self
._parent
._bary
and self
._parent
._bary
._enabled
:
419 if self
._parent
._bary
and self
._parent
._bary
._enabled
:
420 self
.vscroll(self
._parent
._bary
.getmin())
421 if self
._parent
._barx
and self
._parent
._barx
._enabled
:
422 self
.hscroll(self
._parent
._barx
.getmin())
424 def scrollbottom(self
):
425 if self
._parent
._bary
and self
._parent
._bary
._enabled
:
426 self
.vscroll(self
._parent
._bary
.getmax())
429 def domenu_copy(self
, *args
):
430 selbegin
, selend
= self
.ted
.WEGetSelection()
431 if selbegin
== selend
:
433 if hasattr(Scrap
, 'ZeroScrap'):
436 Scrap
.ClearCurrentScrap()
438 self
.updatescrollbars()
440 def domenu_cut(self
, *args
):
441 selbegin
, selend
= self
.ted
.WEGetSelection()
442 if selbegin
== selend
:
444 if hasattr(Scrap
, 'ZeroScrap'):
447 Scrap
.ClearCurrentScrap()
449 self
.updatescrollbars()
452 self
.selectionchanged()
454 Wbase
.CallbackCall(self
._callback
, 0, "", None)
456 def domenu_paste(self
, *args
):
457 if not self
.ted
.WECanPaste():
461 self
.updatescrollbars()
463 self
.selectionchanged()
465 Wbase
.CallbackCall(self
._callback
, 0, "", None)
467 def domenu_clear(self
, *args
):
470 self
.updatescrollbars()
472 self
.selectionchanged()
474 Wbase
.CallbackCall(self
._callback
, 0, "", None)
476 def domenu_undo(self
, *args
):
477 which
, redo
= self
.ted
.WEGetUndoInfo()
481 self
.updatescrollbars()
483 self
.selectionchanged()
485 Wbase
.CallbackCall(self
._callback
, 0, "", None)
487 def can_undo(self
, menuitem
):
488 #doundo = self.ted.WEFeatureFlag(WASTEconst.weFUndo, -1)
492 which
, redo
= self
.ted
.WEGetUndoInfo()
493 if which
< len(UNDOLABELS
):
494 which
= UNDOLABELS
[which
]
500 which
= "Redo "+which
502 which
= "Undo "+which
503 menuitem
.settext(which
)
506 def domenu_selectall(self
, *args
):
510 def getscrollrects(self
):
511 return self
.ted
.WEGetDestRect(), self
.ted
.WEGetViewRect()
513 def vscroll(self
, value
):
514 lineheight
= self
.ted
.WEGetHeight(0, 1)
515 dr
= self
.ted
.WEGetDestRect()
516 vr
= self
.ted
.WEGetViewRect()
517 viewheight
= vr
[3] - vr
[1]
518 maxdelta
= vr
[1] - dr
[1]
519 mindelta
= vr
[3] - dr
[3]
525 delta
= viewheight
- lineheight
527 delta
= lineheight
- viewheight
529 delta
= vr
[1] - dr
[1] - value
530 delta
= min(maxdelta
, delta
)
531 delta
= max(mindelta
, delta
)
533 self
.ted
.WEScroll(0, delta
)
534 self
.updatescrollbars()
536 def hscroll(self
, value
):
537 dr
= self
.ted
.WEGetDestRect()
538 vr
= self
.ted
.WEGetViewRect()
539 destwidth
= dr
[2] - dr
[0]
540 viewwidth
= vr
[2] - vr
[0]
541 viewoffset
= maxdelta
= vr
[0] - dr
[0]
542 mindelta
= vr
[2] - dr
[2]
548 delta
= 0.5 * (vr
[2] - vr
[0])
550 delta
= 0.5 * (vr
[0] - vr
[2])
552 delta
= vr
[0] - dr
[0] - value
553 #cur = (32767 * viewoffset) / (destwidth - viewwidth)
554 #delta = (cur-value)*(destwidth - viewwidth)/32767
555 #if abs(delta - viewoffset) <=2:
556 # # compensate for irritating rounding error
558 delta
= min(maxdelta
, delta
)
559 delta
= max(mindelta
, delta
)
561 self
.ted
.WEScroll(delta
, 0)
562 self
.updatescrollbars()
566 flags
= WASTEconst
.weDoAutoScroll | WASTEconst
.weDoMonoStyled
568 flags
= flags | WASTEconst
.weDoReadOnly
570 flags
= flags | WASTEconst
.weDoUndo
573 def _getviewrect(self
):
574 return Qd
.InsetRect(self
._bounds
, self
.inset
[0], self
.inset
[1])
576 def _calctextbounds(self
):
577 viewrect
= l
, t
, r
, b
= self
._getviewrect
()
579 dl
, dt
, dr
, db
= self
.ted
.WEGetDestRect()
580 vl
, vt
, vr
, vb
= self
.ted
.WEGetViewRect()
582 if (db
- dt
) < (b
- t
):
585 destrect
= l
, dt
+ yshift
, r
, db
+ yshift
588 return viewrect
, destrect
591 class TextEditor(EditText
):
593 """A text edit widget."""
595 def __init__(self
, possize
, text
="", callback
=None, wrap
=1, inset
=(4, 4),
599 EditText
.__init
__(self
, possize
, text
, callback
, inset
, fontsettings
, tabsettings
, readonly
)
603 flags
= WASTEconst
.weDoAutoScroll | WASTEconst
.weDoMonoStyled | \
604 WASTEconst
.weDoOutlineHilite
606 flags
= flags | WASTEconst
.weDoReadOnly
608 flags
= flags | WASTEconst
.weDoUndo
611 def _getviewrect(self
):
612 l
, t
, r
, b
= self
._bounds
613 return (l
+ 5, t
+ 2, r
, b
- 2)
615 def _calctextbounds(self
):
617 return EditText
._calctextbounds
(self
)
619 viewrect
= l
, t
, r
, b
= self
._getviewrect
()
621 dl
, dt
, dr
, db
= self
.ted
.WEGetDestRect()
622 vl
, vt
, vr
, vb
= self
.ted
.WEGetViewRect()
625 if (db
- dt
) < (b
- t
):
627 destrect
= (dl
+ xshift
, dt
+ yshift
, dr
+ xshift
, db
+ yshift
)
629 destrect
= (l
, t
, r
+ 5000, b
)
630 return viewrect
, destrect
632 def draw(self
, visRgn
= None):
635 visRgn
= self
._parentwindow
.wid
.GetWindowPort().visRgn
636 self
.ted
.WEUpdate(visRgn
)
637 if self
._selected
and self
._activated
:
640 def activate(self
, onoff
):
641 self
._activated
= onoff
644 # doesn't draw frame, as EditText.activate does
647 self
.ted
.WEActivate()
649 self
.ted
.WEDeactivate()
650 self
.drawselframe(onoff
)
654 commentPat
= re
.compile("[ \t]*(#)")
655 indentPat
= re
.compile("[ \t]*")
656 kStringColor
= (0, 0x7fff, 0)
657 kCommentColor
= (0, 0, 0xb000)
660 class PyEditor(TextEditor
):
662 """A specialized Python source edit widget"""
664 def __init__(self
, possize
, text
="", callback
=None, inset
=(4, 4),
670 TextEditor
.__init
__(self
, possize
, text
, callback
, 0, inset
, fontsettings
, tabsettings
, readonly
)
671 self
.bind("cmd[", self
.domenu_shiftleft
)
672 self
.bind("cmd]", self
.domenu_shiftright
)
673 self
.bind("cmdshift[", self
.domenu_uncomment
)
674 self
.bind("cmdshift]", self
.domenu_comment
)
675 self
.bind("cmdshiftd", self
.alldirty
)
676 self
.file = file # only for debugger reference
677 self
._debugger
= debugger
679 debugger
.register_editor(self
, self
.file)
680 self
._dirty
= (0, None)
684 # TextEditor.open(self)
685 # if self.do_fontify:
687 # self._dirty = (None, None)
690 flags
= (WASTEconst
.weDoDrawOffscreen | WASTEconst
.weDoUseTempMem |
691 WASTEconst
.weDoAutoScroll | WASTEconst
.weDoOutlineHilite
)
693 flags
= flags | WASTEconst
.weDoReadOnly
695 flags
= flags | WASTEconst
.weDoUndo
698 def textchanged(self
, all
=0):
701 self
._dirty
= (0, None)
703 oldsel
= self
.oldselection
704 sel
= self
.getselection()
708 selstart
, selend
= sel
709 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
711 oldselstart
, oldselend
= min(oldsel
), max(oldsel
)
712 selstart
, selend
= min(selstart
, oldselstart
), max(selend
, oldselend
)
713 startline
= self
.offsettoline(selstart
)
714 endline
= self
.offsettoline(selend
)
715 selstart
, _
= self
.ted
.WEGetLineRange(startline
)
716 _
, selend
= self
.ted
.WEGetLineRange(endline
)
718 selstart
= selstart
- 1
719 self
._dirty
= (selstart
, selend
)
724 if not self
.do_fontify
:
726 start
, end
= self
._dirty
729 textLength
= self
.ted
.WEGetTextLength()
733 self
._dirty
= (None, None)
735 self
.fontify(start
, end
)
736 self
._dirty
= (None, None)
738 def alldirty(self
, *args
):
739 self
._dirty
= (0, None)
741 def fontify(self
, start
=0, end
=None):
742 #W.SetCursor('watch')
744 self
.ted
.WEFeatureFlag(WASTEconst
.weFReadOnly
, 0)
745 self
.ted
.WEFeatureFlag(WASTEconst
.weFOutlineHilite
, 0)
746 self
.ted
.WEDeactivate()
747 self
.ted
.WEFeatureFlag(WASTEconst
.weFAutoScroll
, 0)
748 self
.ted
.WEFeatureFlag(WASTEconst
.weFUndo
, 0)
749 pytext
= self
.get().replace("\r", "\n")
753 end
= min(end
, len(pytext
))
754 selstart
, selend
= self
.ted
.WEGetSelection()
755 self
.ted
.WESetSelection(start
, end
)
756 self
.ted
.WESetStyle(WASTEconst
.weDoFace | WASTEconst
.weDoColor
,
757 (0, 0, 12, (0, 0, 0)))
759 tags
= PyFontify
.fontify(pytext
, start
, end
)
761 'string': (WASTEconst
.weDoColor
, (0, 0, 0, kStringColor
)),
762 'keyword': (WASTEconst
.weDoFace
, (0, 1, 0, (0, 0, 0))),
763 'comment': (WASTEconst
.weDoFace | WASTEconst
.weDoColor
, (0, 0, 0, kCommentColor
)),
764 'identifier': (WASTEconst
.weDoColor
, (0, 0, 0, (0xbfff, 0, 0)))
766 setselection
= self
.ted
.WESetSelection
767 setstyle
= self
.ted
.WESetStyle
768 for tag
, start
, end
, sublist
in tags
:
769 setselection(start
, end
)
770 mode
, style
= styles
[tag
]
771 setstyle(mode
, style
)
772 self
.ted
.WESetSelection(selstart
, selend
)
774 self
.ted
.WEFeatureFlag(WASTEconst
.weFAutoScroll
, 1)
775 self
.ted
.WEFeatureFlag(WASTEconst
.weFUndo
, 1)
776 self
.ted
.WEActivate()
777 self
.ted
.WEFeatureFlag(WASTEconst
.weFOutlineHilite
, 1)
779 self
.ted
.WEFeatureFlag(WASTEconst
.weFReadOnly
, 1)
781 def domenu_shiftleft(self
):
782 self
.expandselection()
783 selstart
, selend
= self
.ted
.WEGetSelection()
784 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
785 snippet
= self
.getselectedtext()
786 lines
= string
.split(snippet
, '\r')
787 for i
in range(len(lines
)):
788 if lines
[i
][:1] == '\t':
789 lines
[i
] = lines
[i
][1:]
790 snippet
= string
.join(lines
, '\r')
792 self
.ted
.WESetSelection(selstart
, selstart
+ len(snippet
))
794 def domenu_shiftright(self
):
795 self
.expandselection()
796 selstart
, selend
= self
.ted
.WEGetSelection()
797 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
798 snippet
= self
.getselectedtext()
799 lines
= string
.split(snippet
, '\r')
800 for i
in range(len(lines
) - (not lines
[-1])):
801 lines
[i
] = '\t' + lines
[i
]
802 snippet
= string
.join(lines
, '\r')
804 self
.ted
.WESetSelection(selstart
, selstart
+ len(snippet
))
806 def domenu_uncomment(self
):
807 self
.expandselection()
808 selstart
, selend
= self
.ted
.WEGetSelection()
809 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
810 snippet
= self
.getselectedtext()
811 lines
= string
.split(snippet
, '\r')
812 for i
in range(len(lines
)):
813 m
= commentPat
.match(lines
[i
])
816 lines
[i
] = lines
[i
][:pos
] + lines
[i
][pos
+1:]
817 snippet
= string
.join(lines
, '\r')
819 self
.ted
.WESetSelection(selstart
, selstart
+ len(snippet
))
821 def domenu_comment(self
):
822 self
.expandselection()
823 selstart
, selend
= self
.ted
.WEGetSelection()
824 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
825 snippet
= self
.getselectedtext()
826 lines
= string
.split(snippet
, '\r')
827 indent
= 3000 # arbitrary large number...
829 if string
.strip(line
):
830 m
= indentPat
.match(line
)
832 indent
= min(indent
, m
.regs
[0][1])
836 for i
in range(len(lines
) - (not lines
[-1])):
837 lines
[i
] = lines
[i
][:indent
] + "#" + lines
[i
][indent
:]
838 snippet
= string
.join(lines
, '\r')
840 self
.ted
.WESetSelection(selstart
, selstart
+ len(snippet
))
842 def setfile(self
, file):
845 def set(self
, text
, file = ''):
849 self
._debugger
.unregister_editor(self
, oldfile
)
850 self
._debugger
.register_editor(self
, file)
851 TextEditor
.set(self
, text
)
855 self
._debugger
.unregister_editor(self
, self
.file)
856 self
._debugger
= None
857 TextEditor
.close(self
)
859 def click(self
, point
, modifiers
):
860 if not self
._enabled
:
862 if self
._debugger
and self
.pt_in_breaks(point
):
863 self
.breakhit(point
, modifiers
)
865 bl
, bt
, br
, bb
= self
._getbreakrect
()
866 Qd
.EraseRect((bl
, bt
, br
-1, bb
))
867 TextEditor
.click(self
, point
, modifiers
)
868 self
.drawbreakpoints()
870 TextEditor
.click(self
, point
, modifiers
)
871 if self
.ted
.WEGetClickCount() >= 3:
872 # select block with our indent
873 lines
= string
.split(self
.get(), '\r')
874 selstart
, selend
= self
.ted
.WEGetSelection()
875 lineno
= self
.ted
.WEOffsetToLine(selstart
)
878 while line
[tabs
:] and line
[tabs
] == '\t':
880 tabstag
= '\t' * tabs
884 for i
in range(lineno
- 1, -1, -1):
886 if line
[:tabs
] <> tabstag
:
889 for i
in range(lineno
+ 1, toline
):
891 if line
[:tabs
] <> tabstag
:
894 selstart
, dummy
= self
.ted
.WEGetLineRange(fromline
)
895 dummy
, selend
= self
.ted
.WEGetLineRange(toline
)
896 self
.ted
.WESetSelection(selstart
, selend
)
898 def breakhit(self
, point
, modifiers
):
901 destrect
= self
.ted
.WEGetDestRect()
902 offset
, edge
= self
.ted
.WEGetOffset(point
)
903 lineno
= self
.ted
.WEOffsetToLine(offset
) + 1
904 if point
[1] <= destrect
[3]:
905 self
._debugger
.clear_breaks_above(self
.file, self
.countlines())
906 self
._debugger
.toggle_break(self
.file, lineno
)
908 self
._debugger
.clear_breaks_above(self
.file, lineno
)
910 def key(self
, char
, event
):
911 (what
, message
, when
, where
, modifiers
) = event
912 if modifiers
& Events
.cmdKey
and not char
in Wkeys
.arrowkeys
:
915 selstart
, selend
= self
.ted
.WEGetSelection()
916 selstart
, selend
= min(selstart
, selend
), max(selstart
, selend
)
917 lastchar
= chr(self
.ted
.WEGetChar(selstart
-1))
918 if lastchar
<> '\r' and selstart
:
919 pos
, dummy
= self
.ted
.WEFindLine(selstart
, 0)
920 lineres
= Res
.Resource('')
921 self
.ted
.WECopyRange(pos
, selstart
, lineres
, None, None)
922 line
= lineres
.data
+ '\n'
923 tabcount
= self
.extratabs(line
)
924 self
.ted
.WEKey(ord('\r'), 0)
925 for i
in range(tabcount
):
926 self
.ted
.WEKey(ord('\t'), 0)
928 self
.ted
.WEKey(ord('\r'), 0)
930 self
.ted
.WEKey(ord(char
), modifiers
)
931 self
.balanceparens(char
)
933 self
.ted
.WEKey(ord(char
), modifiers
)
934 if char
not in Wkeys
.navigationkeys
:
936 self
.selectionchanged()
937 self
.updatescrollbars()
939 def balanceparens(self
, char
):
947 selstart
, selend
= self
.ted
.WEGetSelection()
948 count
= min(selstart
, selend
) - 2
949 mincount
= max(0, count
- 2048)
951 while count
> mincount
:
952 testchar
= chr(self
.ted
.WEGetChar(count
))
953 if testchar
in "\"'" and chr(self
.ted
.WEGetChar(count
- 1)) <> '\\':
954 if lastquote
== testchar
:
955 recursionlevel
= recursionlevel
- 1
958 recursionlevel
= recursionlevel
+ 1
960 elif not lastquote
and testchar
== char
:
961 recursionlevel
= recursionlevel
+ 1
962 elif not lastquote
and testchar
== target
:
963 recursionlevel
= recursionlevel
- 1
964 if recursionlevel
== 0:
966 autoscroll
= self
.ted
.WEFeatureFlag(WASTEconst
.weFAutoScroll
, -1)
968 self
.ted
.WEFeatureFlag(WASTEconst
.weFAutoScroll
, 0)
969 self
.ted
.WESetSelection(count
, count
+ 1)
970 self
._parentwindow
.wid
.GetWindowPort().QDFlushPortBuffer(None) # needed under OSX
972 self
.ted
.WESetSelection(selstart
, selend
)
974 self
.ted
.WEFeatureFlag(WASTEconst
.weFAutoScroll
, 1)
978 def extratabs(self
, line
):
983 tabcount
= tabcount
+ 1
986 tags
= PyFontify
.fontify(line
)
987 # strip comments and strings
988 for tag
, start
, end
, sublist
in tags
:
989 if tag
in ('string', 'comment'):
990 cleanline
= cleanline
+ line
[last
:start
]
992 cleanline
= cleanline
+ line
[last
:]
993 cleanline
= string
.strip(cleanline
)
994 if cleanline
and cleanline
[-1] == ':':
995 tabcount
= tabcount
+ 1
997 # extra indent after unbalanced (, [ or {
998 for open, close
in (('(', ')'), ('[', ']'), ('{', '}')):
999 count
= string
.count(cleanline
, open)
1000 if count
and count
> string
.count(cleanline
, close
):
1001 tabcount
= tabcount
+ 2
1005 def rollover(self
, point
, onoff
):
1007 if self
._debugger
and self
.pt_in_breaks(point
):
1008 Wbase
.SetCursor("arrow")
1010 Wbase
.SetCursor("iBeam")
1012 def draw(self
, visRgn
= None):
1013 TextEditor
.draw(self
, visRgn
)
1015 self
.drawbreakpoints()
1017 def showbreakpoints(self
, onoff
):
1018 if (not not self
._debugger
) <> onoff
:
1022 raise W
.AlertError
, "Can't debug in \"Optimize bytecode\" mode.\r(see \"Default startup options\" in EditPythonPreferences)"
1024 self
._debugger
= PyDebugger
.getdebugger()
1025 self
._debugger
.register_editor(self
, self
.file)
1026 elif self
._debugger
:
1027 self
._debugger
.unregister_editor(self
, self
.file)
1028 self
._debugger
= None
1029 self
.adjust(self
._bounds
)
1031 def togglebreakpoints(self
):
1032 self
.showbreakpoints(not self
._debugger
)
1034 def clearbreakpoints(self
):
1036 self
._debugger
.clear_all_file_breaks(self
.file)
1038 def editbreakpoints(self
):
1040 self
._debugger
.edit_breaks()
1041 self
._debugger
.breaksviewer
.selectfile(self
.file)
1043 def drawbreakpoints(self
, eraseall
= 0):
1044 breakrect
= bl
, bt
, br
, bb
= self
._getbreakrect
()
1047 Qd
.PenPat(Qd
.GetQDGlobalsGray())
1048 Qd
.PaintRect((br
, bt
, br
+ 1, bb
))
1050 self
._parentwindow
.tempcliprect(breakrect
)
1051 Qd
.RGBForeColor((0xffff, 0, 0))
1055 Qd_PaintOval
= Qd
.PaintOval
1056 Qd_EraseRect
= Qd
.EraseRect
1057 for lineno
in self
._debugger
.get_file_breaks(self
.file):
1058 start
, end
= self_ted
.WEGetLineRange(lineno
- 1)
1059 if lineno
<> self_ted
.WEOffsetToLine(start
) + 1:
1060 # breakpoints beyond our text: erase rest, and back out
1061 Qd_EraseRect((bl
, lasttop
, br
, bb
))
1063 (x
, y
), h
= self_ted
.WEGetPoint(start
, 0)
1065 #print y, (lasttop, bottom)
1066 if bottom
> lasttop
:
1067 Qd_EraseRect((bl
, lasttop
, br
, y
+ h
* eraseall
))
1069 redbullet
= bl
+ 2, y
+ 3, bl
+ 8, y
+ 9
1070 Qd_PaintOval(redbullet
)
1072 Qd_EraseRect((bl
, lasttop
, br
, bb
))
1073 Qd
.RGBForeColor((0, 0, 0))
1075 self
._parentwindow
.restoreclip()
1077 def updatescrollbars(self
):
1079 self
.drawbreakpoints(1)
1080 TextEditor
.updatescrollbars(self
)
1082 def pt_in_breaks(self
, point
):
1083 return Qd
.PtInRect(point
, self
._getbreakrect
())
1085 def _getbreakrect(self
):
1087 l
, t
, r
, b
= self
._bounds
1088 return (l
+1, t
+1, l
+ 12, b
-1)
1092 def _getviewrect(self
):
1093 l
, t
, r
, b
= self
._bounds
1095 return (l
+ 17, t
+ 2, r
, b
- 2)
1097 return (l
+ 5, t
+ 2, r
, b
- 2)
1099 def _calctextbounds(self
):
1100 viewrect
= l
, t
, r
, b
= self
._getviewrect
()
1102 dl
, dt
, dr
, db
= self
.ted
.WEGetDestRect()
1103 vl
, vt
, vr
, vb
= self
.ted
.WEGetViewRect()
1106 if (db
- dt
) < (b
- t
):
1108 destrect
= (dl
+ xshift
, dt
+ yshift
, dr
+ xshift
, db
+ yshift
)
1110 destrect
= (l
, t
, r
+ 5000, b
)
1111 return viewrect
, destrect
1114 def GetFNum(fontname
):
1115 """Same as Fm.GetFNum(), but maps a missing font to Monaco instead of the system font."""
1116 if fontname
<> Fm
.GetFontName(0):
1117 fontid
= Fm
.GetFNum(fontname
)
1119 fontid
= Fonts
.monaco
1124 # b/w compat. Anyone using this?
1125 GetFName
= Fm
.GetFontName
1127 def GetPortFontSettings(port
):
1128 return Fm
.GetFontName(port
.GetPortTextFont()), port
.GetPortTextFace(), port
.GetPortTextSize()
1130 def SetPortFontSettings(port
, (font
, face
, size
)):
1131 saveport
= Qd
.GetPort()
1133 Qd
.TextFont(GetFNum(font
))
1136 Qd
.SetPort(saveport
)