2
# Presage, an extensible predictive text entry system
3
# ------------------------------------------------------
5
# Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License along
18
# with this program; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26
except ImportError, ex:
28
Error: failed to import module wxPython.
30
wxPython is a Python binding for the wxWidgets toolkit.
32
Check that wxPython is properly installed.
39
except ImportError, ex:
41
Error: failed to import module presage.
43
Check that presage python binding is properly installed (if
44
installed in a non-standard location, please set PYTHONPATH
47
Check that presage library is properly installed (if installed in a
48
non-standard location, please set LD_LIBRARY_PATH (PATH, LIBPATH)
57
class Prompter(wx.App):
58
def __init__(self, version, config=None, suggestions=None, redirect=False):
59
self.version = version # do this first, wx.App.__init__() calls OnInit()
61
self.suggestions = suggestions
62
wx.App.__init__(self, redirect)
65
self.frame = PrompterFrame(parent=None, id=-1, title='pyprompter', version=self.version, config=self.config, suggestions=self.suggestions)
66
self.SetTopWindow(self.frame)
72
class PrompterFrame(wx.Frame):
73
wildcard = "Text files (*.txt)|*.txt|" \
76
def __init__(self, parent, id, title, version, config, suggestions):
77
wx.Frame.__init__(self, parent, id, title)
78
self.version = version
80
self.editor = PrompterEditor(self, config, suggestions)
85
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
86
self.sizer.Add(self.editor, 1, wx.EXPAND)
87
self.SetSizer(self.sizer)
88
self.SetAutoLayout(True)
91
def MakeMenuBar(self):
92
def BindMenu(item, handler):
93
self.Bind(wx.EVT_MENU, handler, item)
96
self.fileMenu = wx.Menu()
97
BindMenu(self.fileMenu.Append(wx.ID_NEW, "&New\tCTRL+N"), self.OnFileMenuNew)
98
BindMenu(self.fileMenu.Append(wx.ID_OPEN, "&Open\tCTRL+O"), self.OnFileMenuOpen)
99
self.fileMenu.AppendSeparator()
100
BindMenu(self.fileMenu.Append(wx.ID_SAVE, "&Save\tCTRL+S"), self.OnFileMenuSave)
101
BindMenu(self.fileMenu.Append(wx.ID_SAVEAS, "Save &As\tSHIFT+CTRL+S"), self.OnFileMenuSaveAs)
102
self.fileMenu.AppendSeparator()
103
BindMenu(self.fileMenu.Append(wx.ID_CLOSE, "&Close\tCTRL+W"), self.OnFileMenuClose)
104
BindMenu(self.fileMenu.Append(wx.ID_EXIT, "&Quit\tCTRL+Q"), self.OnFileMenuQuit)
107
self.editMenu = wx.Menu()
108
BindMenu(self.editMenu.Append(wx.ID_UNDO, "&Undo\tCTRL+Z"), self.OnEditMenuUndo)
109
BindMenu(self.editMenu.Append(wx.ID_REDO, "&Redo\tSHIFT+CTRL+Z"), self.OnEditMenuRedo)
110
self.editMenu.AppendSeparator()
111
BindMenu(self.editMenu.Append(wx.ID_CUT, "Cu&t\tCTRL+X"), self.OnEditMenuCut)
112
BindMenu(self.editMenu.Append(wx.ID_COPY, "&Copy\tCTRL+C"), self.OnEditMenuCopy)
113
BindMenu(self.editMenu.Append(wx.ID_PASTE, "&Paste\tCTRL+V"), self.OnEditMenuPaste)
114
self.editMenu.AppendSeparator()
115
BindMenu(self.editMenu.Append(wx.ID_SELECTALL, "Select &All\tCTRL+A"), self.OnEditMenuSelectAll)
119
self.viewMenu = wx.Menu()
120
self.ID_TOGGLE_WORD_WRAP = wx.NewId()
121
# need to save wxMenuItem object returned by Append() to test if checked or not
122
self.word_wrap = self.viewMenu.Append(self.ID_TOGGLE_WORD_WRAP,
124
"Toggle word wrap mode",
126
BindMenu(self.word_wrap, self.OnViewMenuWordWrap)
127
# turn text_wrap checked menu item on at start-up
128
self.viewMenu.Check(self.ID_TOGGLE_WORD_WRAP, True)
129
self.viewMenu.AppendSeparator()
130
BindMenu(self.viewMenu.Append(wx.ID_ZOOM_IN, "L&arger text\tCTRL++"), self.OnViewMenuLargerText)
131
BindMenu(self.viewMenu.Append(wx.ID_ZOOM_OUT, "S&maller text\tCTRL+-"), self.OnViewMenuSmallerText)
132
self.viewMenu.AppendSeparator()
133
self.ID_SHOW_TOOLBAR = wx.NewId()
134
self.show_toolbar_view_menu_item = self.viewMenu.Append(self.ID_SHOW_TOOLBAR,
138
BindMenu(self.show_toolbar_view_menu_item, self.OnViewMenuShowToolbar)
139
self.viewMenu.Check(self.ID_SHOW_TOOLBAR, True)
142
self.presageMenu = wx.Menu()
143
self.ID_PROMPT_ME = wx.NewId()
144
BindMenu(self.presageMenu.Append(self.ID_PROMPT_ME, "&Prompt me\tCTRL+P"), self.OnPresageMenuPromptMe)
146
learn_mode = self.editor.prsg.config(self.editor.learn_mode_config_var)
147
if learn_mode.lower() == 'true':
149
elif learn_mode.lower() == 'false':
151
self.ID_TOGGLE_LEARN_MODE = wx.NewId()
152
self.learn_presage_menu_item = self.presageMenu.Append(self.ID_TOGGLE_LEARN_MODE,
153
"&Learn mode\tCTRL+L",
156
self.presageMenu.Check(self.ID_TOGGLE_LEARN_MODE, learn_mode)
157
BindMenu(self.learn_presage_menu_item, self.OnPresageMenuToggleLearnMode)
159
self.ID_TOGGLE_FUNCTION_KEYS_MODE = wx.NewId()
160
self.function_mode_presage_menu_item = self.presageMenu.Append(self.ID_TOGGLE_FUNCTION_KEYS_MODE,
161
"&Function keys\tCTRL+F",
162
"Toggle function keys mode",
164
self.presageMenu.Check(self.ID_TOGGLE_FUNCTION_KEYS_MODE, True)
165
BindMenu(self.function_mode_presage_menu_item, self.OnPresageMenuToggleFunctionMode)
167
self.ID_TOGGLE_AUTOPUNCTUATION_MODE = wx.NewId()
168
self.autopunctuation_mode_presage_menu_item = self.presageMenu.Append(self.ID_TOGGLE_AUTOPUNCTUATION_MODE,
169
"&Autopunctuation\tCTRL+A",
170
"Toggle autopunctuation mode",
172
self.presageMenu.Check(self.ID_TOGGLE_AUTOPUNCTUATION_MODE, True)
173
BindMenu(self.autopunctuation_mode_presage_menu_item, self.OnPresageMenuToggleAutopunctuationMode)
176
self.helpMenu = wx.Menu()
177
BindMenu(self.helpMenu.Append(wx.ID_HELP, "&Contents"), self.OnHelpMenuContents)
178
self.helpMenu.AppendSeparator()
179
BindMenu(self.helpMenu.Append(wx.ID_ABOUT, "&About"), self.OnHelpMenuAbout)
182
self.menuBar = wx.MenuBar()
183
self.menuBar.Append(self.fileMenu, "&File")
184
self.menuBar.Append(self.editMenu, "&Edit")
185
self.menuBar.Append(self.viewMenu, "&View")
186
self.menuBar.Append(self.presageMenu, "&Presage")
187
self.menuBar.Append(self.helpMenu, "&Help")
188
self.SetMenuBar(self.menuBar)
190
# grey out menu items
191
self.fileMenu.Enable(wx.ID_SAVE, False)
192
self.fileMenu.Enable(wx.ID_SAVEAS, False)
194
self.editMenu.Enable(wx.ID_UNDO, False)
195
self.editMenu.Enable(wx.ID_REDO, False)
197
def MakeToolBar(self):
198
def BindTool(item, handler):
199
self.Bind(wx.EVT_TOOL, handler, item)
200
self.Bind(wx.EVT_TOOL_RCLICKED, handler, item)
202
self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL
207
new_bmp = wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, tsize)
208
open_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize)
209
save_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize)
211
undo_bmp = wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_TOOLBAR, tsize)
212
redo_bmp = wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR, tsize)
214
cut_bmp = wx.ArtProvider.GetBitmap(wx.ART_CUT, wx.ART_TOOLBAR, tsize)
215
copy_bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_TOOLBAR, tsize)
216
paste_bmp= wx.ArtProvider.GetBitmap(wx.ART_PASTE, wx.ART_TOOLBAR, tsize)
218
prompt_me_bmp= wx.ArtProvider.GetBitmap(wx.ART_TIP, wx.ART_TOOLBAR, tsize)
220
self.toolbar.SetToolBitmapSize(tsize)
222
BindTool(self.toolbar.AddLabelTool(wx.ID_NEW, "New", new_bmp, shortHelp="New", longHelp="New file"),
224
BindTool(self.toolbar.AddLabelTool(wx.ID_OPEN, "Open", open_bmp, shortHelp="Open", longHelp="Open file"),
226
BindTool(self.toolbar.AddLabelTool(wx.ID_SAVE, "Save", save_bmp, shortHelp="Save", longHelp="Save file"),
228
self.toolbar.AddSeparator()
229
BindTool(self.toolbar.AddLabelTool(wx.ID_UNDO, "Undo", undo_bmp, shortHelp="Undo", longHelp="Undo last action"),
231
BindTool(self.toolbar.AddLabelTool(wx.ID_REDO, "Redo", redo_bmp, shortHelp="Redo", longHelp="Redo last action"),
233
self.toolbar.AddSeparator()
234
BindTool(self.toolbar.AddLabelTool(wx.ID_CUT, "Cut", cut_bmp, shortHelp="Cut", longHelp="Cut selection"),
236
BindTool(self.toolbar.AddLabelTool(wx.ID_COPY, "Copy", copy_bmp, shortHelp="Copy", longHelp="Copy selection"),
238
BindTool(self.toolbar.AddLabelTool(wx.ID_PASTE, "Paste", paste_bmp, shortHelp="Paste", longHelp="Paste selection"),
239
self.OnEditMenuPaste)
240
self.toolbar.AddSeparator()
241
BindTool(self.toolbar.AddLabelTool(self.ID_PROMPT_ME, "Prompt me", prompt_me_bmp, shortHelp="Prompt me", longHelp="Prompt me with a prediction"),
242
self.OnPresageMenuPromptMe)
244
self.toolbar.Realize()
247
def OnFileMenuNew(self, event):
248
self.editor.file = None
249
self.editor.ClearAll()
250
self.fileMenu.Enable(wx.ID_SAVE, False)
251
self.fileMenu.Enable(wx.ID_SAVEAS, False)
253
def OnFileMenuOpen(self, event):
254
print "Opening a file.."
256
# Create the dialog. In this case the current directory is forced as the starting
257
# directory for the dialog, and no default file name is forced. This can easilly
258
# be changed in your program. This is an 'open' dialog, and allows multitple
259
# file selections as well.
261
# Finally, if the directory is changed in the process of getting files, this
262
# dialog is set up to change the current working directory to the path chosen.
264
self, message="Choose a file", defaultDir="",
265
defaultFile="", wildcard=self.wildcard, style=wx.OPEN | wx.CHANGE_DIR
268
# Show the dialog and retrieve the user response. If it is the OK response,
270
if dlg.ShowModal() == wx.ID_OK:
271
# This returns a Python list of files that were selected.
274
print ("Opening %s\n" % path)
277
fsock = open(path, 'r')
278
contents = fsock.read()
280
self.editor.SetText(contents)
281
self.editor.file = path # remember file we're editing
282
self.fileMenu.Enable(wx.ID_SAVE, False)
283
self.fileMenu.Enable(wx.ID_SAVEAS, True)
285
dialog = wx.MessageDialog(self, "Error opening file %s" % path,
286
"Error opening file", wx.OK)
290
# Destroy the dialog. Don't do this until you are done with it!
291
# BAD things can happen otherwise!
294
def OnFileMenuSave(self, event):
296
if self.editor.file == None:
297
self.OnFileMenuSaveAs(event)
299
self.__SaveFile(self.editor.file)
300
self.fileMenu.Enable(wx.ID_SAVE, False)
302
def OnFileMenuSaveAs(self, event):
305
# Create the dialog. In this case the current directory is forced as the starting
306
# directory for the dialog, and no default file name is forced. This can easilly
307
# be changed in your program. This is an 'save' dialog.
309
# Unlike the 'open dialog' example found elsewhere, this example does NOT
310
# force the current working directory to change if the user chooses a different
311
# directory than the one initially set.
313
self, message="Save file as ...", defaultDir="",
314
defaultFile="", wildcard=self.wildcard, style=wx.SAVE
317
# This sets the default filter that the user will initially see. Otherwise,
318
# the first filter in the list will be used by default.
319
dlg.SetFilterIndex(2)
321
# Show the dialog and retrieve the user response. If it is the OK response,
323
if dlg.ShowModal() == wx.ID_OK:
325
self.editor.file = path # remember file we're editing has changed
326
self.__SaveFile(path)
327
self.fileMenu.Enable(wx.ID_SAVE, False)
329
# Destroy the dialog. Don't do this until you are done with it!
330
# BAD things can happen otherwise!
333
def OnFileMenuClose(self, event):
334
self.OnFileMenuNew(event) # this will do for now
336
def OnFileMenuQuit(self, event):
337
print "This should first check that changes have been saved..."
340
def OnEditMenuUndo(self, event):
341
if self.editor.CanUndo():
343
print "Undo last action"
345
def OnEditMenuRedo(self, event):
346
if self.editor.CanRedo():
348
print "Redo last action"
350
def OnEditMenuCut(self, event):
351
self.clip = self.editor.GetSelectedText()
352
self.editor.ReplaceSelection('')
353
print "Cut selected text: " + self.clip
355
def OnEditMenuCopy(self, event):
356
self.clip = self.editor.GetSelectedText()
357
print "Stored selected text into clip: " + self.clip
359
def OnEditMenuPaste(self, event):
360
self.editor.ReplaceSelection(self.clip)
361
print "Replace selection with: " + self.clip
363
def OnEditMenuSelectAll(self, event):
364
self.editor.SelectAll()
366
def OnViewMenuWordWrap(self, event):
367
self.editor.ToggleWordWrapMode()
369
def OnViewMenuLargerText(self, event):
370
self.editor.IncreaseTextSize()
372
def OnViewMenuSmallerText(self, event):
373
self.editor.DecreaseTextSize()
375
def OnViewMenuShowToolbar(self, event):
380
self.SendSizeEvent() # cause Frame to reevaluate childrens' positions
382
def OnPresageMenuPromptMe(self, event):
383
self.editor.ShowPrediction()
385
def OnPresageMenuToggleLearnMode(self, event):
386
self.editor.prsg.config(self.editor.learn_mode_config_var, str(event.Checked()))
387
print "Learn mode switched to " + str(event.Checked())
389
def OnPresageMenuToggleFunctionMode(self, event):
390
self.editor.function_keys_enabled = event.Checked()
392
def OnPresageMenuToggleAutopunctuationMode(self, event):
393
self.editor.autopunctuation = event.Checked()
395
def OnHelpMenuContents(self, event):
396
message = "Sorry, help not written yet."
397
dialog = wx.MessageDialog(self, message, "pyprompter help", wx.OK)
401
def OnHelpMenuAbout(self, event):
402
self.__ShowAboutDialogBox()
404
def __ShowAboutDialogBox(self):
406
version = self.version
407
copyright = '(C) 2008 Matteo Vescovi'
408
description = '''This program is intended as a demonstration of Presage ONLY.
409
The Presage project aims to provide an intelligent predictive text entry platform. Its intent is NOT to provide a predictive text entry user interface.
411
Think of Presage as the predictive backend that sits behind a shiny user interface and does all the predictive heavy lifting.
413
website = 'http://presage.sourceforge.net/'
414
devs = ["Matteo Vescovi"]
415
license = '''This program is free software; you can redistribute it and/or modify
416
it under the terms of the GNU General Public License as published by
417
the Free Software Foundation; either version 2 of the License, or
418
(at your option) any later version.
420
This program is distributed in the hope that it will be useful,
421
but WITHOUT ANY WARRANTY; without even the implied warranty of
422
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
423
GNU General Public License for more details.
425
You should have received a copy of the GNU General Public License along
426
with this program; if not, write to the Free Software Foundation, Inc.,
427
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
429
# AboutBox and AboutDialogInfo were introduced in wxPython 2.7.1.1
430
if wx.VERSION > (2, 7, 1, 1):
431
# build about dialog information
432
info = wx.AboutDialogInfo()
434
info.SetVersion(version)
435
info.SetCopyright(copyright)
436
info.SetDescription(description)
437
info.SetWebSite(website)
438
info.SetDevelopers(devs)
439
info.SetDocWriters(devs)
440
info.SetArtists(devs)
441
#info.SetTranslators(devs)
442
info.SetLicense(license)
445
# show about dialog box
449
message = name + ' ' + version + '\n' \
453
+ description + '\n' \
456
dialog = wx.MessageDialog(self, message, "About pyprompter", wx.OK)
460
def __SaveFile(self, path):
462
fp = open(path, 'w') # Create file anew
463
fp.write(self.editor.GetText())
466
dialog = wx.MessageDialog(self, "Error saving file %s" % path,
467
"Error saving file", wx.OK)
474
class PrompterEditor(wx.stc.StyledTextCtrl):
475
def __init__(self, parent, config, suggestions):
476
wx.stc.StyledTextCtrl.__init__(self, parent)
478
self.parent = parent # remember parent access frame menus
479
self.file = None # remember what file to save to
480
self.append_whitespace_on_completion = True
481
self.autopunctuation = True
482
self.autopunctuation_whitespace = ' '
483
self.autopunctuation_chars = ".,;:'?!$%&"
484
self.function_keys_enabled = True
485
self.learn_mode_config_var = "Presage.Predictors.SmoothedNgramPredictor.LEARN"
487
self.Bind(wx.EVT_CHAR, self.OnChar)
488
self.Bind(wx.stc.EVT_STC_USERLISTSELECTION, self.OnUserListSelection)
489
self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified)
491
class PrompterPresageCallback(presage.PresageCallback):
492
def __init__(self, edtr):
493
presage.PresageCallback.__init__(self)
496
def get_past_stream(self):
497
result = self.editor.GetTextRange(0,
498
self.editor.GetCurrentPos())
501
def get_future_stream(self):
502
result = self.editor.GetTextRange(self.editor.GetCurrentPos(),
503
self.editor.GetTextLength())
506
callback = PrompterPresageCallback(self).__disown__()
509
self.prsg = presage.Presage(callback, config)
511
self.prsg = presage.Presage(callback)
514
self.prsg.config('Presage.Selector.SUGGESTIONS', suggestions)
516
self.SetCodePage(wx.stc.STC_CP_UTF8) # set unicode codepage
517
self.SetWrapMode(wx.stc.STC_WRAP_WORD)
518
self.AutoCompSetAutoHide(False)
520
self.AutoCompSetSeparator(44)
521
#self.AutoCompSetIgnoreCase(1)
522
self.AutoCompSetMaxHeight(int(self.prsg.config("Presage.Selector.SUGGESTIONS")))
525
self.StyleSetSize(wx.stc.STC_STYLE_DEFAULT, self.text_size)
529
self.SetMarginWidth(i, 0)
531
# delaying the __ShowPrediction until after the parent frame and
533
wx.CallAfter(self.__ShowPrediction)
534
wx.CallAfter(self.SetSTCFocus, 1)
536
def OnChar(self, event):
537
print "------------ OnChar() handler"
539
keycode = event.GetKeyCode()
541
if self.__FunctionKey(keycode):
542
self.__HandleFunctionKey(keycode)
544
key = unichr(keycode)
546
self.parent.fileMenu.Enable(wx.ID_SAVE, True)
547
self.parent.fileMenu.Enable(wx.ID_SAVEAS, True)
549
if self.__AutoPunctuation(key):
550
# autopunctuation takes care of adding text and updating
551
# prsg, nothing to do here.
556
self.__ShowPrediction()
558
def ShowPrediction(self, string = ''):
559
self.__ShowPrediction(string)
561
def __ShowPrediction(self, string = ''):
562
print "------------ __ShowPrediction()"
564
prefix = self.prsg.prefix()
565
context = self.prsg.context()
566
context_change = self.prsg.context_change()
568
self.prediction = self.prsg.predict()
570
if self.function_keys_enabled:
571
self.prediction = self.__PrependFunctionLabel(self.prediction)
572
self.suggestions = self.separator.join(self.prediction);
574
except presage.PresageException, ex:
575
print 'Caught exception %s' % (ex)
576
print ' code: %d' % (ex.code())
577
print ' what: %s' % (ex.what())
579
if ex.code() == presage.PRESAGE_SQLITE_EXECUTE_SQL_ERROR:
580
# switch off learning and update menu checkbox
581
self.prsg.config(self.learn_mode_config_var, "false")
582
self.parent.presageMenu.Check(self.parent.ID_TOGGLE_LEARN_MODE, False)
585
dialog = wx.MessageDialog(self.parent, "The adaptive text learning component of the presage predictive text entry engine has detected an error. Learning has been switched off.", "Learning error in presage predictive text engine", wx.OK)
589
print "String: " + string
590
print "Prefix: " + prefix
591
print "Prefix len: " + str(len(prefix))
592
print "Context: " + context
593
print "Context change: " + str(context_change)
594
print "Prediction: " + self.suggestions
596
if self.AutoCompActive():
597
self.AutoCompCancel()
599
# AutoCompShow() does not generate an event when autocompletion is
600
# successful, hence it is not possible to notify presage that
601
# the current token was completed.
602
#self.AutoCompShow(len(prefix), suggestions)
604
# UserListShow() throws an EVT_STC_USERLISTSELECTION event that we
605
# can handle to notify presage that the token was automatically
607
self.UserListShow(1, self.suggestions)
609
def __AutoPunctuation(self, char):
610
if self.autopunctuation:
611
# autopunctuation is enabled
612
if char in self.autopunctuation_chars:
613
# char is an autopunctuation character
614
curr_pos = self.GetCurrentPos()
616
# previous character exists
617
prev_pos = curr_pos - 1
618
prev_char = chr(self.GetCharAt(prev_pos))
619
if prev_char in self.autopunctuation_whitespace:
620
# previous character is an autopunctuation whitespace
622
# swap whitespace and current char
623
self.SetSelection(prev_pos, curr_pos)
624
self.ReplaceSelection(char + ' ')
630
def __FunctionKey(self, keycode):
632
if self.function_keys_enabled:
633
self.function_keys = [wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6,
634
wx.WXK_F7, wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12]
635
if keycode in self.function_keys:
639
def __HandleFunctionKey(self, key):
640
print "Got function key " + str(key)
643
idx = self.function_keys.index(key)
644
print self.prediction[idx]
645
if self.AutoCompActive():
646
self.AutoCompCancel()
648
self.UserListShow(1, self.suggestions)
649
self.AutoCompSelect(self.prediction[idx])
650
self.AutoCompComplete()
652
print 'Key not in prediction completion list'
654
def __PrependFunctionLabel(self, prediction):
655
return ['F' + str(i + 1) + ' ' + prediction[i] for i in range(len(prediction))]
657
def __RemoveFunctionLabel(self, completion):
658
idx = completion.find(' ')
660
completion = completion[idx+1:]
663
def OnUserListSelection(self, event):
664
completion = unicode(event.GetText())
665
if self.function_keys_enabled:
666
completion = self.__RemoveFunctionLabel(completion)
667
prefix_length = len(unicode(self.prsg.prefix()))
669
print "----------- OnUserListSelection() handler"
670
print "Completion: " + completion
671
print "Prefix length: " + str(prefix_length)
672
print "To be added: " + completion[prefix_length:]
674
# no need to call complete, using callbacks
675
#self.prsg.complete(completion.encode('utf-8'))
676
self.AddText(completion[prefix_length:])
678
if self.append_whitespace_on_completion:
680
# no need to update, using callbacks
681
#self.prsg.update(' ')
683
# schedule showing of prediction after current and pending events
684
# are dealt with (thanks to Robin Dunn for pointing this out)
685
wx.CallAfter(self.__ShowPrediction)
687
def OnModified(self, event):
688
# grey out or enable menu items
689
self.parent.fileMenu.Enable(wx.ID_SAVE, True)
690
self.parent.fileMenu.Enable(wx.ID_SAVEAS, True)
693
self.parent.editMenu.Enable(wx.ID_UNDO, True)
695
self.parent.editMenu.Enable(wx.ID_UNDO, False)
698
self.parent.editMenu.Enable(wx.ID_REDO, True)
700
self.parent.editMenu.Enable(wx.ID_REDO, False)
702
def ToggleWordWrapMode(self):
703
if self.parent.word_wrap.IsChecked():
704
self.SetWrapMode(wx.stc.STC_WRAP_WORD)
706
self.SetWrapMode(wx.stc.STC_WRAP_NONE)
708
def IncreaseTextSize(self):
710
self.StyleSetSize(wx.stc.STC_STYLE_DEFAULT, self.text_size)
712
def DecreaseTextSize(self):
713
if self.text_size > 1:
715
self.StyleSetSize(wx.stc.STC_STYLE_DEFAULT, self.text_size)