comparison orpg/tools/predTextCtrl.py @ 135:dcf4fbe09b70 beta

Traipse Beta 'OpenRPG' {091010-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Beta) Added Bookmarks Fix to Remote Admin Commands Minor fix to text based Server Fix to Pretty Print, from Core Fix to Splitter Nodes not being created Fix to massive amounts of images loading, from Core Added 'boot' command to remote admin Added confirmation window for sent nodes Minor changes to allow for portability to an OpenSUSE linux OS Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Zoom Mouse plugin added Images added to Plugin UI Switching to Element Tree Map efficiency, from FlexiRPG Added Status Bar to Update Manager default_manifest.xml renamed to default_upmana.xml Cleaner clode for saved repositories New TrueDebug Class in orpg_log (See documentation for usage) Mercurial's hgweb folder is ported to upmana **Pretty important update that can help remove thousands of dead children from your gametree. **Children, <forms />, <group_atts />, <horizontal />, <cols />, <rows />, <height />, etc... are all tags now. Check your gametree and look for dead children!! **New Gamtree Recusion method, mapping, and context sensitivity. !!Alpha - Watch out for infinite loops!!
author sirebral
date Tue, 10 Nov 2009 14:11:28 -0600
parents 118fbe111922
children 9babc183fa47
comparison
equal deleted inserted replaced
101:394ebb3b6a0f 135:dcf4fbe09b70
31 ## Module Loading 31 ## Module Loading
32 ## 32 ##
33 33
34 import string 34 import string
35 from orpg.orpg_windows import * 35 from orpg.orpg_windows import *
36 import wx #wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
36 from wx.lib.expando import ExpandoTextCtrl 37 from wx.lib.expando import ExpandoTextCtrl
37 from orpg.tools.orpg_log import logger 38 from orpg.tools.orpg_log import logger, debug
38 39
39 # This line added to test CVS commit 40 # This line added to test CVS commit
40 41
41 ## 42 ##
42 ## Class Definitions 43 ## Class Definitions
120 # 121 #
121 # Returns: None 122 # Returns: None
122 # 123 #
123 # Purpose: Sets or increments the priority of a word, adding the word if necessary 124 # Purpose: Sets or increments the priority of a word, adding the word if necessary
124 def setWord(self,wordText,priority = 1,sumFlag = 0): 125 def setWord(self,wordText,priority = 1,sumFlag = 0):
125
126 cur = self.rootNode # start from the root 126 cur = self.rootNode # start from the root
127
128 for ch in wordText: # for each character in the word 127 for ch in wordText: # for each character in the word
129 if cur.children.has_key(ch): # check to see if we've found a new word 128 if cur.children.has_key(ch): # check to see if we've found a new word
130
131 cur = cur.children[ch] # if we haven't found a new word, move to the next letter and try again 129 cur = cur.children[ch] # if we haven't found a new word, move to the next letter and try again
132
133 else: # in this clause, we're creating a new branch, as the word is new 130 else: # in this clause, we're creating a new branch, as the word is new
134 newLetter = Letter(ch,cur) # create a new class Letter using this ascii code and the current letter as a parent 131 newLetter = Letter(ch,cur) # create a new class Letter using this ascii code and the current letter as a parent
135
136 if cur is self.rootNode: # special case: Others expect the top level letters to point to None, not self.rootNode 132 if cur is self.rootNode: # special case: Others expect the top level letters to point to None, not self.rootNode
137 newLetter.parentNode = None 133 newLetter.parentNode = None
138
139 cur.children[ch] = newLetter # add the new letter to the list of children of the current letter 134 cur.children[ch] = newLetter # add the new letter to the list of children of the current letter
140 cur = newLetter # make the new letter the current one for the next time through 135 cur = newLetter # make the new letter the current one for the next time through
141 136
142 # at this point, cur is pointing to the last letter of either a new or existing word. 137 # at this point, cur is pointing to the last letter of either a new or existing word.
143 138 if sumFlag: cur.priority += priority # if the caller wants to add to the existing (0 if new)
144 if sumFlag: # if the caller wants to add to the existing (0 if new) 139 else: cur.priority = priority # else, the set the priority directly
145 cur.priority += priority
146 else: # else, the set the priority directly
147 cur.priority = priority
148
149 self.updateMostCommon(cur) # this will run back through the tree to fix up the mostCommon members 140 self.updateMostCommon(cur) # this will run back through the tree to fix up the mostCommon members
150
151 141
152 # addWord subroutine. 142 # addWord subroutine.
153 # 143 #
154 # self : instance of self 144 # self : instance of self
155 # wordText : string representing word to add 145 # wordText : string representing word to add
158 # 148 #
159 # Purpose: Convenience method that wraps setWord. Used to add words known not to exist. 149 # Purpose: Convenience method that wraps setWord. Used to add words known not to exist.
160 def addWord(self,wordText): 150 def addWord(self,wordText):
161 self.setWord(wordText,priority = 1) 151 self.setWord(wordText,priority = 1)
162 152
163
164 # incWord subroutine. 153 # incWord subroutine.
165 # 154 #
166 # self : instance of self 155 # self : instance of self
167 # wordText : string representing word to add 156 # wordText : string representing word to add
168 # 157 #
169 # Returns: None 158 # Returns: None
170 # 159 #
171 # Purpose: Convenience method that wraps setWord. Used to increment the priority of existing words and add new words. 160 # Purpose: Convenience method that wraps setWord. Used to increment the priority of existing words and add new words.
172 # Note: Generally, this method can be used instead of addWord. 161 # Note: Generally, this method can be used instead of addWord.
162
173 def incWord(self,wordText): 163 def incWord(self,wordText):
174 self.setWord(wordText,priority = 1, sumFlag = 1) 164 self.setWord(wordText,priority = 1, sumFlag = 1)
175 165
176
177 # setWordPriority subroutine. 166 # setWordPriority subroutine.
178 # 167 #
179 # self : instance of self 168 # self : instance of self
180 # wordText : string representing word to add 169 # wordText : string representing word to add
181 # priority: int that is the new priority 170 # priority: int that is the new priority
182 # 171 #
183 # Returns: None 172 # Returns: None
184 # 173 #
185 # Purpose: Convenience method that wraps setWord. Sets existing words to priority or adds new words with priority = priority 174 # Purpose: Convenience method that wraps setWord. Sets existing words to priority or adds new words with priority = priority
175
186 def setWordPriority(self,wordText,priority): 176 def setWordPriority(self,wordText,priority):
187 self.setWord(wordText,priority = priority) 177 self.setWord(wordText,priority = priority)
188 178
189 179
190 # findWordNode subroutine. 180 # findWordNode subroutine.
194 # 184 #
195 # Returns: class Letter or None if word isn't found. 185 # Returns: class Letter or None if word isn't found.
196 # 186 #
197 # Purpose: Given a word, it returns the class Letter node that corresponds to the word. Used mostly in prep for a call to 187 # Purpose: Given a word, it returns the class Letter node that corresponds to the word. Used mostly in prep for a call to
198 # getPrediction() 188 # getPrediction()
189
199 def findWordNode(self,wordText): #returns class Letter that represents the last letter in the word 190 def findWordNode(self,wordText): #returns class Letter that represents the last letter in the word
200
201 cur = self.rootNode # start at the root 191 cur = self.rootNode # start at the root
202
203 for ch in wordText: # move through each letter in the word 192 for ch in wordText: # move through each letter in the word
204 if cur.children.has_key(ch): # if the next letter exists, make cur equal that letter and loop 193 if cur.children.has_key(ch): # if the next letter exists, make cur equal that letter and loop
205 cur = cur.children[ch] 194 cur = cur.children[ch]
206 else: 195 else: return None # return None if letter not found
207 return None # return None if letter not found
208
209 return cur # return cur, as this points to the last letter if we got this far 196 return cur # return cur, as this points to the last letter if we got this far
210 197
211 198
212 # findWordPriority subroutine. 199 # findWordPriority subroutine.
213 # 200 #
215 # wordText : string representing word to add 202 # wordText : string representing word to add
216 # 203 #
217 # Returns: Int representing the word's priority or 0 if not found. 204 # Returns: Int representing the word's priority or 0 if not found.
218 # 205 #
219 # Purpose: Returns the priority of the given word 206 # Purpose: Returns the priority of the given word
207
220 def findWordPriority(self,wordText): 208 def findWordPriority(self,wordText):
221 209
222 cur = self.findWordNode(wordText) # find the class Letter node that corresponds to this word 210 cur = self.findWordNode(wordText) # find the class Letter node that corresponds to this word
223 if cur: 211 if cur: return cur.priority # if it was found, return it's priority
224 return cur.priority # if it was found, return it's priority 212 else: return 0 # else, return 0, meaning word not found
225 else:
226 return 0 # else, return 0, meaning word not found
227
228 213
229 def printTree(self, current=None): 214 def printTree(self, current=None):
230 letters = [] 215 letters = []
231 if current is None: 216 if current is None:
232 current = self.rootNode 217 current = self.rootNode
233
234 for l, letter in current.children.iteritems(): 218 for l, letter in current.children.iteritems():
235 letters.append(str(letter)) 219 letters.append(str(letter))
236 if letter.children != {}: 220 if letter.children != {}:
237 m = self.printTree(letter) 221 m = self.printTree(letter)
238 letters.append(m) 222 letters.append(m)
239
240 return letters 223 return letters
241
242
243 224
244 # getPrediction subroutine. 225 # getPrediction subroutine.
245 # 226 #
246 # self : instance of self 227 # self : instance of self
247 # k : ASCII char that was typed 228 # k : ASCII char that was typed
338 else: 319 else:
339 ExpandoTextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name) 320 ExpandoTextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name)
340 321
341 self.tree = LetterTree # Instantiate a new LetterTree. 322 self.tree = LetterTree # Instantiate a new LetterTree.
342 # TODO: make name of word file an argument. 323 # TODO: make name of word file an argument.
343 324 self.parent = parent # Save parent for later use in passing KeyEvents
344 325 self.cur = self.tree.rootNode # self.cur is a short cut placeholder for typing consecutive chars
345 326 # It may be vestigal
346 327 self.keyHook = keyHook # Save the keyHook passed in
347 self.parent = parent # Save parent for later use in passing KeyEvents 328 ExpandoTextCtrl._wrapLine = self._wrapLine
348 329
349 self.cur = self.tree.rootNode # self.cur is a short cut placeholder for typing consecutive chars 330
350 # It may be vestigal 331 def _wrapLine(self, line, dc, width):
351 332 # Estimate where the control will wrap the lines and
352 self.keyHook = keyHook # Save the keyHook passed in 333 # return the count of extra lines needed.
353 334 # Re writes ExpandoTextCtrl _wrapLine function
335 pte = dc.GetPartialTextExtents(line)
336 width -= wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
337 idx = 0
338 start = 0
339 count = 0
340 spc = -1
341 while idx < len(pte):
342 if line[idx] == ' ': debug((line)); spc = idx
343 if pte[idx] - start > width:
344 # we've reached the max width, add a new line
345 count += 1
346 # did we see a space? if so restart the count at that pos
347 if spc != -1:
348 idx = spc + 1
349 spc = -1
350 start = pte[idx]
351 else:
352 idx += 1
353 return count
354 354
355 # findWord subroutine. 355 # findWord subroutine.
356 # 356 #
357 # self : instance of self 357 # self : instance of self
358 # insert: index of last char in st 358 # insert: index of last char in st
366 # Returns: String that is the word or "" if none found. This generally doesn't 366 # Returns: String that is the word or "" if none found. This generally doesn't
367 # happen, as st usually ends in a letter, which will be returned. 367 # happen, as st usually ends in a letter, which will be returned.
368 # 368 #
369 # Purpose: This function is generally used to figure out the beginning of the 369 # Purpose: This function is generally used to figure out the beginning of the
370 # current word being typed, for later use in a LetterTree.getPrediction() 370 # current word being typed, for later use in a LetterTree.getPrediction()
371 def findWord(self,insert,st): 371 def findWord(self, insert, st):
372 372
373 # Good luck reading this one. Basically, I started out with an idea, and fiddled with the 373 # Good luck reading this one. Basically, I started out with an idea, and fiddled with the
374 # constants as best I could until it worked. It's not a piece of work of which I'm too 374 # constants as best I could until it worked. It's not a piece of work of which I'm too
375 # proud. Basically, it's intent is to check each character to the left until it finds one 375 # proud. Basically, it's intent is to check each character to the left until it finds one
376 # that isn't a letter. If it finds such a character, it stops and returns the slice 376 # that isn't a letter. If it finds such a character, it stops and returns the slice
402 if(self.keyHook): 402 if(self.keyHook):
403 if self.keyHook(event) == 1: # if the passed in keyHook routine returns a one, it wants no predictive behavior 403 if self.keyHook(event) == 1: # if the passed in keyHook routine returns a one, it wants no predictive behavior
404 self.parent.OnChar(event) 404 self.parent.OnChar(event)
405 return 405 return
406 406
407
408
409 # This bit converts the GetKeyCode() return (int) to a char if it's in a certain range 407 # This bit converts the GetKeyCode() return (int) to a char if it's in a certain range
410 asciiKey = "" 408 asciiKey = ""
411 if (event.GetKeyCode() < 256) and (event.GetKeyCode() > 19): 409 if (event.GetKeyCode() < 256) and (event.GetKeyCode() > 19):
412 asciiKey = chr(event.GetKeyCode()) 410 asciiKey = chr(event.GetKeyCode())
413 411
414 412 if asciiKey == "": # If we didn't convert it to a char, then process based on the int GetKeyCodes
415 if asciiKey == "": # If we didn't convert it to a char, then process based on the int GetKeyCodes 413 if event.GetKeyCode() == wx.WXK_TAB: # We want to hook tabs to allow the user to signify acceptance of a
416 414 # predicted word.
417 if event.GetKeyCode() == wx.WXK_TAB: # We want to hook tabs to allow the user to signify acceptance of a
418 # predicted word.
419 # Handle Tab key 415 # Handle Tab key
420 416 fromPos = toPos = 0 # get the current selection range
421 fromPos = toPos = 0 # get the current selection range
422 (fromPos,toPos) = self.GetSelection() 417 (fromPos,toPos) = self.GetSelection()
423 418 if (toPos - fromPos) == 0: # if there is no selection, pass tab on
424 if (toPos - fromPos) == 0: # if there is no selection, pass tab on
425 self.parent.OnChar(event) 419 self.parent.OnChar(event)
426 return 420 return
427
428 else: # This means at least one char is selected 421 else: # This means at least one char is selected
429
430 self.SetInsertionPoint(toPos) # move the insertion point to the end of the selection 422 self.SetInsertionPoint(toPos) # move the insertion point to the end of the selection
431 self.SetSelection(toPos,toPos) # and set the selection to no chars 423 self.SetSelection(toPos,toPos) # and set the selection to no chars
432 # The prediction, if any, had been inserted into the text earlier, so 424 # The prediction, if any, had been inserted into the text earlier, so
433 # moving the insertion point to the spot directly afterwards is 425 # moving the insertion point to the spot directly afterwards is
434 # equivalent to acceptance. Without this, the next typed key would 426 # equivalent to acceptance. Without this, the next typed key would
439 logger.exception('Shift + Enter Not completed, 439, predtextCtrl', True) 431 logger.exception('Shift + Enter Not completed, 439, predtextCtrl', True)
440 st = self.GetValue() 432 st = self.GetValue()
441 st += '<br />' 433 st += '<br />'
442 return 434 return
443 435
444
445 elif event.GetKeyCode() == wx.WXK_RETURN: # We want to hook returns, so that we can update the word list 436 elif event.GetKeyCode() == wx.WXK_RETURN: # We want to hook returns, so that we can update the word list
446
447 st = self.GetValue() # Grab the text from the control 437 st = self.GetValue() # Grab the text from the control
448 newSt = "" # Init a buffer 438 newSt = "" # Init a buffer
449
450 # This block of code, by popular demand, changes the behavior of the control to ignore any prediction that 439 # This block of code, by popular demand, changes the behavior of the control to ignore any prediction that
451 # hasn't been "accepted" when the enter key is struck. 440 # hasn't been "accepted" when the enter key is struck.
452 (startSel,endSel) = self.GetSelection() # get the curren selection 441 (startSel,endSel) = self.GetSelection() # get the curren selection
453 442
454 # 443 #
473 for ch in st: 462 for ch in st:
474 if ch not in string.letters: 463 if ch not in string.letters:
475 newSt += " " 464 newSt += " "
476 else: 465 else:
477 newSt += ch 466 newSt += ch
478
479 # Now that we've got a string of just letter sequences (words) and spaces 467 # Now that we've got a string of just letter sequences (words) and spaces
480 # split it and to a LetterTree.incWord on the lowercase version of it. 468 # split it and to a LetterTree.incWord on the lowercase version of it.
481 # Reminder: incWord will increment the priority of existing words and add 469 # Reminder: incWord will increment the priority of existing words and add
482 # new ones 470 # new ones
483 for aWord in string.split(newSt): 471 for aWord in string.split(newSt):
500 elif event.GetKeyCode() == wx.WXK_LEFT: 488 elif event.GetKeyCode() == wx.WXK_LEFT:
501 (startSel,endSel) = self.GetSelection() 489 (startSel,endSel) = self.GetSelection()
502 self.SetInsertionPoint(startSel) 490 self.SetInsertionPoint(startSel)
503 self.parent.OnChar(event) 491 self.parent.OnChar(event)
504 return 492 return
505
506
507 else: 493 else:
508 # Handle any other non-ascii events by calling parent's OnChar() 494 # Handle any other non-ascii events by calling parent's OnChar()
509 self.parent.OnChar(event) #Call super.OnChar to get default behavior 495 self.parent.OnChar(event) #Call super.OnChar to get default behavior
510 return 496 return
511
512
513 elif asciiKey in string.letters: 497 elif asciiKey in string.letters:
514 # This is the real meat and potatoes of predTextCtrl. This is where most of the 498 # This is the real meat and potatoes of predTextCtrl. This is where most of the
515 # wx.TextCtrl logic is changed. 499 # wx.TextCtrl logic is changed.
516
517 (startSel,endSel) = self.GetSelection() # get the curren selection 500 (startSel,endSel) = self.GetSelection() # get the curren selection
518 st = self.GetValue() # and the text in the control 501 st = self.GetValue() # and the text in the control
519 front = st[:startSel] # Slice off the text to the front of where we are 502 front = st[:startSel] # Slice off the text to the front of where we are
520 back = st[endSel:] # Slice off the text to the end from where we are 503 back = st[endSel:] # Slice off the text to the end from where we are
521
522 st = front + asciiKey + back # This expression creates a string that will insert the 504 st = front + asciiKey + back # This expression creates a string that will insert the
523 # typed character (asciiKey is generated at the 505 # typed character (asciiKey is generated at the
524 # beginning of OnChar()) into the text. If there 506 # beginning of OnChar()) into the text. If there
525 # was text selected, that text will not be part 507 # was text selected, that text will not be part
526 # of the new string, due to the way front and back 508 # of the new string, due to the way front and back
527 # were sliced. 509 # were sliced.
528 510
529 insert = startSel + 1 # creates an int that denotes where the new InsertionPoint 511 insert = startSel + 1 # creates an int that denotes where the new InsertionPoint
530 # should be. 512 # should be.
531
532 curWord = "" # Assume there's a problem with finding the curWord 513 curWord = "" # Assume there's a problem with finding the curWord
533
534 if (len(back) == 0) or (back[0] not in string.letters): # We should only insert a prediction if we are typing 514 if (len(back) == 0) or (back[0] not in string.letters): # We should only insert a prediction if we are typing
535 # at the end of a word, not in the middle. There are 515 # at the end of a word, not in the middle. There are
536 # three cases: we are typing at the end of the string or 516 # three cases: we are typing at the end of the string or
537 # we are typing in the middle of the string and the next 517 # we are typing in the middle of the string and the next
538 # char is NOT a letter or we are typing in the middle of the 518 # char is NOT a letter or we are typing in the middle of the
609 # s/he must strike the tab key at this point. Of course, one could 589 # s/he must strike the tab key at this point. Of course, one could
610 # just use the right arrow key as well, but that's not as easy to 590 # just use the right arrow key as well, but that's not as easy to
611 # reach. 591 # reach.
612 592
613 return # Done! Do NOT pass the event on at this point, because it's all done. 593 return # Done! Do NOT pass the event on at this point, because it's all done.
614
615
616 else: 594 else:
617 # Handle every other non-letter ascii (e.g. semicolon) by passing the event on. 595 # Handle every other non-letter ascii (e.g. semicolon) by passing the event on.
618 self.parent.OnChar(event) #Call super.OnChar to get default behavior 596 self.parent.OnChar(event) #Call super.OnChar to get default behavior
619 return 597 return
620
621 # End of class predTextCtrl! 598 # End of class predTextCtrl!