diff src/browser/sat_browser/widget.py @ 679:a90cc8fc9605

merged branch frontends_multi_profiles
author Goffi <goffi@goffi.org>
date Wed, 18 Mar 2015 16:15:18 +0100
parents src/browser/sat_browser/panels.py@3eb3a2c0c011 src/browser/sat_browser/panels.py@849ffb24d5bf
children 9877607c719a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/sat_browser/widget.py	Wed Mar 18 16:15:18 2015 +0100
@@ -0,0 +1,261 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Libervia: a Salut à Toi frontend
+# Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import pyjd  # this is dummy in pyjs
+from sat.core.log import getLogger
+log = getLogger(__name__)
+
+from sat.core.i18n import D_
+
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.HorizontalPanel import HorizontalPanel
+from pyjamas.ui.Button import Button
+from pyjamas.ui.Frame import Frame
+from pyjamas import DOM
+
+
+import dialog
+import libervia_widget
+from constants import Const as C
+from sat_frontends.quick_frontend import quick_widgets
+from sat_frontends.tools import host_listener
+
+
+# class UniBoxPanel(HorizontalPanel):
+#     """Panel containing the UniBox"""
+#
+#     def __init__(self, host):
+#         HorizontalPanel.__init__(self)
+#         self.host = host
+#         self.setStyleName('uniBoxPanel')
+#         self.unibox = None
+#
+#     def refresh(self):
+#         """Enable or disable this panel. Contained widgets are created when necessary."""
+#         enable = self.host.getCachedParam(C.COMPOSITION_KEY, C.ENABLE_UNIBOX_PARAM) == 'true'
+#         self.setVisible(enable)
+#         if enable and not self.unibox:
+#             self.button = Button('<img src="media/icons/tango/actions/32/format-text-italic.png" class="richTextIcon"/>')
+#             self.button.setTitle('Open the rich text editor')
+#             self.button.addStyleName('uniBoxButton')
+#             self.add(self.button)
+#             self.unibox = UniBox(self.host)
+#             self.add(self.unibox)
+#             self.setCellWidth(self.unibox, '100%')
+#             self.button.addClickListener(self.openRichMessageEditor)
+#             self.unibox.addKey("@@: ")
+#             self.unibox.onSelectedChange(self.host.getSelected())
+#
+#     def openRichMessageEditor(self):
+#         """Open the rich text editor."""
+#         self.button.setVisible(False)
+#         self.unibox.setVisible(False)
+#         self.setCellWidth(self.unibox, '0px')
+#         self.host.panel._contactsMove(self)
+#
+#         def afterEditCb():
+#             Window.removeWindowResizeListener(self)
+#             self.host.panel._contactsMove(self.host.panel._hpanel)
+#             self.setCellWidth(self.unibox, '100%')
+#             self.button.setVisible(True)
+#             self.unibox.setVisible(True)
+#             self.host.resize()
+#
+#         richtext.RichMessageEditor.getOrCreate(self.host, self, afterEditCb)
+#         Window.addWindowResizeListener(self)
+#         self.host.resize()
+#
+#     def onWindowResized(self, width, height):
+#         right = self.host.panel.menu.getAbsoluteLeft() + self.host.panel.menu.getOffsetWidth()
+#         left = self.host.panel._contacts.getAbsoluteLeft() + self.host.panel._contacts.getOffsetWidth()
+#         ideal_width = right - left - 40
+#         self.host.richtext.setWidth("%spx" % ideal_width)
+
+
+
+# class UniBox(MessageBox, MouseHandler):  # AutoCompleteTextBox):
+#     """This text box is used as a main typing point, for message, microblog, etc"""
+#
+#     def __init__(self, host):
+#         MessageBox.__init__(self, host)
+#         #AutoCompleteTextBox.__init__(self)
+#         self.setStyleName('uniBox')
+#         # FIXME
+#         # host.addSelectedListener(self.onSelectedChange)
+#
+#     def addKey(self, key):
+#         return
+#         #self.getCompletionItems().completions.append(key)
+#
+#     def removeKey(self, key):
+#         return
+#         # TODO: investigate why AutoCompleteTextBox doesn't work here,
+#         # maybe it can work on a TextBox but no TextArea. Remove addKey
+#         # and removeKey methods if they don't serve anymore.
+#         try:
+#             self.getCompletionItems().completions.remove(key)
+#         except KeyError:
+#             log.warning("trying to remove an unknown key")
+#
+#     def _getTarget(self, txt):
+#         """ Say who will receive the messsage
+#         @return: a tuple (selected, target_type, target info) with:
+#             - target_hook: None if we use the selected widget, (msg, data) if we have a hook (e.g. "@@: " for a public blog), where msg is the parsed message (i.e. without the "hook key: "@@: bla" become ("bla", None))
+#             - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC
+#             - msg: HTML message which will appear in the privacy warning banner """
+#         target = self._selected_cache
+#
+#         def getSelectedOrStatus():
+#             if target and target.isSelectable():
+#                 _type, msg = target.getWarningData()
+#                 target_hook = None  # we use the selected widget, not a hook
+#             else:
+#                 _type, msg = "STATUS", "This will be your new status message"
+#                 target_hook = (txt, None)
+#             return (target_hook, _type, msg)
+#
+#         if not txt.startswith('@'):
+#             target_hook, _type, msg = getSelectedOrStatus()
+#         elif txt.startswith('@@: '):
+#             _type = "PUBLIC"
+#             msg = MicroblogPanel.warning_msg_public
+#             target_hook = (txt[4:], None)
+#         elif txt.startswith('@'):
+#             _end = txt.find(': ')
+#             if _end == -1:
+#                 target_hook, _type, msg = getSelectedOrStatus()
+#             else:
+#                 group = txt[1:_end]  # only one target group is managed for the moment
+#                 if not group or not group in self.host.contact_panel.getGroups():
+#                     # the group doesn't exists, we ignore the key
+#                     group = None
+#                     target_hook, _type, msg = getSelectedOrStatus()
+#                 else:
+#                     _type = "GROUP"
+#                     msg = MicroblogPanel.warning_msg_group % group
+#                     target_hook = (txt[_end + 2:], group)
+#         else:
+#             log.error("Unknown target")
+#             target_hook, _type, msg = getSelectedOrStatus()
+#
+#         return (target_hook, _type, msg)
+#
+#     def onKeyPress(self, sender, keycode, modifiers):
+#         _txt = self.getText()
+#         target_hook, type_, msg = self._getTarget(_txt)
+#
+#         if keycode == KEY_ENTER:
+#             if _txt:
+#                 if target_hook:
+#                     parsed_txt, data = target_hook
+#                     self.host.send([(type_, data)], parsed_txt)
+#                     self.host._updateInputHistory(_txt)
+#                     self.setText('')
+#             self.host.showWarning(None, None)
+#         else:
+#             self.host.showWarning(type_, msg)
+#         MessageBox.onKeyPress(self, sender, keycode, modifiers)
+#
+#     def getTargetAndData(self):
+#         """For external use, to get information about the (hypothetical) message
+#         that would be sent if we press Enter right now in the unibox.
+#         @return a tuple (target, data) with:
+#           - data: what would be the content of the message (body)
+#           - target: JID, group with the prefix "@" or the public entity "@@"
+#         """
+#         _txt = self.getText()
+#         target_hook, _type, _msg = self._getTarget(_txt)
+#         if target_hook:
+#             data, target = target_hook
+#             if target is None:
+#                 return target_hook
+#             return (data, "@%s" % (target if target != "" else "@"))
+#         if isinstance(self._selected_cache, MicroblogPanel):
+#             groups = self._selected_cache.accepted_groups
+#             target = "@%s" % (groups[0] if len(groups) > 0 else "@")
+#             if len(groups) > 1:
+#                 Window.alert("Sole the first group of the selected panel is taken in consideration: '%s'" % groups[0])
+#         # elif isinstance(self._selected_cache, ChatPanel): # FIXME
+#         #     target = self._selected_cache.target
+#         else:
+#             target = None
+#         return (_txt, target)
+#
+#     def onWidgetClosed(self, lib_wid):
+#         """Called when a libervia widget is closed"""
+#         if self._selected_cache == lib_wid:
+#             self.onSelectedChange(None)
+#
+#     """def complete(self):
+#
+#         #self.visible=False #XXX: self.visible is not unset in pyjamas when ENTER is pressed and a completion is done
+#         #XXX: fixed directly on pyjamas, if the patch is accepted, no need to walk around this
+#         return AutoCompleteTextBox.complete(self)"""
+
+
+class WebWidget(quick_widgets.QuickWidget, libervia_widget.LiberviaWidget):
+    """ (mini)browser like widget """
+
+    def __init__(self, host, target, show_url=True, profiles=None):
+        """
+        @param host: SatWebFrontend instance
+        @param target: url to open
+        """
+        quick_widgets.QuickWidget.__init__(self, host, target, C.PROF_KEY_NONE)
+        libervia_widget.LiberviaWidget.__init__(self, host)
+        self._vpanel = VerticalPanel()
+        self._vpanel.setSize('100%', '100%')
+        self._url = dialog.ExtTextBox(enter_cb=self.onUrlClick)
+        self._url.setText(target or "")
+        self._url.setWidth('100%')
+        if show_url:
+            hpanel = HorizontalPanel()
+            hpanel.add(self._url)
+            btn = Button("Go", self.onUrlClick)
+            hpanel.setCellWidth(self._url, "100%")
+            hpanel.add(btn)
+            self._vpanel.add(hpanel)
+            self._vpanel.setCellHeight(hpanel, '20px')
+        self._frame = Frame(target or "")
+        self._frame.setSize('100%', '100%')
+        DOM.setStyleAttribute(self._frame.getElement(), "position", "relative")
+        self._vpanel.add(self._frame)
+        self.setWidget(self._vpanel)
+
+    def onUrlClick(self, sender):
+        url = self._url.getText()
+        scheme_end = url.find(':')
+        scheme = "" if scheme_end == -1 else url[:scheme_end]
+        if scheme not in C.WEB_PANEL_SCHEMES:
+            url = "http://" + url
+        self._frame.setUrl(url)
+
+
+##  Menu
+
+def hostReady(host):
+    def onWebWidget():
+        web_widget = host.displayWidget(WebWidget, C.WEB_PANEL_DEFAULT_URL)
+        host.setSelected(web_widget)
+
+    def gotMenus():
+        host.menus.addMenu(C.MENU_GLOBAL, (D_(u"General"), D_(u"Web widget")), callback=onWebWidget)
+    host.addListener('gotMenus', gotMenus)
+
+host_listener.addListener(hostReady)