changeset 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
files browser_side/base_panels.py browser_side/panels.py
diffstat 2 files changed, 90 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- 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 <enter> or <escape> 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 <enter> or <escape> 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)
--- 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 = '&lt;click to set a status&gt;'
 
     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):