Mercurial > libervia-web
comparison browser_side/base_panels.py @ 402:d7e78cb78dfc
browser_side: HTMLTextEditor and LightTextEditor factorization
author | souliane <souliane@mailoo.org> |
---|---|
date | Thu, 13 Mar 2014 16:05:35 +0100 |
parents | ea03f898067f |
children | ec6f7581b453 |
comparison
equal
deleted
inserted
replaced
401:ea03f898067f | 402:d7e78cb78dfc |
---|---|
29 from pyjamas.ui.StackPanel import StackPanel | 29 from pyjamas.ui.StackPanel import StackPanel |
30 from pyjamas.ui.TextArea import TextArea | 30 from pyjamas.ui.TextArea import TextArea |
31 from pyjamas.ui.Event import BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT | 31 from pyjamas.ui.Event import BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT |
32 from pyjamas.ui.KeyboardListener import KEY_ENTER, KEY_ESCAPE, KeyboardHandler | 32 from pyjamas.ui.KeyboardListener import KEY_ENTER, KEY_ESCAPE, KeyboardHandler |
33 from pyjamas.ui.FocusListener import FocusHandler | 33 from pyjamas.ui.FocusListener import FocusHandler |
34 from pyjamas.ui.ClickListener import ClickHandler | |
34 from pyjamas import DOM | 35 from pyjamas import DOM |
35 | 36 |
36 from datetime import datetime | 37 from datetime import datetime |
37 from time import time | 38 from time import time |
38 | 39 |
434 """Add a method to be called whenever the text is edited. | 435 """Add a method to be called whenever the text is edited. |
435 @param listener: method taking two arguments: sender, keycode""" | 436 @param listener: method taking two arguments: sender, keycode""" |
436 self.edit_listeners.append(listener) | 437 self.edit_listeners.append(listener) |
437 | 438 |
438 | 439 |
439 class HTMLTextEditor(BaseTextEditor, HTML, FocusHandler, KeyboardHandler): | 440 class SimpleTextEditor(BaseTextEditor, FocusHandler, KeyboardHandler, ClickHandler): |
440 """Manage a simple text editor with the HTML 5 "contenteditable" property.""" | 441 """Base class for manage a simple text editor.""" |
441 | 442 |
442 def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None): | 443 def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): |
443 """ | 444 """ |
444 @param content | 445 @param content |
445 @param modifiedCb | 446 @param modifiedCb |
446 @param afterEditCb | 447 @param afterEditCb |
447 @param single_line: set to True to manage a single line editor. In that | 448 @param single_line: set to True to manage a single line editor. In that |
448 case the edition will be terminated when <enter> or <escape> is pressed. | 449 case the edition will be terminated when <enter> or <escape> is pressed. |
449 @param listen_focus: set to True to terminate the edition when the | 450 @param listen_focus: set to True to terminate the edition when the |
450 focus is lost. Leave to None in order to use single_line's value. | 451 focus is lost. Leave to None in order to use single_line's value. |
452 @param listen_click: set to True to start the edition when you click on the widget. | |
451 @param enhance_display: if True, the display text will be enhanced with addURLToText | 453 @param enhance_display: if True, the display text will be enhanced with addURLToText |
452 """ | 454 """ |
453 HTML.__init__(self) | |
454 self.__single_line = single_line | 455 self.__single_line = single_line |
455 self.__enhance_display = enhance_display | 456 self.__enhance_display = enhance_display |
456 self.__listen_focus = single_line if listen_focus is None else listen_focus | 457 self.__listen_focus = single_line if listen_focus is None else listen_focus |
458 self.__listen_click = listen_click | |
457 if self.__listen_focus: | 459 if self.__listen_focus: |
458 FocusHandler.__init__(self) | 460 FocusHandler.__init__(self) |
461 if self.__listen_click: | |
462 ClickHandler.__init__(self) | |
459 KeyboardHandler.__init__(self) | 463 KeyboardHandler.__init__(self) |
460 strproc = lambda text: html_sanitize(html_strip(text)) if self.__single_line else html_strip(text) | 464 strproc = lambda text: html_sanitize(html_strip(text)) if self.__single_line else html_strip(text) |
461 BaseTextEditor.__init__(self, content, strproc, modifiedCb, afterEditCb) | 465 BaseTextEditor.__init__(self, content, strproc, modifiedCb, afterEditCb) |
466 self.textarea = self.display = None | |
462 | 467 |
463 def setContent(self, content=None): | 468 def setContent(self, content=None): |
464 BaseTextEditor.setContent(self, content) | 469 BaseTextEditor.setContent(self, content) |
465 | 470 |
466 def getContent(self): | 471 def getContent(self): |
467 text = DOM.getInnerHTML(self.getElement()) | 472 raise NotImplementedError |
468 return {'text': self.strproc(text) if text else ''} | |
469 | 473 |
470 def edit(self, edit, abort=False, sync=False): | 474 def edit(self, edit, abort=False, sync=False): |
471 if edit: | |
472 self.setHTML(self._original_content['text']) | |
473 self.getElement().setAttribute('contenteditable', 'true' if edit else 'false') | |
474 BaseTextEditor.edit(self, edit) | 475 BaseTextEditor.edit(self, edit) |
475 if edit: | 476 if edit: |
476 if self.__listen_focus: | 477 if self.__listen_focus and self not in self.textarea._focusListeners: |
477 self.addFocusListener(self) | 478 self.textarea.addFocusListener(self) |
478 self.addKeyboardListener(self) | 479 if self.__listen_click: |
480 self.display.clearClickListener() | |
481 if self not in self.textarea._keyboardListeners: | |
482 self.textarea.addKeyboardListener(self) | |
479 else: | 483 else: |
480 self.setDisplayContent() | 484 self.setDisplayContent() |
481 if self.__listen_focus: | 485 if self.__listen_focus: |
482 if self in self._focusListeners: | 486 try: |
483 self.removeFocusListener(self) | |
484 if self in self._keyboardListeners: | |
485 self.removeKeyboardListener(self) | |
486 | |
487 def setDisplayContent(self): | |
488 text = addURLToImage(self._original_content['text']) | |
489 self.setHTML(addURLToText(text) if self.__enhance_display else text) | |
490 | |
491 def setFocus(self, focus): | |
492 if focus: | |
493 self.getElement().focus() | |
494 else: | |
495 self.getElement().blur() | |
496 | |
497 def onKeyDown(self, sender, keycode, modifiers): | |
498 for listener in self.edit_listeners: | |
499 listener(self, keycode) | |
500 | |
501 def onKeyPress(self, sender, keycode, modifiers): | |
502 if not self.__single_line: | |
503 return | |
504 # XXX: it seems that pyjamas never catches the escape key | |
505 if keycode in (KEY_ENTER, KEY_ESCAPE): # finish the edition | |
506 self.setFocus(False) | |
507 if not self.__listen_focus: | |
508 self.edit(False) | |
509 | |
510 def onLostFocus(self, sender): | |
511 """Finish the edition when focus is lost""" | |
512 self.edit(False) | |
513 | |
514 | |
515 class LightTextEditor(BaseTextEditor, SimplePanel, FocusHandler, KeyboardHandler): | |
516 """Manage a simple text editor with a TextArea for editing, HTML for display.""" | |
517 | |
518 def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None): | |
519 """ | |
520 @param content | |
521 @param modifiedCb | |
522 @param afterEditCb | |
523 @param single_line: set to True to manage a single line editor. In that | |
524 case the edition will be terminated when <enter> or <escape> is pressed. | |
525 @param listen_focus: set to True to terminate the edition when the | |
526 focus is lost. Leave to None in order to use single_line's value. | |
527 @param enhance_display: if True, the display text will be enhanced with addURLToText | |
528 """ | |
529 SimplePanel.__init__(self) | |
530 self.__single_line = single_line | |
531 self.__enhance_display = enhance_display | |
532 self.__listen_focus = single_line if listen_focus is None else listen_focus | |
533 if self.__listen_focus: | |
534 FocusHandler.__init__(self) | |
535 KeyboardHandler.__init__(self) | |
536 strproc = lambda text: html_sanitize(html_strip(text)) if self.__single_line else html_strip(text) | |
537 BaseTextEditor.__init__(self, content, strproc, modifiedCb, afterEditCb) | |
538 self.textarea = TextArea() | |
539 self.display = HTML() | |
540 | |
541 def setContent(self, content=None): | |
542 BaseTextEditor.setContent(self, content) | |
543 | |
544 def getContent(self): | |
545 text = self.textarea.getText() | |
546 return {'text': self.strproc(text) if text else ''} | |
547 | |
548 def edit(self, edit, abort=False, sync=False): | |
549 if edit: | |
550 self.textarea.setText(self._original_content['text']) | |
551 self.setWidget(self.textarea if edit else self.display) | |
552 BaseTextEditor.edit(self, edit) | |
553 if edit: | |
554 if self.__listen_focus: | |
555 self.textarea.addFocusListener(self) | |
556 self.textarea.addKeyboardListener(self) | |
557 else: | |
558 self.setDisplayContent() | |
559 if self.__listen_focus: | |
560 if self in self._focusListeners: | |
561 self.textarea.removeFocusListener(self) | 487 self.textarea.removeFocusListener(self) |
562 if self in self._keyboardListeners: | 488 except ValueError: |
489 pass | |
490 if self.__listen_click and self not in self.display._clickListeners: | |
491 self.display.addClickListener(self) | |
492 try: | |
563 self.textarea.removeKeyboardListener(self) | 493 self.textarea.removeKeyboardListener(self) |
494 except ValueError: | |
495 pass | |
564 | 496 |
565 def setDisplayContent(self): | 497 def setDisplayContent(self): |
566 text = addURLToImage(self._original_content['text']) | 498 text = addURLToImage(self._original_content['text']) |
567 self.display.setHTML(addURLToText(text) if self.__enhance_display else text) | 499 self.display.setHTML(addURLToText(text) if self.__enhance_display else text) |
568 | 500 |
569 def setFocus(self, focus): | 501 def setFocus(self, focus): |
570 self.textarea.setFocus(focus) | 502 raise NotImplementedError |
571 | 503 |
572 def onKeyDown(self, sender, keycode, modifiers): | 504 def onKeyDown(self, sender, keycode, modifiers): |
573 for listener in self.edit_listeners: | 505 for listener in self.edit_listeners: |
574 listener(self.textarea, keycode) | 506 listener(self.textarea, keycode) |
575 | 507 |
582 if not self.__listen_focus: | 514 if not self.__listen_focus: |
583 self.edit(False) | 515 self.edit(False) |
584 | 516 |
585 def onLostFocus(self, sender): | 517 def onLostFocus(self, sender): |
586 """Finish the edition when focus is lost""" | 518 """Finish the edition when focus is lost""" |
587 self.edit(False) | 519 if self.__listen_focus: |
520 self.edit(False) | |
521 | |
522 def onClick(self, sender=None): | |
523 """Start the edition when the widget is clicked""" | |
524 if self.__listen_click: | |
525 self.edit(True) | |
526 | |
527 def onBrowserEvent(self, event): | |
528 if self.__listen_focus: | |
529 FocusHandler.onBrowserEvent(self, event) | |
530 if self.__listen_click: | |
531 ClickHandler.onBrowserEvent(self, event) | |
532 KeyboardHandler.onBrowserEvent(self, event) | |
533 | |
534 | |
535 class HTMLTextEditor(SimpleTextEditor, HTML, FocusHandler, KeyboardHandler): | |
536 """Manage a simple text editor with the HTML 5 "contenteditable" property.""" | |
537 | |
538 def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): | |
539 HTML.__init__(self) | |
540 SimpleTextEditor.__init__(self, content, modifiedCb, afterEditCb, single_line, enhance_display, listen_focus, listen_click) | |
541 self.textarea = self.display = self | |
542 | |
543 def getContent(self): | |
544 text = DOM.getInnerHTML(self.getElement()) | |
545 return {'text': self.strproc(text) if text else ''} | |
546 | |
547 def edit(self, edit, abort=False, sync=False): | |
548 if edit: | |
549 self.textarea.setHTML(self._original_content['text']) | |
550 self.getElement().setAttribute('contenteditable', 'true' if edit else 'false') | |
551 SimpleTextEditor.edit(self, edit, abort, sync) | |
552 | |
553 def setFocus(self, focus): | |
554 if focus: | |
555 self.getElement().focus() | |
556 else: | |
557 self.getElement().blur() | |
558 | |
559 | |
560 class LightTextEditor(SimpleTextEditor, SimplePanel, FocusHandler, KeyboardHandler): | |
561 """Manage a simple text editor with a TextArea for editing, HTML for display.""" | |
562 | |
563 def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): | |
564 SimplePanel.__init__(self) | |
565 SimpleTextEditor.__init__(self, content, modifiedCb, afterEditCb, single_line, enhance_display, listen_focus, listen_click) | |
566 self.textarea = TextArea() | |
567 self.display = HTML() | |
568 | |
569 def getContent(self): | |
570 text = self.textarea.getText() | |
571 return {'text': self.strproc(text) if text else ''} | |
572 | |
573 def edit(self, edit, abort=False, sync=False): | |
574 if edit: | |
575 self.textarea.setText(self._original_content['text']) | |
576 self.setWidget(self.textarea if edit else self.display) | |
577 SimpleTextEditor.edit(self, edit, abort, sync) | |
578 | |
579 def setFocus(self, focus): | |
580 self.textarea.setFocus(focus) |