comparison src/browser/sat_browser/widget.py @ 648:6d3142b782c3 frontends_multi_profiles

browser_side: classes reorganisation: - moved widgets in dedicated modules (base, contact, editor, libervia) and a widget module for single classes - same thing for panels (base, main, contact) - libervia_widget mix main panels and widget and drag n drop for technical reasons (see comments) - renamed WebPanel to WebWidget
author Goffi <goffi@goffi.org>
date Thu, 26 Feb 2015 18:10:54 +0100
parents src/browser/sat_browser/panels.py@7113d40533d6
children 849ffb24d5bf
comparison
equal deleted inserted replaced
647:e0021d571eef 648:6d3142b782c3
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 # Libervia: a Salut à Toi frontend
5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org>
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 import pyjd # this is dummy in pyjs
21 from sat.core.log import getLogger
22 log = getLogger(__name__)
23
24 from pyjamas.ui.VerticalPanel import VerticalPanel
25 from pyjamas.ui.HorizontalPanel import HorizontalPanel
26 from pyjamas.ui.Button import Button
27 from pyjamas.ui.Frame import Frame
28 from pyjamas import DOM
29
30
31 import dialog
32 import libervia_widget
33 from constants import Const as C
34 from sat_frontends.quick_frontend import quick_widgets
35
36
37 # class UniBoxPanel(HorizontalPanel):
38 # """Panel containing the UniBox"""
39 #
40 # def __init__(self, host):
41 # HorizontalPanel.__init__(self)
42 # self.host = host
43 # self.setStyleName('uniBoxPanel')
44 # self.unibox = None
45 #
46 # def refresh(self):
47 # """Enable or disable this panel. Contained widgets are created when necessary."""
48 # enable = self.host.getCachedParam(C.COMPOSITION_KEY, C.ENABLE_UNIBOX_PARAM) == 'true'
49 # self.setVisible(enable)
50 # if enable and not self.unibox:
51 # self.button = Button('<img src="media/icons/tango/actions/32/format-text-italic.png" class="richTextIcon"/>')
52 # self.button.setTitle('Open the rich text editor')
53 # self.button.addStyleName('uniBoxButton')
54 # self.add(self.button)
55 # self.unibox = UniBox(self.host)
56 # self.add(self.unibox)
57 # self.setCellWidth(self.unibox, '100%')
58 # self.button.addClickListener(self.openRichMessageEditor)
59 # self.unibox.addKey("@@: ")
60 # self.unibox.onSelectedChange(self.host.getSelected())
61 #
62 # def openRichMessageEditor(self):
63 # """Open the rich text editor."""
64 # self.button.setVisible(False)
65 # self.unibox.setVisible(False)
66 # self.setCellWidth(self.unibox, '0px')
67 # self.host.panel._contactsMove(self)
68 #
69 # def afterEditCb():
70 # Window.removeWindowResizeListener(self)
71 # self.host.panel._contactsMove(self.host.panel._hpanel)
72 # self.setCellWidth(self.unibox, '100%')
73 # self.button.setVisible(True)
74 # self.unibox.setVisible(True)
75 # self.host.resize()
76 #
77 # richtext.RichMessageEditor.getOrCreate(self.host, self, afterEditCb)
78 # Window.addWindowResizeListener(self)
79 # self.host.resize()
80 #
81 # def onWindowResized(self, width, height):
82 # right = self.host.panel.menu.getAbsoluteLeft() + self.host.panel.menu.getOffsetWidth()
83 # left = self.host.panel._contacts.getAbsoluteLeft() + self.host.panel._contacts.getOffsetWidth()
84 # ideal_width = right - left - 40
85 # self.host.richtext.setWidth("%spx" % ideal_width)
86
87
88
89 # class UniBox(MessageBox, MouseHandler): # AutoCompleteTextBox):
90 # """This text box is used as a main typing point, for message, microblog, etc"""
91 #
92 # def __init__(self, host):
93 # MessageBox.__init__(self, host)
94 # #AutoCompleteTextBox.__init__(self)
95 # self.setStyleName('uniBox')
96 # # FIXME
97 # # host.addSelectedListener(self.onSelectedChange)
98 #
99 # def addKey(self, key):
100 # return
101 # #self.getCompletionItems().completions.append(key)
102 #
103 # def removeKey(self, key):
104 # return
105 # # TODO: investigate why AutoCompleteTextBox doesn't work here,
106 # # maybe it can work on a TextBox but no TextArea. Remove addKey
107 # # and removeKey methods if they don't serve anymore.
108 # try:
109 # self.getCompletionItems().completions.remove(key)
110 # except KeyError:
111 # log.warning("trying to remove an unknown key")
112 #
113 # def _getTarget(self, txt):
114 # """ Say who will receive the messsage
115 # @return: a tuple (selected, target_type, target info) with:
116 # - 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))
117 # - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC
118 # - msg: HTML message which will appear in the privacy warning banner """
119 # target = self._selected_cache
120 #
121 # def getSelectedOrStatus():
122 # if target and target.isSelectable():
123 # _type, msg = target.getWarningData()
124 # target_hook = None # we use the selected widget, not a hook
125 # else:
126 # _type, msg = "STATUS", "This will be your new status message"
127 # target_hook = (txt, None)
128 # return (target_hook, _type, msg)
129 #
130 # if not txt.startswith('@'):
131 # target_hook, _type, msg = getSelectedOrStatus()
132 # elif txt.startswith('@@: '):
133 # _type = "PUBLIC"
134 # msg = MicroblogPanel.warning_msg_public
135 # target_hook = (txt[4:], None)
136 # elif txt.startswith('@'):
137 # _end = txt.find(': ')
138 # if _end == -1:
139 # target_hook, _type, msg = getSelectedOrStatus()
140 # else:
141 # group = txt[1:_end] # only one target group is managed for the moment
142 # if not group or not group in self.host.contact_panel.getGroups():
143 # # the group doesn't exists, we ignore the key
144 # group = None
145 # target_hook, _type, msg = getSelectedOrStatus()
146 # else:
147 # _type = "GROUP"
148 # msg = MicroblogPanel.warning_msg_group % group
149 # target_hook = (txt[_end + 2:], group)
150 # else:
151 # log.error("Unknown target")
152 # target_hook, _type, msg = getSelectedOrStatus()
153 #
154 # return (target_hook, _type, msg)
155 #
156 # def onKeyPress(self, sender, keycode, modifiers):
157 # _txt = self.getText()
158 # target_hook, type_, msg = self._getTarget(_txt)
159 #
160 # if keycode == KEY_ENTER:
161 # if _txt:
162 # if target_hook:
163 # parsed_txt, data = target_hook
164 # self.host.send([(type_, data)], parsed_txt)
165 # self.host._updateInputHistory(_txt)
166 # self.setText('')
167 # self.host.showWarning(None, None)
168 # else:
169 # self.host.showWarning(type_, msg)
170 # MessageBox.onKeyPress(self, sender, keycode, modifiers)
171 #
172 # def getTargetAndData(self):
173 # """For external use, to get information about the (hypothetical) message
174 # that would be sent if we press Enter right now in the unibox.
175 # @return a tuple (target, data) with:
176 # - data: what would be the content of the message (body)
177 # - target: JID, group with the prefix "@" or the public entity "@@"
178 # """
179 # _txt = self.getText()
180 # target_hook, _type, _msg = self._getTarget(_txt)
181 # if target_hook:
182 # data, target = target_hook
183 # if target is None:
184 # return target_hook
185 # return (data, "@%s" % (target if target != "" else "@"))
186 # if isinstance(self._selected_cache, MicroblogPanel):
187 # groups = self._selected_cache.accepted_groups
188 # target = "@%s" % (groups[0] if len(groups) > 0 else "@")
189 # if len(groups) > 1:
190 # Window.alert("Sole the first group of the selected panel is taken in consideration: '%s'" % groups[0])
191 # # elif isinstance(self._selected_cache, ChatPanel): # FIXME
192 # # target = self._selected_cache.target
193 # else:
194 # target = None
195 # return (_txt, target)
196 #
197 # def onWidgetClosed(self, lib_wid):
198 # """Called when a libervia widget is closed"""
199 # if self._selected_cache == lib_wid:
200 # self.onSelectedChange(None)
201 #
202 # """def complete(self):
203 #
204 # #self.visible=False #XXX: self.visible is not unset in pyjamas when ENTER is pressed and a completion is done
205 # #XXX: fixed directly on pyjamas, if the patch is accepted, no need to walk around this
206 # return AutoCompleteTextBox.complete(self)"""
207
208
209 class WebWidget(quick_widgets.QuickWidget, libervia_widget.LiberviaWidget):
210 """ (mini)browser like widget """
211
212 def __init__(self, host, target, show_url=True, profiles=None):
213 """
214 @param host: SatWebFrontend instance
215 @param target: url to open
216 """
217 quick_widgets.QuickWidget.__init__(self, host, target, C.PROF_KEY_NONE)
218 libervia_widget.LiberviaWidget.__init__(self, host)
219 self._vpanel = VerticalPanel()
220 self._vpanel.setSize('100%', '100%')
221 self._url = dialog.ExtTextBox(enter_cb=self.onUrlClick)
222 self._url.setText(target or "")
223 self._url.setWidth('100%')
224 if show_url:
225 hpanel = HorizontalPanel()
226 hpanel.add(self._url)
227 btn = Button("Go", self.onUrlClick)
228 hpanel.setCellWidth(self._url, "100%")
229 hpanel.add(btn)
230 self._vpanel.add(hpanel)
231 self._vpanel.setCellHeight(hpanel, '20px')
232 self._frame = Frame(target or "")
233 self._frame.setSize('100%', '100%')
234 DOM.setStyleAttribute(self._frame.getElement(), "position", "relative")
235 self._vpanel.add(self._frame)
236 self.setWidget(self._vpanel)
237
238 def onUrlClick(self, sender):
239 url = self._url.getText()
240 scheme_end = url.find(':')
241 scheme = "" if scheme_end == -1 else url[:scheme_end]
242 if scheme not in C.WEB_PANEL_SCHEMES:
243 url = "http://" + url
244 self._frame.setUrl(url)