diff browser_side/richtext.py @ 281:36ce989c73a5

browser_side: more customizable rich text editor
author souliane <souliane@mailoo.org>
date Mon, 09 Dec 2013 15:34:03 +0100
parents 1ccdc34cfb60
children ae3ec654836d
line wrap: on
line diff
--- a/browser_side/richtext.py	Wed Dec 04 21:52:30 2013 +0100
+++ b/browser_side/richtext.py	Mon Dec 09 15:34:03 2013 +0100
@@ -29,13 +29,23 @@
 from pyjamas.ui.HorizontalPanel import HorizontalPanel
 from list_manager import ListManager
 from sat_frontends.tools import composition
+import logging
+
+
+# used for onCloseCallback
+CANCEL, SYNC_NOT_SAVE, SAVE = xrange(0, 3)
 
 
 class RichTextEditor(FlexTable):
     """Panel for the rich text editor."""
 
-    def __init__(self, host, parent, onCloseCallback=None):
-        """Fill the editor with recipients panel, toolbar, text area..."""
+    def __init__(self, host, parent, onCloseCallback=None, options=()):
+        """Fill the editor with recipients panel, toolbar, text area...
+        @param host: the SatWebFrontend instance
+        @param parent: the parent panel
+        @param onCloseCallback: method to call when the dialog is closed
+        @param options: list of options: 'no_recipient', 'no_command', 'no_style'...
+        """
 
         # TODO: don't forget to comment this before commit
         self._debug = False
@@ -43,33 +53,49 @@
         # This must be done before FlexTable.__init__ because it is used by setVisible
         self.host = host
 
-        offset1 = len(composition.RECIPIENT_TYPES)
+        self.no_close = 'no_close' in options
+        self.update_msg = 'update_msg' in options
+        self.no_recipient = 'no_recipient' in options
+        self.no_command = 'no_command' in options
+        self.no_sync_unibox = self.no_command or 'no_sync_unibox' in options
+        self.no_main_style = 'no_style' in options or 'no_main_style' in options
+        self.no_toolbar_style = 'no_style' in options or 'no_toolbar_style' in options
+        self.no_textarea_style = 'no_style' in options or 'no_textarea_style' in options
+
+        offset1 = 0 if self.no_recipient else len(composition.RECIPIENT_TYPES)
         offset2 = len(composition.RICH_FORMATS) if self._debug else 1
-        FlexTable.__init__(self, offset1 + offset2 + 2, 2)
-        self.addStyleName('richTextEditor')
+        offset3 = 0 if self.no_command else 1
+        FlexTable.__init__(self, offset1 + offset2 + 1 + offset3, 2)
+        if not self.no_main_style:
+            self.addStyleName('richTextEditor')
 
         self._parent = parent
         self._on_close_callback = onCloseCallback
 
-        # recipient types sub-panels are automatically added by the manager
-        self.recipient = RecipientManager(self)
-        self.recipient.createWidgets(title_format="%s: ")
+        if not self.no_recipient:
+            # recipient types sub-panels are automatically added by the manager
+            self.recipient = RecipientManager(self)
+            self.recipient.createWidgets(title_format="%s: ")
 
         # Rich text tool bar is automatically added by setVisible
 
         self.textarea = TextArea()
-        self.textarea.addStyleName('richTextArea')
-
-        self.command = HorizontalPanel()
-        self.command.addStyleName("marginAuto")
-        self.command.add(Button("Cancel", listener=self.cancelWithoutSaving))
-        self.command.add(Button("Back to quick box", listener=self.closeAndSave))
-        self.command.add(Button("Send message", listener=self.sendMessage))
+        if not self.no_textarea_style:
+            self.textarea.addStyleName('richTextArea')
 
         self.getFlexCellFormatter().setColSpan(offset1 + offset2, 0, 2)
-        self.getFlexCellFormatter().setColSpan(offset1 + offset2 + 1, 0, 2)
         self.setWidget(offset1 + offset2, 0, self.textarea)
