# HG changeset patch # User souliane # Date 1394723135 -3600 # Node ID d7e78cb78dfcfd2092c5a3d543e6d696d7235bd3 # Parent ea03f898067fcb3aeece52f07517818a04349026 browser_side: HTMLTextEditor and LightTextEditor factorization diff -r ea03f898067f -r d7e78cb78dfc browser_side/base_panels.py --- a/browser_side/base_panels.py Thu Mar 13 13:15:48 2014 +0100 +++ b/browser_side/base_panels.py Thu Mar 13 16:05:35 2014 +0100 @@ -31,6 +31,7 @@ from pyjamas.ui.Event import BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT from pyjamas.ui.KeyboardListener import KEY_ENTER, KEY_ESCAPE, KeyboardHandler from pyjamas.ui.FocusListener import FocusHandler +from pyjamas.ui.ClickListener import ClickHandler from pyjamas import DOM from datetime import datetime @@ -436,10 +437,10 @@ self.edit_listeners.append(listener) -class HTMLTextEditor(BaseTextEditor, HTML, FocusHandler, KeyboardHandler): - """Manage a simple text editor with the HTML 5 "contenteditable" property.""" +class SimpleTextEditor(BaseTextEditor, FocusHandler, KeyboardHandler, ClickHandler): + """Base class for manage a simple text editor.""" - def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None): + def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): """ @param content @param modifiedCb @@ -448,126 +449,57 @@ case the edition will be terminated when or is pressed. @param listen_focus: set to True to terminate the edition when the focus is lost. Leave to None in order to use single_line's value. + @param listen_click: set to True to start the edition when you click on the widget. @param enhance_display: if True, the display text will be enhanced with addURLToText """ - HTML.__init__(self) self.__single_line = single_line self.__enhance_display = enhance_display self.__listen_focus = single_line if listen_focus is None else listen_focus + self.__listen_click = listen_click if self.__listen_focus: FocusHandler.__init__(self) + if self.__listen_click: + ClickHandler.__init__(self) KeyboardHandler.__init__(self) strproc = lambda text: html_sanitize(html_strip(text)) if self.__single_line else html_strip(text) BaseTextEditor.__init__(self, content, strproc, modifiedCb, afterEditCb) + self.textarea = self.display = None def setContent(self, content=None): BaseTextEditor.setContent(self, content) def getContent(self): - text = DOM.getInnerHTML(self.getElement()) - return {'text': self.strproc(text) if text else ''} + raise NotImplementedError def edit(self, edit, abort=False, sync=False): - if edit: - self.setHTML(self._original_content['text']) - self.getElement().setAttribute('contenteditable', 'true' if edit else 'false') BaseTextEditor.edit(self, edit) if edit: - if self.__listen_focus: - self.addFocusListener(self) - self.addKeyboardListener(self) + if self.__listen_focus and self not in self.textarea._focusListeners: + self.textarea.addFocusListener(self) + if self.__listen_click: + self.display.clearClickListener() + if self not in self.textarea._keyboardListeners: + self.textarea.addKeyboardListener(self) else: self.setDisplayContent() if self.__listen_focus: - if self in self._focusListeners: - self.removeFocusListener(self) - if self in self._keyboardListeners: - self.removeKeyboardListener(self) - - def setDisplayContent(self): - text = addURLToImage(self._original_content['text']) - self.setHTML(addURLToText(text) if self.__enhance_display else text) - - def setFocus(self, focus): - if focus: - self.getElement().focus() - else: - self.getElement().blur() - - def onKeyDown(self, sender, keycode, modifiers): - for listener in self.edit_listeners: - listener(self, keycode) - - def onKeyPress(self, sender, keycode, modifiers): - if not self.__single_line: - return - # XXX: it seems that pyjamas never catches the escape key - if keycode in (KEY_ENTER, KEY_ESCAPE): # finish the edition - self.setFocus(False) - if not self.__listen_focus: - self.edit(False) - - def onLostFocus(self, sender): - """Finish the edition when focus is lost""" - self.edit(False) - - -class LightTextEditor(BaseTextEditor, SimplePanel, FocusHandler, KeyboardHandler): - """Manage a simple text editor with a TextArea for editing, HTML for display.""" - - def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None): - """ - @param content - @param modifiedCb - @param afterEditCb - @param single_line: set to True to manage a single line editor. In that - case the edition will be terminated when or is pressed. - @param listen_focus: set to True to terminate the edition when the - focus is lost. Leave to None in order to use single_line's value. - @param enhance_display: if True, the display text will be enhanced with addURLToText - """ - SimplePanel.__init__(self) - self.__single_line = single_line - self.__enhance_display = enhance_display - self.__listen_focus = single_line if listen_focus is None else listen_focus - if self.__listen_focus: - FocusHandler.__init__(self) - KeyboardHandler.__init__(self) - strproc = lambda text: html_sanitize(html_strip(text)) if self.__single_line else html_strip(text) - BaseTextEditor.__init__(self, content, strproc, modifiedCb, afterEditCb) - self.textarea = TextArea() - self.display = HTML() - - def setContent(self, content=None): - BaseTextEditor.setContent(self, content) - - def getContent(self): - text = self.textarea.getText() - return {'text': self.strproc(text) if text else ''} - - def edit(self, edit, abort=False, sync=False): - if edit: - self.textarea.setText(self._original_content['text']) - self.setWidget(self.textarea if edit else self.display) - BaseTextEditor.edit(self, edit) - if edit: - if self.__listen_focus: - self.textarea.addFocusListener(self) - self.textarea.addKeyboardListener(self) - else: - self.setDisplayContent() - if self.__listen_focus: - if self in self._focusListeners: + try: self.textarea.removeFocusListener(self) - if self in self._keyboardListeners: + except ValueError: + pass + if self.__listen_click and self not in self.display._clickListeners: + self.display.addClickListener(self) + try: self.textarea.removeKeyboardListener(self) + except ValueError: + pass def setDisplayContent(self): text = addURLToImage(self._original_content['text']) self.display.setHTML(addURLToText(text) if self.__enhance_display else text) def setFocus(self, focus): - self.textarea.setFocus(focus) + raise NotImplementedError def onKeyDown(self, sender, keycode, modifiers): for listener in self.edit_listeners: @@ -584,4 +516,65 @@ def onLostFocus(self, sender): """Finish the edition when focus is lost""" - self.edit(False) + if self.__listen_focus: + self.edit(False) + + def onClick(self, sender=None): + """Start the edition when the widget is clicked""" + if self.__listen_click: + self.edit(True) + + def onBrowserEvent(self, event): + if self.__listen_focus: + FocusHandler.onBrowserEvent(self, event) + if self.__listen_click: + ClickHandler.onBrowserEvent(self, event) + KeyboardHandler.onBrowserEvent(self, event) + + +class HTMLTextEditor(SimpleTextEditor, HTML, FocusHandler, KeyboardHandler): + """Manage a simple text editor with the HTML 5 "contenteditable" property.""" + + def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): + HTML.__init__(self) + SimpleTextEditor.__init__(self, content, modifiedCb, afterEditCb, single_line, enhance_display, listen_focus, listen_click) + self.textarea = self.display = self + + def getContent(self): + text = DOM.getInnerHTML(self.getElement()) + return {'text': self.strproc(text) if text else ''} + + def edit(self, edit, abort=False, sync=False): + if edit: + self.textarea.setHTML(self._original_content['text']) + self.getElement().setAttribute('contenteditable', 'true' if edit else 'false') + SimpleTextEditor.edit(self, edit, abort, sync) + + def setFocus(self, focus): + if focus: + self.getElement().focus() + else: + self.getElement().blur() + + +class LightTextEditor(SimpleTextEditor, SimplePanel, FocusHandler, KeyboardHandler): + """Manage a simple text editor with a TextArea for editing, HTML for display.""" + + def __init__(self, content=None, modifiedCb=None, afterEditCb=None, single_line=False, enhance_display=True, listen_focus=None, listen_click=False): + SimplePanel.__init__(self) + SimpleTextEditor.__init__(self, content, modifiedCb, afterEditCb, single_line, enhance_display, listen_focus, listen_click) + self.textarea = TextArea() + self.display = HTML() + + def getContent(self): + text = self.textarea.getText() + return {'text': self.strproc(text) if text else ''} + + def edit(self, edit, abort=False, sync=False): + if edit: + self.textarea.setText(self._original_content['text']) + self.setWidget(self.textarea if edit else self.display) + SimpleTextEditor.edit(self, edit, abort, sync) + + def setFocus(self, focus): + self.textarea.setFocus(focus) diff -r ea03f898067f -r d7e78cb78dfc browser_side/panels.py --- a/browser_side/panels.py Thu Mar 13 13:15:48 2014 +0100 +++ b/browser_side/panels.py Thu Mar 13 16:05:35 2014 +0100 @@ -944,18 +944,16 @@ return False -class StatusPanel(HTMLTextEditor, ClickHandler): +class StatusPanel(HTMLTextEditor): EMPTY_STATUS = '<click to set a status>' def __init__(self, host, status=''): self.host = host modifiedCb = lambda content: self.host.bridge.call('setStatus', None, self.host.status_panel.presence, content['text']) or True - HTMLTextEditor.__init__(self, {'text': status}, modifiedCb, None, single_line=True) + HTMLTextEditor.__init__(self, {'text': status}, modifiedCb, None, single_line=True, listen_click=True) self.edit(False) self.setStyleName('statusPanel') - ClickHandler.__init__(self) - self.addClickListener(self) @property def status(self): @@ -985,10 +983,7 @@ status = Const.PRESENCE[presence] else: status = self.EMPTY_STATUS - self.setHTML(addURLToText(status)) - - def onClick(self, sender): - self.edit(True) + self.display.setHTML(addURLToText(status)) class PresenceStatusPanel(HorizontalPanel, ClickHandler):