Package Gnumed :: Package wxpython :: Module gmSoapSTCWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmSoapSTCWidgets

   1  # -*- coding: utf-8 -*- 
   2  __doc__ = """GNUmed StyledTextCtrl subclass for SOAP editing. 
   3   
   4  based on: 11/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)""" 
   5  #================================================================ 
   6  __author__  = "K. Hilbert <Karsten.Hilbert@gmx.net>" 
   7  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
   8   
   9  import logging 
  10  import sys 
  11   
  12   
  13  import wx 
  14  import wx.stc 
  15   
  16   
  17  if __name__ == '__main__': 
  18          sys.path.insert(0, '../../') 
  19  from Gnumed.business import gmSoapDefs 
  20  from Gnumed.wxpython import gmKeywordExpansionWidgets 
  21  from Gnumed.wxpython.gmTextCtrl import cUnicodeInsertion_TextCtrlMixin 
  22   
  23   
  24  _log = logging.getLogger('gm.stc') 
  25   
  26  #================================================================ 
27 -class cWxTextCtrlCompatibility_StcMixin():
28
29 - def __init__(self, *args, **kwargs):
30 if not isinstance(self, wx.stc.StyledTextCtrl): 31 raise TypeError('[%s]: can only be applied to wx.stc.StyledTextCtrl, not [%s]' % (cWxTextCtrlCompatibility_StcMixin, self.__class__.__name__))
32 33 #-------------------------------------------------- 34 # wx.TextCtrl compatibility 35 #--------------------------------------------------
36 - def GetValue(self):
37 _log.debug('%s.GetValue() - %s', cWxTextCtrlCompatibility_StcMixin, self.__class__.__name__) 38 return self.GetText()
39 40 #--------------------------------------------------
41 - def SetValue(self, value):
42 _log.debug('%s.SetValue() - %s', cWxTextCtrlCompatibility_StcMixin, self.__class__.__name__) 43 return self.SetText(value)
44 45 #--------------------------------------------------
46 - def WriteText(self, value):
47 return self.InsertText(self.CurrentPos, value)
48 49 #--------------------------------------------------
50 - def GetLastPosition(self):
51 return self.Length
52 53 LastPosition = property(GetLastPosition, lambda x:x) 54 55 #--------------------------------------------------
56 - def GetNumberOfLines(self):
57 return self.LineCount
58 59 #--------------------------------------------------
60 - def GetLineText(self, line_no):
61 return self.GetLine(line_no)
62 63 #--------------------------------------------------
64 - def GetInsertionPoint(self):
65 return self.CurrentPos
66
67 - def SetInsertionPoint(self, position):
68 self.CurrentPos = position
69 70 InsertionPoint = property(GetInsertionPoint, SetInsertionPoint) 71 72 #--------------------------------------------------
73 - def ShowPosition(self, position):
74 #self.ScrollToLine(self.LineFromPosition(position)) 75 self.CurrentPos = position 76 self.EnsureCaretVisible()
77 78 #--------------------------------------------------
79 - def IsMultiLine(self):
80 return True
81 82 #--------------------------------------------------
83 - def PositionToXY(self, position):
84 try: 85 #return wx.stc.StyledTextCtrl.PositionToXY(position) # does not work 86 #return wx.TextAreaBase.PositionToXY(position) # does not work 87 return super(wx.TextAreaBase, self).PositionToXY(position) 88 except AttributeError: 89 # reimplement for wxPython 2.8, 90 # this is moot now, hwoever, since 2.8 returned an (x, y) tuple 91 return (True, self.GetColumn(position), self.LineFromPosition(position))
92 93 #--------------------------------------------------
94 - def Replace(self, start, end, replacement):
95 self.SetSelection(start, end) 96 self.ReplaceSelection(replacement) 97 wx.CallAfter(self.SetSelection, 0, 0)
98 99 #----------------------------------------------------------------------
100 -class cSoapSTC(cUnicodeInsertion_TextCtrlMixin, gmKeywordExpansionWidgets.cKeywordExpansion_TextCtrlMixin, cWxTextCtrlCompatibility_StcMixin, wx.stc.StyledTextCtrl):
101 102 _MARKER_ADM = 0 103 _MARKER_S = 1 104 _MARKER_O = 2 105 _MARKER_A = 3 106 _MARKER_P = 4 107 _MARKER_U = 5 108 _MARKER_LINE_BG_LIGHT_GREY = 31 109 110 _DEFINED_MARKERS_MASK = ( 111 _MARKER_ADM 112 | 113 _MARKER_S 114 | 115 _MARKER_O 116 | 117 _MARKER_A 118 | 119 _MARKER_P 120 | 121 _MARKER_U 122 | 123 _MARKER_LINE_BG_LIGHT_GREY 124 ) 125 126 _DEFINED_MARKER_NUMS = [ 127 _MARKER_ADM, 128 _MARKER_S, 129 _MARKER_O, 130 _MARKER_A, 131 _MARKER_P, 132 _MARKER_U, 133 _MARKER_LINE_BG_LIGHT_GREY 134 ] 135 _SOAP_MARKER_NUMS = [ 136 _MARKER_ADM, 137 _MARKER_S, 138 _MARKER_O, 139 _MARKER_A, 140 _MARKER_P, 141 _MARKER_U 142 ] 143 _SOAP2MARKER = { 144 None: _MARKER_ADM, 145 ' ': _MARKER_ADM, 146 '.': _MARKER_ADM, 147 's': _MARKER_S, 148 'o': _MARKER_O, 149 'a': _MARKER_A, 150 'p': _MARKER_P, 151 'u': _MARKER_U, 152 'S': _MARKER_S, 153 'O': _MARKER_O, 154 'A': _MARKER_A, 155 'P': _MARKER_P, 156 'U': _MARKER_U 157 } 158 _MARKER2SOAP = { 159 _MARKER_ADM: None, 160 _MARKER_S: 's', 161 _MARKER_O: 'o', 162 _MARKER_A: 'a', 163 _MARKER_P: 'p', 164 _MARKER_U: 'u' 165 } 166 _SOAPMARKER2BACKGROUND = { 167 _MARKER_ADM: False, 168 _MARKER_S: True, 169 _MARKER_O: False, 170 _MARKER_A: True, 171 _MARKER_P: False, 172 _MARKER_U: True 173 } 174
175 - def __init__(self, *args, **kwargs):
176 177 # normalize wxGlade output 178 if args[2] == '': 179 l_args = list(args) 180 l_args[2] = wx.DefaultPosition 181 args = tuple(l_args) 182 wx.stc.StyledTextCtrl.__init__(self, *args, **kwargs) 183 cWxTextCtrlCompatibility_StcMixin.__init__(self) 184 gmKeywordExpansionWidgets.cKeywordExpansion_TextCtrlMixin.__init__(self) 185 cUnicodeInsertion_TextCtrlMixin.__init__(self) 186 187 # wrapping and overflow 188 self.SetWrapMode(wx.stc.STC_WRAP_NONE) 189 # said to be problematic: 190 self.SetEdgeColumn(80) 191 self.SetEdgeColour('grey') 192 #self.SetEdgeMode(wx.stc.STC_EDGE_LINE) 193 self.SetEdgeMode(wx.stc.STC_EDGE_BACKGROUND) 194 195 # EOL style 196 self.SetEOLMode(wx.stc.STC_EOL_LF) 197 #self.SetViewEOL(1) # visual debugging 198 self.SetViewEOL(0) 199 200 # whitespace handling 201 #self.SetViewWhiteSpace(wx.stc.STC_WS_VISIBLEAFTERINDENT) # visual debugging 202 self.SetViewWhiteSpace(wx.stc.STC_WS_INVISIBLE) 203 #self.SetWhitespaceBackground(1, a_color) # 1 = override lexer 204 #self.SetWhitespaceForeground(1, a_color) # 1 = override lexer 205 206 # caret handling 207 #self.SetCaretLineBackground('light goldenrod yellow') 208 self.SetCaretLineBackground('khaki') 209 self.SetCaretLineVisible(1) 210 211 # margins 212 # left margin: 0 pixel widths 213 self.SetMarginLeft(0) 214 # margin 0: SOAP markers 215 self.SetMarginType(0, wx.stc.STC_MARGIN_SYMBOL) 216 self.SetMarginWidth(0, 16) 217 self.SetMarginMask(0, cSoapSTC._DEFINED_MARKERS_MASK) 218 # margin 1 and 2: additional 2-letter markers (not yet supported) 219 self.SetMarginType(1, wx.stc.STC_MARGIN_SYMBOL) 220 self.SetMarginMask(1, 0) 221 self.SetMarginWidth(1, 0) 222 self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL) 223 self.SetMarginMask(2, 0) 224 self.SetMarginWidth(2, 0) 225 226 # markers 227 # can only use ASCII so far, so must make sure translations are ASCII: 228 self.MarkerDefine(cSoapSTC._MARKER_ADM, wx.stc.STC_MARK_CHARACTER + ord('.'), 'blue', 'white') 229 self.MarkerDefine(cSoapSTC._MARKER_S, wx.stc.STC_MARK_CHARACTER + ord(gmSoapDefs.soap_cat2l10n['s']), 'blue', 'grey96') 230 self.MarkerDefine(cSoapSTC._MARKER_O, wx.stc.STC_MARK_CHARACTER + ord(gmSoapDefs.soap_cat2l10n['o']), 'blue', 'white') 231 self.MarkerDefine(cSoapSTC._MARKER_A, wx.stc.STC_MARK_CHARACTER + ord(gmSoapDefs.soap_cat2l10n['a']), 'blue', 'grey96') 232 self.MarkerDefine(cSoapSTC._MARKER_P, wx.stc.STC_MARK_CHARACTER + ord(gmSoapDefs.soap_cat2l10n['p']), 'blue', 'white') 233 self.MarkerDefine(cSoapSTC._MARKER_U, wx.stc.STC_MARK_CHARACTER + ord(gmSoapDefs.soap_cat2l10n['u']), 'blue', 'grey96') 234 self.MarkerDefine(cSoapSTC._MARKER_LINE_BG_LIGHT_GREY, wx.stc.STC_MARK_BACKGROUND, 'grey96', 'grey96') 235 236 # unset hotkeys we want to re-define 237 #self.CmdKeyClear('t', wx.stc.STC_SCMOD_CTRL) # does not seem to work 238 self.__changing_SOAP_cat = False 239 self.__markers_of_prev_line = None 240 self.__ensure_has_all_soap_types = False 241 242 # we do our own popup menu 243 self.UsePopUp(0) 244 self.__build_context_menu() 245 246 # always keep one line of each of .SOAP around 247 self.SetText_from_SOAP() 248 249 self.__register_events() 250 251 # text expansion mixin 252 self.enable_keyword_expansions()
253 254 #------------------------------------------------------- 255 # SOAP-enhanced text setting 256 #-------------------------------------------------------
257 - def SetText(self, *args, **kwargs):
258 _log.debug('%s.SetText()', self.__class__.__name__) 259 wx.stc.StyledTextCtrl.SetText(self, *args, **kwargs)
260
261 - def AddText(self, *args, **kwargs):
262 _log.debug('%s.AddText()', self.__class__.__name__) 263 wx.stc.StyledTextCtrl.AddText(self, *args, **kwargs)
264
265 - def AddStyledText(self, *args, **kwargs):
266 _log.debug('%s.AddStyledText()', self.__class__.__name__) 267 wx.stc.StyledTextCtrl.AddStyledText(self, *args, **kwargs)
268
269 - def InsertText(self, *args, **kwargs):
270 _log.debug('%s.InsertText()', self.__class__.__name__) 271 wx.stc.StyledTextCtrl.InsertText(self, *args, **kwargs)
272 273 #-------------------------------------------------------
274 - def ReplaceSelection(self, text):
275 sel_start, sel_end = self.GetSelection() 276 start_line = self.LineFromPosition(sel_start) 277 end_line = start_line + text.count('\n') 278 start_line_soap_cat = self.MarkerGet(start_line) 279 #_log.debug(u'replacing @ pos %s-%s with %s lines (line %s to line %s)', sel_start, sel_end, text.count(u'\n'), start_line, end_line) 280 wx.stc.StyledTextCtrl.ReplaceSelection(self, text) 281 if start_line != end_line: 282 for target_line in range(start_line, end_line): 283 self.MarkerDelete(target_line, -1) 284 self.__set_markers_of_line(target_line, start_line_soap_cat)
285 286 #-------------------------------------------------------
287 - def ReplaceTarget(self, *args, **kwargs):
288 _log.debug('%s.ReplaceTarget()', self.__class__.__name__) 289 wx.stc.StyledTextCtrl.ReplaceTarget(self, *args, **kwargs)
290
291 - def ReplaceTargetRE(self, *args, **kwargs):
292 _log.debug('%s.ReplaceTargetRE()', self.__class__.__name__) 293 wx.stc.StyledTextCtrl.ReplaceTargetRE(self, *args, **kwargs)
294 295 #------------------------------------------------------- 296 # external API 297 #-------------------------------------------------------
298 - def SetText_from_SOAP(self, soap=None, sort_order=None):
299 # defaults 300 if soap is None: 301 #soap = {None: [u'']} # 'soap' will be added below by normalization 302 soap = {} 303 if sort_order is None: 304 sort_order = ['s', 'o', 'a', 'p', None, 'u'] 305 306 # normalize input 307 for cat in 'soap': 308 try: 309 soap[cat] 310 except KeyError: 311 soap[cat] = [''] 312 try: 313 soap['u'] 314 except KeyError: 315 soap['u'] = [] 316 try: 317 soap[None] 318 except KeyError: 319 soap[None] = [] 320 if '.' in soap: 321 soap[None].extend(soap['.']) 322 del soap['.'] 323 if ' ' in soap: 324 soap[None].extend(soap[' ']) 325 del soap[' '] 326 327 # normalize sort order 328 for cat in 'soapu': 329 if cat not in sort_order: 330 sort_order.append(cat) 331 if None not in sort_order: 332 sort_order.append(None) 333 334 # sort and flatten 335 soap_lines = [] 336 line_categories = [] 337 for cat in sort_order: 338 lines = soap[cat] 339 if len(lines) == 0: 340 continue 341 for line in lines: 342 soap_lines.append(line.strip()) 343 line_categories.append(cat) 344 345 _log.debug('%s.SetText_from_SOAP(): 1 controlled use of .SetText() follows', self.__class__.__name__) 346 self.SetText('\n'.join(soap_lines)) 347 348 for idx in range(len(line_categories)): 349 #self.set_soap_cat_of_line(idx, line_categories[idx], unconditionally = True) 350 self.set_soap_cat_of_line(idx, line_categories[idx])
351 352 #-------------------------------------------------------
353 - def GetText_as_SOAP(self):
354 lines = self.GetText().split('\n') 355 soap = {} 356 for line_idx in range(len(lines)): 357 cat = self.get_soap_cat_of_line(line_idx) 358 try: 359 soap[cat] 360 except KeyError: 361 soap[cat] = [] 362 soap[cat].append(lines[line_idx]) 363 return soap
364 365 soap = property(GetText_as_SOAP, lambda x:x) 366 367 #--------------------------------------------------------
368 - def _get_empty(self):
369 soap = self.GetText_as_SOAP() 370 for cat in soap: 371 if ''.join([ l.strip() for l in soap[cat] ]) != '': 372 return False 373 return True
374 375 empty = property(_get_empty, lambda x:x) 376 377 #-------------------------------------------------------
378 - def sort_by_SOAP(self, sort_order=None):
380 381 #-------------------------------------------------------
382 - def append_soap_line(self, soap_cat):
383 caret_pos = self.CurrentPos 384 self.GotoPos(self.Length) 385 self.AddText('\n') 386 #self.set_soap_cat_of_line(self.LineCount, soap_cat, True) 387 self.set_soap_cat_of_line(self.LineCount, soap_cat)
388 389 #------------------------------------------------------- 390 # generic helpers 391 #-------------------------------------------------------
392 - def strip_trailing_whitespace_from_line(self, line):
393 line_text = self.GetLine(line) 394 line_start = self.PositionFromLine(line) 395 line_end = self.GetLineEndPosition(line) 396 self.SetTargetStart(line_start) 397 self.SetTargetEnd(line_end) 398 self.ReplaceTarget(line_text.rstrip())
399 400 #-------------------------------------------------------
401 - def caret_coords_in_stc(self):
402 return self.PointFromPosition(self.CurrentPos)
403 404 #-------------------------------------------------------
405 - def caret_coords_on_screen(self):
406 return self.ClientToScreen(self.caret_coords_in_stc())
407 408 #------------------------------------------------------- 409 # internal helpers 410 #-------------------------------------------------------
411 - def __build_context_menu(self):
412 413 # build menu 414 self.__popup_menu = wx.Menu(title = _('SOAP Editor Actions:')) 415 416 # sort 417 item = self.__popup_menu.Append(-1, _('&Sort lines'), _('Sort lines by SOAP category')) 418 self.Bind(wx.EVT_MENU, self.__on_sort_by_soap, item) 419 420 # expand keyword 421 item = self.__popup_menu.Append(-1, _('e&Xpand keyword'), _('Expand keyword / macro')) 422 self.Bind(wx.EVT_MENU, self.__on_expand_keyword, item) 423 424 # insert unicode 425 item = self.__popup_menu.Append(-1, _('Insert &Unicode'), _('Insert a unicode character')) 426 self.Bind(wx.EVT_MENU, self.__on_insert_unicode, item) 427 428 self.__popup_menu.AppendSeparator() 429 430 # undo 431 # redo 432 433 # submenu "line" 434 menu_line = wx.Menu() 435 436 item = menu_line.Append(-1, _('as &Subjective'), _('Set line to category "Subjective"')) 437 self.Bind(wx.EVT_MENU, self.__on_make_line_Soap, item) 438 item = menu_line.Append(-1, _('as &Objective'), _('Set line to category "Objective"')) 439 self.Bind(wx.EVT_MENU, self.__on_make_line_sOap, item) 440 item = menu_line.Append(-1, _('as &Assessment'), _('Set line to category "Assessment"')) 441 self.Bind(wx.EVT_MENU, self.__on_make_line_soAp, item) 442 item = menu_line.Append(-1, _('as &Plan'), _('Set line to category "Plan"')) 443 self.Bind(wx.EVT_MENU, self.__on_make_line_soaP, item) 444 item = menu_line.Append(-1, _('as &Unspecified'), _('Set line to category "unspecified"')) 445 self.Bind(wx.EVT_MENU, self.__on_make_line_soapU, item) 446 item = menu_line.Append(-1, _('as ad&Ministrative'), _('Set line to category "administrative"')) 447 self.Bind(wx.EVT_MENU, self.__on_make_line_soapADM, item) 448 menu_line.AppendSeparator() 449 item = menu_line.Append(-1, _('\u2192 &Clipboard'), _('Copy line to clipboard')) 450 self.Bind(wx.EVT_MENU, self.__on_line2clipboard, item) 451 item = menu_line.Append(-1, _('\u2192 +Clipboard+'), _('Add line to clipboard')) 452 self.Bind(wx.EVT_MENU, self.__on_add_line2clipboard, item) 453 # encrypt 454 455 # submenu "text" 456 menu_all = wx.Menu() 457 458 item = menu_all.Append(-1, _('\u2192 &Clipboard'), _('Copy content to clipboard')) 459 self.Bind(wx.EVT_MENU, self.__on_content2clipboard, item) 460 item = menu_all.Append(-1, _('\u2192 +Clipboard+'), _('Add content to clipboard')) 461 self.Bind(wx.EVT_MENU, self.__on_add_content2clipboard, item) 462 # ------ 463 # cut 464 # copy 465 # paste 466 # delete 467 # ------- 468 469 # selected region 470 self.__menu_selection = wx.Menu() 471 472 item = self.__menu_selection.Append(-1, _('\u2192 &Clipboard'), _('Copy selection to clipboard')) 473 self.Bind(wx.EVT_MENU, self.__on_region2clipboard, item) 474 item = self.__menu_selection.Append(-1, _('\u2192 +Clipboard+'), _('Add selection to clipboard')) 475 self.Bind(wx.EVT_MENU, self.__on_add_region2clipboard, item) 476 477 self.__popup_menu.Append(wx.NewId(), _('&Line ...'), menu_line) 478 self.__popup_menu.Append(wx.NewId(), _('&Text ...'), menu_all) 479 self.__popup_menu.Append(wx.NewId(), _('&Region ...'), self.__menu_selection)
480 481 #-------------------------------------------------------
482 - def __show_context_menu(self, position):
483 sel_start, sel_end = self.GetSelection() 484 sel_menu_id = self.__popup_menu.FindItem(_('&Region ...')) 485 if sel_start == sel_end: 486 self.__popup_menu.Enable(sel_menu_id, False) 487 else: 488 self.__popup_menu.Enable(sel_menu_id, True) 489 490 self.PopupMenu(self.__popup_menu, position)
491 492 #-------------------------------------------------------
493 - def __get_clipboard_text(self):
494 if wx.TheClipboard.IsOpened(): 495 _log.debug('clipboard already open') 496 return '' 497 if not wx.TheClipboard.Open(): 498 _log.debug('cannot open clipboard') 499 return '' 500 data_obj = wx.TextDataObject() 501 got_it = wx.TheClipboard.GetData(data_obj) 502 if not got_it: 503 return '' 504 return data_obj.Text
505 506 #------------------------------------------------------- 507 # context menu handlers 508 #-------------------------------------------------------
509 - def __on_expand_keyword(self, evt):
510 self.attempt_expansion(show_list_if_needed = True)
511 512 #-------------------------------------------------------
513 - def __on_insert_unicode(self, evt):
515 516 #-------------------------------------------------------
517 - def __on_content2clipboard(self, evt):
518 txt = self.GetText().strip() 519 if txt == '': 520 return 521 self.CopyText(len(txt), txt)
522 523 #-------------------------------------------------------
524 - def __on_add_content2clipboard(self, evt):
525 txt = self.GetText().strip() 526 if txt == '': 527 return 528 txt = self.__get_clipboard_text() + '\n' + txt 529 self.CopyText(len(txt), txt)
530 531 #-------------------------------------------------------
532 - def __on_region2clipboard(self, evt):
533 self.Copy()
534 535 #-------------------------------------------------------
536 - def __on_add_region2clipboard(self, evt):
537 region = self.GetTextRange(self.SelectionStart, self.SelectionEnd) 538 if region.strip() == '': 539 return 540 txt = self.__get_clipboard_text() + '\n' + region 541 self.CopyText(len(txt), txt)
542 543 #-------------------------------------------------------
544 - def __on_line2clipboard(self, evt):
545 txt = self.GetLine(self.CurrentLine).strip() 546 if txt == '': 547 return 548 self.CopyText(len(txt), txt)
549 550 #-------------------------------------------------------
551 - def __on_add_line2clipboard(self, evt):
552 txt = self.GetLine(self.CurrentLine).strip() 553 if txt == '': 554 return 555 txt = self.__get_clipboard_text() + '\n' + txt 556 self.CopyText(len(txt), txt)
557 558 #-------------------------------------------------------
559 - def __on_make_line_Soap(self, evt):
560 self.set_soap_cat_of_line(self.CurrentLine, 's') 561 wx.CallAfter(self.sort_by_SOAP)
562 563 #-------------------------------------------------------
564 - def __on_make_line_sOap(self, evt):
565 self.set_soap_cat_of_line(self.CurrentLine, 'o') 566 wx.CallAfter(self.sort_by_SOAP)
567 568 #-------------------------------------------------------
569 - def __on_make_line_soAp(self, evt):
570 self.set_soap_cat_of_line(self.CurrentLine, 'a') 571 wx.CallAfter(self.sort_by_SOAP)
572 573 #-------------------------------------------------------
574 - def __on_make_line_soaP(self, evt):
575 self.set_soap_cat_of_line(self.CurrentLine, 'p') 576 wx.CallAfter(self.sort_by_SOAP)
577 578 #-------------------------------------------------------
579 - def __on_make_line_soapU(self, evt):
580 self.set_soap_cat_of_line(self.CurrentLine, 'u') 581 wx.CallAfter(self.sort_by_SOAP)
582 583 #-------------------------------------------------------
584 - def __on_make_line_soapADM(self, evt):
585 self.set_soap_cat_of_line(self.CurrentLine, '.') 586 wx.CallAfter(self.sort_by_SOAP)
587 588 #-------------------------------------------------------
589 - def __on_sort_by_soap(self, evt):
590 self.sort_by_SOAP()
591 592 #------------------------------------------------------- 593 # marker related helpers 594 #-------------------------------------------------------
595 - def _clone_markers(self, source, target):
596 self.MarkerDelete(target, -1) 597 self.__set_markers_of_line(target, self.MarkerGet(source))
598 599 #-------------------------------------------------------
600 - def __set_markers_of_line(self, line, markers):
601 for marker_num in cSoapSTC._DEFINED_MARKER_NUMS: 602 if markers & (1 << marker_num): 603 self.MarkerAdd(line, marker_num)
604 605 #-------------------------------------------------------
606 - def get_soap_marker_of_line(self, line):
607 markers = self.MarkerGet(line) 608 for marker_num in cSoapSTC._SOAP_MARKER_NUMS: 609 if markers & (1 << marker_num): 610 return marker_num 611 612 return -1 # should only happen when deleting all lines -> STC empties out INCLUDING existing markers ...
613 614 #-------------------------------------------------------
615 - def get_soap_cat_of_line(self, line):
616 markers = self.MarkerGet(line) 617 for marker_num in cSoapSTC._SOAP_MARKER_NUMS: 618 if markers & (1 << marker_num): 619 return cSoapSTC._MARKER2SOAP[marker_num] 620 621 return -1 # should only happen when deleting all lines -> STC empties out INCLUDING existing markers ...
622 623 #------------------------------------------------------- 624 # def set_soap_cat_of_line(self, line, soap_category, unconditionally=False):
625 - def set_soap_cat_of_line(self, line, soap_category):
626 627 readd_soap_line = False 628 prev_soap_cat = '-' 629 # if not unconditionally: 630 if True: 631 # need to keep at least one of previous SOAP 632 prev_soap_marker = self.get_soap_marker_of_line(line) 633 if prev_soap_marker != -1: 634 if self.marker_count(prev_soap_marker) < 2: 635 prev_soap_cat = cSoapSTC._MARKER2SOAP[prev_soap_marker] 636 readd_soap_line = True 637 # return False 638 639 # remove all SOAP markers of this line 640 for marker_num in cSoapSTC._SOAP_MARKER_NUMS: 641 self.MarkerDelete(line, marker_num) 642 self.MarkerDelete(line, cSoapSTC._MARKER_LINE_BG_LIGHT_GREY) 643 644 new_marker_num = cSoapSTC._SOAP2MARKER[soap_category] 645 self.MarkerAdd(line, new_marker_num) 646 if cSoapSTC._SOAPMARKER2BACKGROUND[new_marker_num]: 647 self.MarkerAdd(line, cSoapSTC._MARKER_LINE_BG_LIGHT_GREY) 648 649 # for some reason the marker is now set but the change is not always displayed ? 650 # -> this happens if wx.CallAfter is used on this method 651 652 if readd_soap_line: 653 wx.CallAfter(self.append_soap_line, prev_soap_cat) 654 655 return True
656 657 #-------------------------------------------------------
658 - def check_has_all_soap_types(self):
659 for marker_num in [ cSoapSTC._MARKER_S, cSoapSTC._MARKER_O, cSoapSTC._MARKER_A, cSoapSTC._MARKER_P ]: 660 if self.MarkerNext(0, (1 << marker_num)) == -1: 661 return False 662 return True
663 664 #-------------------------------------------------------
665 - def ensure_has_all_soap_types(self):
666 self.__ensure_has_all_soap_types = False 667 self.sort_by_SOAP()
668 669 #-------------------------------------------------------
670 - def marker_count(self, marker):
671 line_count = 0 672 line_w_marker = -1 673 while True: 674 line_w_marker = self.MarkerNext(line_w_marker + 1, (1 << marker)) 675 if line_w_marker == -1: 676 break 677 line_count += 1 678 return line_count
679 680 #-------------------------------------------------------
681 - def soap_cat_count(self, soap_category):
682 marker = cSoapSTC._SOAP2MARKER[soap_category] 683 return self.marker_count(marker)
684 685 #------------------------------------------------------- 686 # key handlers 687 #-------------------------------------------------------
688 - def __handle_delete_key(self, evt):
689 690 if evt.HasModifiers(): 691 # we only handle DELETE w/o modifiers so far 692 evt.Skip() 693 return False 694 695 sel_start, sel_end = self.GetSelection() 696 if sel_start != sel_end: 697 evt.Skip() 698 sel_start_line = self.LineFromPosition(sel_start) 699 sel_end_line = self.LineFromPosition(sel_end) 700 # within one line -> allow in any case 701 if sel_start_line == sel_end_line: 702 return 703 sel_start_soap_marker = self.get_soap_marker_of_line(sel_start_line) 704 sel_end_soap_marker = self.get_soap_marker_of_line(sel_end_line) 705 if sel_start_soap_marker == sel_end_soap_marker: 706 # across lines of the same SOAP type -> allow 707 return 708 self.__ensure_has_all_soap_types = True 709 return 710 711 curr_line = self.CurrentLine 712 if (curr_line + 1) == self.LineCount: # adjust for line index being 0-based 713 # we are on the last line, therefore we cannot end up 714 # pulling up a next line (and thereby remove the only 715 # line with a given SOAP category in case the last+1 716 # line would happen to be the only one of that category) 717 evt.Skip() 718 return False 719 720 # in last column 721 caret_pos = self.GetColumn(self.CurrentPos) 722 max_pos = self.LineLength(curr_line) - 1 723 if caret_pos < max_pos: 724 # DELETE _inside_ a line (as opposed to at the 725 # _end_ of one) will not pull up the next line 726 # so no special SOAP checking 727 evt.Skip() 728 return False 729 730 soap_marker_current_line = self.get_soap_marker_of_line(curr_line) 731 soap_marker_next_line = self.get_soap_marker_of_line(curr_line + 1) 732 if soap_marker_current_line == soap_marker_next_line: 733 # pulling up a line of the _same_ SOAP category 734 # is fine - and exactly what the user intended 735 # so allow that to happen (IOW no special DELETE 736 # handling) 737 evt.Skip() 738 return False 739 740 # now we have got 741 # - a DELETE 742 # - without modifier keys 743 # - _not_ on the last line 744 # - in the last column of the current line 745 # - but the next line is of a different SOAP category 746 # so, do NOT evt.Skip() - IOW, ignore this DELETE 747 return True
748 749 #-------------------------------------------------------
750 - def __handle_backspace_key(self, evt):
751 752 if evt.HasModifiers(): 753 # we only handle BACKSPACE w/o modifiers so far 754 evt.Skip() 755 return False 756 757 sel_start, sel_end = self.GetSelection() 758 if sel_start != sel_end: 759 evt.Skip() 760 sel_start_line = self.LineFromPosition(sel_start) 761 sel_end_line = self.LineFromPosition(sel_end) 762 # within one line -> allow in any case 763 if sel_start_line == sel_end_line: 764 return 765 sel_start_soap_marker = self.get_soap_marker_of_line(sel_start_line) 766 sel_end_soap_marker = self.get_soap_marker_of_line(sel_end_line) 767 if sel_start_soap_marker == sel_end_soap_marker: 768 # across lines of the same SOAP type -> allow 769 return 770 self.__ensure_has_all_soap_types = True 771 return 772 773 curr_line = self.LineFromPosition(self.CurrentPos) 774 if curr_line == 0: 775 # cannot BACKSPACE into line -1 anyway 776 evt.Skip() 777 return False 778 779 if self.GetColumn(self.CurrentPos) > 0: 780 # not in first column, so not BACKSPACing into previous line 781 evt.Skip() 782 return False 783 784 soap_marker_current_line = self.get_soap_marker_of_line(curr_line) 785 soap_marker_next_line = self.get_soap_marker_of_line(curr_line - 1) 786 if soap_marker_current_line == soap_marker_next_line: 787 # backspacing into previous line of the _same_ SOAP 788 # category is fine - and exactly what the user 789 # intended so allow that to happen (IOW no special 790 # DELETE handling) 791 evt.Skip() 792 return False 793 794 # now we have got 795 # - a BACKSPACE 796 # - without modifier keys 797 # - _not_ on the first line 798 # - in the first column of the current line 799 # - but the previous line is of a different SOAP category 800 # so, do NOT evt.Skip() - IOW, ignore this BACKSPACE 801 return True
802 803 #-------------------------------------------------------
804 - def __handle_return_key_down(self, evt):
805 # currently we always want to pass on the RETURN (but remember the markers) 806 evt.Skip() 807 if evt.HasModifiers(): 808 # we only handle RETURN w/o modifiers so far 809 self.__markers_of_prev_line = None 810 return 811 self.__markers_of_prev_line = self.MarkerGet(self.CurrentLine)
812 813 #-------------------------------------------------------
814 - def __handle_soap_category_key_down(self, key, line):
815 self.__changing_SOAP_cat = False 816 try: 817 soap_category = gmSoapDefs.l10n2soap_cat[key] 818 except KeyError: 819 if key.islower(): 820 key = key.upper() 821 else: 822 key = key.lower() 823 try: 824 soap_category = gmSoapDefs.l10n2soap_cat[key] 825 except KeyError: 826 return 827 self.set_soap_cat_of_line(line, soap_category) 828 wx.CallAfter(self.sort_by_SOAP)
829 830 #-------------------------------------------------------
831 - def __handle_menu_key_down(self, evt):
832 if wx.MAJOR_VERSION > 2: 833 evt.Skip() 834 return 835 # on wxp2 we need to explicitely handle WXK_MENU 836 # for the context menu to properly work on a key press 837 self.__show_context_menu(self.caret_coords_on_screen())
838 839 #-------------------------------------------------------
840 - def _on_context_menu_activated(self, evt):
841 menu_position = evt.GetPosition() 842 if menu_position == wx.DefaultPosition: 843 caret_pos_in_stc = self.PointFromPosition(self.CurrentPos) 844 caret_pos_on_screen = self.ClientToScreen(caret_pos_in_stc) 845 menu_position = caret_pos_on_screen 846 self.__show_context_menu(menu_position)
847 848 #------------------------------------------------------- 849 # event setup and handlers 850 #-------------------------------------------------------
851 - def __register_events(self):
852 # wxPython events 853 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down) # happens before key gets into STC 854 #self.Bind(wx.EVT_CHAR, self._on_wx_char) # happens before char gets into STC 855 self.Bind(wx.EVT_CONTEXT_MENU, self._on_context_menu_activated) 856 857 # STC events 858 self.Bind(wx.stc.EVT_STC_CHARADDED, self._on_stc_char_added) 859 self.Bind(wx.stc.EVT_STC_CHANGE, self._on_stc_change)
860 861 #self.Bind(stc.EVT_STC_DO_DROP, self.OnDoDrop) 862 #self.Bind(stc.EVT_STC_DRAG_OVER, self.OnDragOver) 863 #self.Bind(stc.EVT_STC_START_DRAG, self.OnStartDrag) 864 #self.Bind(stc.EVT_STC_MODIFIED, self.OnModified) 865 866 #self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) 867 868 #-------------------------------------------------------
869 - def _on_wx_char(self, evt):
870 evt.Skip()
871 872 #-------------------------------------------------------
873 - def _on_key_down(self, evt):
874 875 # CTRL-T has been pressed last, now another character has been pressed 876 if self.__changing_SOAP_cat: 877 self.__handle_soap_category_key_down(chr(evt.GetUniChar()).lower(), self.CurrentLine) 878 # somehow put cursor into the changed (and possibly moved) line 879 return 880 881 key = evt.KeyCode 882 883 # ENTER 884 if key == wx.WXK_RETURN: 885 self.__handle_return_key_down(evt) 886 return 887 888 # BACKSPACE 889 if key == wx.WXK_BACK: 890 self.__handle_backspace_key(evt) 891 return 892 893 # DELETE 894 if key == wx.WXK_DELETE: 895 self.__handle_delete_key(evt) 896 return 897 898 # MENU 899 if key == wx.WXK_MENU: 900 self.__handle_menu_key_down(evt) 901 return 902 903 # CTRL-T: set Type 904 if key == ord('T'): 905 if evt.HasModifiers(): 906 if evt.CmdDown(): # CTRL-T or APPLE-T 907 self.__changing_SOAP_cat = True 908 return 909 910 evt.Skip() # make sure unhandled keys get to the STC
911 912 #-------------------------------------------------------
913 - def _on_stc_char_added(self, evt):
914 evt.Skip() 915 key = evt.GetKey() 916 if key == 10: 917 # we cannot simply transfer the markers of the previous 918 # line (where we pressed RETURN) into the current line 919 # (which appeared after the RETURN) because the STC handles 920 # creating the "new" line differently based on where in the 921 # previous line RETURN was pressed (!) -- if it happened 922 # to be in position 0 (at the start of the line) the previous 923 # line is pushed DOWN and an empty line is inserted BEFORE 924 # the previous line (likely an optimization) 925 # hence we need to remember the markers of the real previous 926 # line from _before_ the new line gets created and use that 927 # auto-set the markers of the new line... |-) 928 if self.__markers_of_prev_line is None: 929 return 930 self.__set_markers_of_line(self.CurrentLine - 1, self.__markers_of_prev_line) 931 self.__set_markers_of_line(self.CurrentLine, self.__markers_of_prev_line) 932 self.__markers_of_prev_line = None 933 return
934 935 #-------------------------------------------------------
936 - def _on_stc_change(self, evt):
937 if self.__ensure_has_all_soap_types: 938 wx.CallAfter(self.ensure_has_all_soap_types)
939 940 #------------------------------------------------------- 941 #------------------------------------------------------- 942 #------------------------------------------------------- 943 #------------------------------------------------------- 944 # unused: 945 #-------------------------------------------------------
946 - def OnDestroy(self, evt):
947 # This is how the clipboard contents can be preserved after 948 # the app has exited. 949 wx.TheClipboard.Flush() 950 evt.Skip()
951 952
953 - def OnStartDrag(self, evt):
954 #self.log.write("OnStartDrag: %d, %s\n" 955 # % (evt.GetDragAllowMove(), evt.GetDragText())) 956 957 if debug and evt.GetPosition() < 250: 958 evt.SetDragAllowMove(False) # you can prevent moving of text (only copy) 959 evt.SetDragText("DRAGGED TEXT") # you can change what is dragged
960 #evt.SetDragText("") # or prevent the drag with empty text 961 962
963 - def OnDragOver(self, evt):
964 #self.log.write( 965 # "OnDragOver: x,y=(%d, %d) pos: %d DragResult: %d\n" 966 # % (evt.GetX(), evt.GetY(), evt.GetPosition(), evt.GetDragResult()) 967 # ) 968 969 if debug and evt.GetPosition() < 250: 970 evt.SetDragResult(wx.DragNone) # prevent dropping at the beginning of the buffer
971 972
973 - def OnDoDrop(self, evt):
974 #self.log.write("OnDoDrop: x,y=(%d, %d) pos: %d DragResult: %d\n" 975 # "\ttext: %s\n" 976 # % (evt.GetX(), evt.GetY(), evt.GetPosition(), evt.GetDragResult(), 977 # evt.GetDragText())) 978 979 if debug and evt.GetPosition() < 500: 980 evt.SetDragText("DROPPED TEXT") # Can change text if needed
981 #evt.SetDragResult(wx.DragNone) # Can also change the drag operation, but it 982 # is probably better to do it in OnDragOver so 983 # there is visual feedback 984 985 #evt.SetPosition(25) # Can also change position, but I'm not sure why 986 # you would want to... 987 988
989 - def OnModified(self, evt):
990 #self.log.write("""OnModified 991 # Mod type: %s 992 # At position: %d 993 # Lines added: %d 994 # Text Length: %d 995 # Text: %s\n""" % ( self.transModType(evt.GetModificationType()), 996 # evt.GetPosition(), 997 # evt.GetLinesAdded(), 998 # evt.GetLength(), 999 # repr(evt.GetText()) )) 1000 pass
1001 1002
1003 - def transModType(self, modType):
1004 st = "" 1005 table = [(stc.STC_MOD_INSERTTEXT, "InsertText"), 1006 (stc.STC_MOD_DELETETEXT, "DeleteText"), 1007 (stc.STC_MOD_CHANGESTYLE, "ChangeStyle"), 1008 (stc.STC_MOD_CHANGEFOLD, "ChangeFold"), 1009 (stc.STC_PERFORMED_USER, "UserFlag"), 1010 (stc.STC_PERFORMED_UNDO, "Undo"), 1011 (stc.STC_PERFORMED_REDO, "Redo"), 1012 (stc.STC_LASTSTEPINUNDOREDO, "Last-Undo/Redo"), 1013 (stc.STC_MOD_CHANGEMARKER, "ChangeMarker"), 1014 (stc.STC_MOD_BEFOREINSERT, "B4-Insert"), 1015 (stc.STC_MOD_BEFOREDELETE, "B4-Delete") 1016 ] 1017 1018 for flag,text in table: 1019 if flag & modType: 1020 st = st + text + " " 1021 1022 if not st: 1023 st = 'UNKNOWN' 1024 1025 return st
1026 1027 #---------------------------------------------------------------------- 1028 #---------------------------------------------------------------------- 1029 #---------------------------------------------------------------------- 1030 if wx.Platform == '__WXMSW__': 1031 face1 = 'Arial' 1032 face2 = 'Times New Roman' 1033 face3 = 'Courier New' 1034 pb = 12 1035 else: 1036 face1 = 'Helvetica' 1037 face2 = 'Times' 1038 face3 = 'Courier' 1039 pb = 14 1040 1041 1042 _USE_PANEL = 1 1043
1044 -def runTest(frame, nb):
1045 if not _USE_PANEL: 1046 ed = p = cSoapSTC(nb, -1) 1047 1048 else: 1049 p = wx.Panel(nb, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE) 1050 ed = cSoapSTC(p, -1, log) 1051 s = wx.BoxSizer(wx.HORIZONTAL) 1052 s.Add(ed, 1, wx.EXPAND) 1053 p.SetSizer(s) 1054 p.SetAutoLayout(True) 1055 1056 1057 #ed.SetBufferedDraw(False) 1058 #ed.StyleClearAll() 1059 #ed.SetScrollWidth(800) 1060 #ed.SetWrapMode(True) 1061 #ed.SetUseAntiAliasing(False) 1062 #ed.SetViewEOL(True) 1063 1064 #ed.CmdKeyClear(stc.STC_KEY_BACK, 1065 # stc.STC_SCMOD_CTRL) 1066 #ed.CmdKeyAssign(stc.STC_KEY_BACK, 1067 # stc.STC_SCMOD_CTRL, 1068 # stc.STC_CMD_DELWORDLEFT) 1069 1070 ed.SetText(demoText) 1071 1072 if wx.USE_UNICODE: 1073 import codecs 1074 decode = codecs.lookup("utf-8")[1] 1075 1076 ed.GotoPos(ed.GetLength()) 1077 ed.AddText("\n\nwx.StyledTextCtrl can also do Unicode:\n") 1078 uniline = ed.GetCurrentLine() 1079 unitext, l = decode('\xd0\x9f\xd0\xb8\xd1\x82\xd0\xbe\xd0\xbd - ' 1080 '\xd0\xbb\xd1\x83\xd1\x87\xd1\x88\xd0\xb8\xd0\xb9 ' 1081 '\xd1\x8f\xd0\xb7\xd1\x8b\xd0\xba \xd0\xbf\xd1\x80\xd0\xbe\xd0\xb3\xd1\x80\xd0\xb0\xd0\xbc\xd0\xbc\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xb8\xd1\x8f!\n\n') 1082 ed.AddText('\tRussian: ') 1083 ed.AddText(unitext) 1084 ed.GotoPos(0) 1085 #else: 1086 # #ed.StyleSetFontEncoding(stc.STC_STYLE_DEFAULT, wx.FONTENCODING_KOI8) 1087 # #text = u'\u041f\u0438\u0442\u043e\u043d - \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \n\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f!' 1088 # #text = text.encode('koi8-r') 1089 # #ed.StyleSetFontEncoding(stc.STC_STYLE_DEFAULT, wx.FONTENCODING_BIG5) 1090 # #text = u'Python \u662f\u6700\u597d\u7684\u7de8\u7a0b\u8a9e\u8a00\uff01' 1091 # #text = text.encode('big5') 1092 # ed.GotoPos(ed.GetLength()) 1093 # ed.AddText('\n\n' + text) 1094 1095 ed.EmptyUndoBuffer() 1096 1097 # make some styles 1098 ed.StyleSetSpec(stc.STC_STYLE_DEFAULT, "size:%d,face:%s" % (pb, face3)) 1099 ed.StyleClearAll() 1100 ed.StyleSetSpec(1, "size:%d,bold,face:%s,fore:#0000FF" % (pb, face1)) 1101 ed.StyleSetSpec(2, "face:%s,italic,fore:#FF0000,size:%d" % (face2, pb)) 1102 ed.StyleSetSpec(3, "face:%s,bold,size:%d" % (face2, pb)) 1103 ed.StyleSetSpec(4, "face:%s,size:%d" % (face1, pb-1)) 1104 1105 # Now set some text to those styles... Normally this would be 1106 # done in an event handler that happens when text needs displayed. 1107 ed.StartStyling(98, 0xff) 1108 ed.SetStyling(6, 1) # set style for 6 characters using style 1 1109 1110 ed.StartStyling(190, 0xff) 1111 ed.SetStyling(20, 2) 1112 1113 ed.StartStyling(310, 0xff) 1114 ed.SetStyling(4, 3) 1115 ed.SetStyling(2, 0) 1116 ed.SetStyling(10, 4) 1117 1118 1119 # line numbers in the margin 1120 ed.SetMarginType(0, stc.STC_MARGIN_NUMBER) 1121 ed.SetMarginWidth(0, 22) 1122 ed.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "size:%d,face:%s" % (pb-2, face1)) 1123 1124 # setup some markers 1125 ed.SetMarginType(1, stc.STC_MARGIN_SYMBOL) 1126 ed.MarkerDefine(0, stc.STC_MARK_ROUNDRECT, "#CCFF00", "RED") 1127 ed.MarkerDefine(1, stc.STC_MARK_CIRCLE, "FOREST GREEN", "SIENNA") 1128 ed.MarkerDefine(2, stc.STC_MARK_SHORTARROW, "blue", "blue") 1129 ed.MarkerDefine(3, stc.STC_MARK_ARROW, "#00FF00", "#00FF00") 1130 1131 # put some markers on some lines 1132 ed.MarkerAdd(17, 0) 1133 ed.MarkerAdd(18, 1) 1134 ed.MarkerAdd(19, 2) 1135 ed.MarkerAdd(20, 3) 1136 ed.MarkerAdd(20, 0) 1137 1138 1139 # and finally, an indicator or two 1140 ed.IndicatorSetStyle(0, stc.STC_INDIC_SQUIGGLE) 1141 ed.IndicatorSetForeground(0, wx.RED) 1142 ed.IndicatorSetStyle(1, stc.STC_INDIC_DIAGONAL) 1143 ed.IndicatorSetForeground(1, wx.BLUE) 1144 ed.IndicatorSetStyle(2, stc.STC_INDIC_STRIKE) 1145 ed.IndicatorSetForeground(2, wx.RED) 1146 1147 ed.StartStyling(836, stc.STC_INDICS_MASK) 1148 ed.SetStyling(10, stc.STC_INDIC0_MASK) 1149 ed.SetStyling(8, stc.STC_INDIC1_MASK) 1150 ed.SetStyling(10, stc.STC_INDIC2_MASK | stc.STC_INDIC1_MASK) 1151 1152 1153 # some test stuff... 1154 if debug: 1155 print("GetTextLength(): ", ed.GetTextLength(), len(ed.GetText())) 1156 print("GetText(): ", repr(ed.GetText())) 1157 print() 1158 print("GetStyledText(98, 104): ", repr(ed.GetStyledText(98, 104)), len(ed.GetStyledText(98, 104))) 1159 print() 1160 print("GetCurLine(): ", repr(ed.GetCurLine())) 1161 ed.GotoPos(5) 1162 print("GetCurLine(): ", repr(ed.GetCurLine())) 1163 print() 1164 print("GetLine(1): ", repr(ed.GetLine(1))) 1165 print() 1166 ed.SetSelection(25, 35) 1167 print("GetSelectedText(): ", repr(ed.GetSelectedText())) 1168 print("GetTextRange(25, 35): ", repr(ed.GetTextRange(25, 35))) 1169 print("FindText(0, max, 'indicators'): ", end=' ') 1170 print(ed.FindText(0, ed.GetTextLength(), "indicators")) 1171 if wx.USE_UNICODE: 1172 end = ed.GetLength() 1173 start = ed.PositionFromLine(uniline) 1174 print("GetTextRange(%d, %d): " % (start, end), end=' ') 1175 print(repr(ed.GetTextRange(start, end))) 1176 1177 1178 wx.CallAfter(ed.GotoPos, 0) 1179 return p
1180 1181 1182 #---------------------------------------------------------------------- 1183 overview = """\ 1184 <html><body> 1185 Once again, no docs yet. <b>Sorry.</b> But <a href="data/stc.h.html">this</a> 1186 and <a href="http://www.scintilla.org/ScintillaDoc.html">this</a> should 1187 be helpful. 1188 </body><html> 1189 """ 1190 1191 #=================================================== 1192 # main 1193 #--------------------------------------------------- 1194 if __name__ == '__main__': 1195 1196 if len(sys.argv) < 2: 1197 sys.exit() 1198 1199 if sys.argv[1] != 'test': 1200 sys.exit() 1201 1202 import wx.lib.colourdb 1203 1204 from Gnumed.pycommon import gmI18N 1205 gmI18N.activate_locale() 1206 gmI18N.install_domain(domain = 'gnumed') 1207 1208 #-----------------------------------------------
1209 - def test_stc():
1210 app = wx.PyWidgetTester(size = (600, 600)) 1211 wx.lib.colourdb.updateColourDB() 1212 #print wx.lib.colourdb.getColourList() 1213 app.SetWidget(cSoapSTC, -1, (100,50)) 1214 app.MainLoop() 1215 return True
1216 1217 # app = wx.PyWidgetTester(size = (200, 50)) 1218 # tc = cTextCtrl(app.frame, -1) 1219 # #tc.enable_keyword_expansions() 1220 # app.frame.Show(True) 1221 # app.MainLoop() 1222 # return True 1223 1224 #----------------------------------------------- 1225 test_stc() 1226