Mercurial > libervia-web
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) |