-        self.setWidget(offset1 + offset2 + 1, 0, self.command)
+
+        if not self.no_command:
+            self.command = HorizontalPanel()
+            self.command.addStyleName("marginAuto")
+            self.command.add(Button("Cancel", listener=self.cancelWithoutSaving))
+            if not self.no_sync_unibox:
+                self.command.add(Button("Back to quick box", listener=self.closeAndSave))
+            self.command.add(Button("Update" if self.update_msg else "Send message",
+                                    listener=self.__close if self.update_msg else self.sendMessage))
+            self.getFlexCellFormatter().setColSpan(offset1 + offset2 + 1, 0, 2)
+            self.setWidget(offset1 + offset2 + 1, 0, self.command)
 
     @classmethod
     def getOrCreate(cls, host, parent=None, onCloseCallback=None):
@@ -113,14 +139,15 @@
         if visible:
             self.host.bridge.call('asyncGetParamA', self.setToolBar, composition.PARAM_NAME_SYNTAX, composition.PARAM_KEY_COMPOSITION) or self.setToolBar(None)
 
-    def __close(self):
+    def __close(self, result=SAVE):
         """Remove the widget from parent or close the popup."""
-        if self._parent is None:
-            self.popup.hide()
-        else:
-            self.setVisible(False)
+        if not self.no_close:
+            if self._parent is None:
+                self.popup.hide()
+            else:
+                self.setVisible(False)
         if self._on_close_callback is not None:
-            self._on_close_callback()
+            self._on_close_callback(result)
 
     def setToolBar(self, _format):
         """This method is called asynchronously after the parameter
@@ -132,11 +159,12 @@
         if hasattr(self, "_format") and self._format == _format:
             return
         self._format = _format
-        offset1 = len(composition.RECIPIENT_TYPES)
+        offset1 = 0 if self.no_recipient else len(composition.RECIPIENT_TYPES)
         count = 0
         for _format in composition.RICH_FORMATS.keys() if self._debug else [self._format]:
             toolbar = HorizontalPanel()
-            toolbar.addStyleName('richTextToolbar')
+            if not self.no_toolbar_style:
+                toolbar.addStyleName('richTextToolbar')
             for key in composition.RICH_FORMATS[_format].keys():
                 self.addToolbarButton(toolbar, _format, key)
             label = Label("Format: %s" % _format)
@@ -177,12 +205,19 @@
     def syncFromUniBox(self):
         """Synchronize from unibox."""
         data, target = self.host.uni_box.getTargetAndData()
-        self.recipient.setContacts({"To": [target]} if target else {})
+        if hasattr(self, 'recipient'):
+            self.recipient.setContacts({"To": [target]} if target else {})
         self.textarea.setText(data if data else "")
 
     def syncToUniBox(self, recipients=None, emptyText=False):
         """Synchronize to unibox if a maximum of one recipient is set.
         @return True if the sync could be done, False otherwise"""
+        def setText():
+            self.host.uni_box.setText("" if emptyText else self.textarea.getText())
+
+        if not hasattr(self, 'recipient'):
+            setText()
+            return True
         if recipients is None:
             recipients = self.recipient.getContacts()
         target = ""
@@ -197,7 +232,7 @@
                 return False
             # TODO: change this if later more then one recipients are allowed
             target = recipients[key][0]
-        self.host.uni_box.setText("" if emptyText else self.textarea.getText())
+        setText()
         from panels import ChatPanel, MicroblogPanel
         if target == "":
             return True
@@ -211,18 +246,22 @@
 
     def cancelWithoutSaving(self):
         """Ask for confirmation before closing the dialog."""
+        if self.update_msg and self.original_text and self.textarea.getText() == self.original_text:
+            self.__close(CANCEL)
+            return
+
         def confirm_cb(answer):
             if answer:
-                self.__close()
+                self.__close(CANCEL)
 
-        _dialog = ConfirmDialog(confirm_cb, text="Do you really want to cancel this message?")
+        _dialog = ConfirmDialog(confirm_cb, text="Do you really want to %s?" % ("cancel your changes" if self.update_msg else "cancel this message"))
         _dialog.show()
 
     def closeAndSave(self):
         """Synchronize to unibox and close the dialog afterward. Display
         a message and leave the dialog open if the sync was not possible."""
         if self.syncToUniBox():
-            self.__close()
+            self.__close(SYNC_NOT_SAVE)
             return
         InfoDialog("Too many recipients",
                    "A message with more than one direct recipient (To)," +
@@ -249,7 +288,7 @@
             return
         self.syncToUniBox(recipients, emptyText=True)
         self.host.send(targets, text, extra={'rich': text})
-        self.__close()
+        self.__close(SAVE)
 
 
 class RecipientManager(ListManager):