]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/py/editwindow.py
Allow clearing the history, and saving the history on demand
[wxWidgets.git] / wxPython / wx / py / editwindow.py
1 """EditWindow class."""
2
3 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
4 __cvsid__ = "$Id$"
5 __revision__ = "$Revision$"[11:-2]
6
7 import wx
8 from wx import stc
9
10 import keyword
11 import os
12 import sys
13 import time
14
15 import dispatcher
16 from version import VERSION
17
18
19 if 'wxMSW' in wx.PlatformInfo:
20 FACES = { 'times' : 'Times New Roman',
21 'mono' : 'Courier New',
22 'helv' : 'Arial',
23 'lucida' : 'Lucida Console',
24 'other' : 'Comic Sans MS',
25 'size' : 10,
26 'lnsize' : 8,
27 'backcol' : '#FFFFFF',
28 'calltipbg' : '#FFFFB8',
29 'calltipfg' : '#404040',
30 }
31
32 elif 'wxGTK' in wx.PlatformInfo and 'gtk2' in wx.PlatformInfo:
33 FACES = { 'times' : 'Serif',
34 'mono' : 'Monospace',
35 'helv' : 'Sans',
36 'other' : 'new century schoolbook',
37 'size' : 10,
38 'lnsize' : 9,
39 'backcol' : '#FFFFFF',
40 'calltipbg' : '#FFFFB8',
41 'calltipfg' : '#404040',
42 }
43
44 elif 'wxMac' in wx.PlatformInfo:
45 FACES = { 'times' : 'Lucida Grande',
46 'mono' : 'Courier New',
47 'helv' : 'Geneva',
48 'other' : 'new century schoolbook',
49 'size' : 13,
50 'lnsize' : 10,
51 'backcol' : '#FFFFFF',
52 'calltipbg' : '#FFFFB8',
53 'calltipfg' : '#404040',
54 }
55
56 else: # GTK1, etc.
57 FACES = { 'times' : 'Times',
58 'mono' : 'Courier',
59 'helv' : 'Helvetica',
60 'other' : 'new century schoolbook',
61 'size' : 12,
62 'lnsize' : 10,
63 'backcol' : '#FFFFFF',
64 'calltipbg' : '#FFFFB8',
65 'calltipfg' : '#404040',
66 }
67
68
69 class EditWindow(stc.StyledTextCtrl):
70 """EditWindow based on StyledTextCtrl."""
71
72 revision = __revision__
73
74 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
75 size=wx.DefaultSize, style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
76 """Create EditWindow instance."""
77 stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
78 self.__config()
79 stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
80 dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
81 dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
82 dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
83
84 def _fontsizer(self, signal):
85 """Receiver for Font* signals."""
86 size = self.GetZoom()
87 if signal == 'FontIncrease':
88 size += 1
89 elif signal == 'FontDecrease':
90 size -= 1
91 elif signal == 'FontDefault':
92 size = 0
93 self.SetZoom(size)
94
95
96 def __config(self):
97 self.setDisplayLineNumbers(False)
98
99 self.SetLexer(stc.STC_LEX_PYTHON)
100 self.SetKeyWords(0, ' '.join(keyword.kwlist))
101
102 self.setStyles(FACES)
103 self.SetViewWhiteSpace(False)
104 self.SetTabWidth(4)
105 self.SetUseTabs(False)
106 # Do we want to automatically pop up command completion options?
107 self.autoComplete = True
108 self.autoCompleteIncludeMagic = True
109 self.autoCompleteIncludeSingle = True
110 self.autoCompleteIncludeDouble = True
111 self.autoCompleteCaseInsensitive = True
112 self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
113 self.autoCompleteAutoHide = False
114 self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
115 self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
116 # Do we want to automatically pop up command argument help?
117 self.autoCallTip = True
118 self.callTipInsert = True
119 self.CallTipSetBackground(FACES['calltipbg'])
120 self.CallTipSetForeground(FACES['calltipfg'])
121 self.SetWrapMode(False)
122 try:
123 self.SetEndAtLastLine(False)
124 except AttributeError:
125 pass
126
127 def setDisplayLineNumbers(self, state):
128 self.lineNumbers = state
129 if state:
130 self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
131 self.SetMarginWidth(1, 40)
132 else:
133 # Leave a small margin so the feature hidden lines marker can be seen
134 self.SetMarginType(1, 0)
135 self.SetMarginWidth(1, 10)
136
137 def setStyles(self, faces):
138 """Configure font size, typeface and color for lexer."""
139
140 # Default style
141 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
142 "face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
143 faces)
144
145 self.StyleClearAll()
146
147 # Built in styles
148 self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
149 "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % FACES)
150 self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
151 "face:%(mono)s" % faces)
152 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
153 "fore:#0000FF,back:#FFFF88")
154 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
155 "fore:#FF0000,back:#FFFF88")
156
157 # Python styles
158 self.StyleSetSpec(stc.STC_P_DEFAULT,
159 "face:%(mono)s" % faces)
160 self.StyleSetSpec(stc.STC_P_COMMENTLINE,
161 "fore:#007F00,face:%(mono)s" % faces)
162 self.StyleSetSpec(stc.STC_P_NUMBER,
163 "")
164 self.StyleSetSpec(stc.STC_P_STRING,
165 "fore:#7F007F,face:%(mono)s" % faces)
166 self.StyleSetSpec(stc.STC_P_CHARACTER,
167 "fore:#7F007F,face:%(mono)s" % faces)
168 self.StyleSetSpec(stc.STC_P_WORD,
169 "fore:#00007F,bold")
170 self.StyleSetSpec(stc.STC_P_TRIPLE,
171 "fore:#7F0000")
172 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
173 "fore:#000033,back:#FFFFE8")
174 self.StyleSetSpec(stc.STC_P_CLASSNAME,
175 "fore:#0000FF,bold")
176 self.StyleSetSpec(stc.STC_P_DEFNAME,
177 "fore:#007F7F,bold")
178 self.StyleSetSpec(stc.STC_P_OPERATOR,
179 "")
180 self.StyleSetSpec(stc.STC_P_IDENTIFIER,
181 "")
182 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
183 "fore:#7F7F7F")
184 self.StyleSetSpec(stc.STC_P_STRINGEOL,
185 "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
186
187 def OnUpdateUI(self, event):
188 """Check for matching braces."""
189 # If the auto-complete window is up let it do its thing.
190 if self.AutoCompActive() or self.CallTipActive():
191 return
192 braceAtCaret = -1
193 braceOpposite = -1
194 charBefore = None
195 caretPos = self.GetCurrentPos()
196 if caretPos > 0:
197 charBefore = self.GetCharAt(caretPos - 1)
198 styleBefore = self.GetStyleAt(caretPos - 1)
199
200 # Check before.
201 if charBefore and chr(charBefore) in '[]{}()' \
202 and styleBefore == stc.STC_P_OPERATOR:
203 braceAtCaret = caretPos - 1
204
205 # Check after.
206 if braceAtCaret < 0:
207 charAfter = self.GetCharAt(caretPos)
208 styleAfter = self.GetStyleAt(caretPos)
209 if charAfter and chr(charAfter) in '[]{}()' \
210 and styleAfter == stc.STC_P_OPERATOR:
211 braceAtCaret = caretPos
212
213 if braceAtCaret >= 0:
214 braceOpposite = self.BraceMatch(braceAtCaret)
215
216 if braceAtCaret != -1 and braceOpposite == -1:
217 self.BraceBadLight(braceAtCaret)
218 else:
219 self.BraceHighlight(braceAtCaret, braceOpposite)
220
221 def CanCopy(self):
222 """Return True if text is selected and can be copied."""
223 return self.GetSelectionStart() != self.GetSelectionEnd()
224
225 def CanCut(self):
226 """Return True if text is selected and can be cut."""
227 return self.CanCopy() and self.CanEdit()
228
229 def CanEdit(self):
230 """Return True if editing should succeed."""
231 return not self.GetReadOnly()
232
233 def CanPaste(self):
234 """Return True if pasting should succeed."""
235 return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
236
237
238 def GetLastPosition(self):
239 return self.GetLength()
240
241 def GetRange(self, start, end):
242 return self.GetTextRange(start, end)
243
244 def GetSelection(self):
245 return self.GetAnchor(), self.GetCurrentPos()
246
247 def ShowPosition(self, pos):
248 line = self.LineFromPosition(pos)
249 #self.EnsureVisible(line)
250 self.GotoLine(line)
251
252 def DoFindNext(self, findData, findDlg=None):
253 backward = not (findData.GetFlags() & wx.FR_DOWN)
254 matchcase = (findData.GetFlags() & wx.FR_MATCHCASE) != 0
255 end = self.GetLastPosition()
256 textstring = self.GetRange(0, end)
257 findstring = findData.GetFindString()
258 if not matchcase:
259 textstring = textstring.lower()
260 findstring = findstring.lower()
261 if backward:
262 start = self.GetSelection()[0]
263 loc = textstring.rfind(findstring, 0, start)
264 else:
265 start = self.GetSelection()[1]
266 loc = textstring.find(findstring, start)
267
268 # if it wasn't found then restart at begining
269 if loc == -1 and start != 0:
270 if backward:
271 start = end
272 loc = textstring.rfind(findstring, 0, start)
273 else:
274 start = 0
275 loc = textstring.find(findstring, start)
276
277 # was it still not found?
278 if loc == -1:
279 dlg = wx.MessageDialog(self, 'Unable to find the search text.',
280 'Not found!',
281 wx.OK | wx.ICON_INFORMATION)
282 dlg.ShowModal()
283 dlg.Destroy()
284 if findDlg:
285 if loc == -1:
286 wx.CallAfter(findDlg.SetFocus)
287 return
288 else:
289 findDlg.Close()
290
291 # show and select the found text
292 self.ShowPosition(loc)
293 self.SetSelection(loc, loc + len(findstring))