0
|
1 #!/usr/bin/python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 """ |
|
5 Libervia: a Salut à Toi frontend |
|
6 Copyright (C) 2011 Jérôme Poisson (goffi@goffi.org) |
|
7 |
|
8 This program is free software: you can redistribute it and/or modify |
|
9 it under the terms of the GNU Affero General Public License as published by |
|
10 the Free Software Foundation, either version 3 of the License, or |
|
11 (at your option) any later version. |
|
12 |
|
13 This program is distributed in the hope that it will be useful, |
|
14 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 GNU Affero General Public License for more details. |
|
17 |
|
18 You should have received a copy of the GNU Affero General Public License |
|
19 along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
20 """ |
|
21 |
|
22 import pyjd # this is dummy in pyjs |
|
23 from pyjamas.ui.SimplePanel import SimplePanel |
|
24 from pyjamas.ui.RootPanel import RootPanel |
|
25 from pyjamas.ui.VerticalPanel import VerticalPanel |
|
26 from pyjamas.ui.HorizontalPanel import HorizontalPanel |
|
27 from pyjamas.ui.Label import Label |
|
28 from pyjamas.ui import HasAlignment |
|
29 from pyjamas.ui.MenuBar import MenuBar |
|
30 from pyjamas.ui.MenuItem import MenuItem |
|
31 from pyjamas import Window |
|
32 from pyjamas.ui.AutoComplete import AutoCompleteTextBox |
|
33 from pyjamas.JSONService import JSONProxy |
|
34 from register import RegisterPanel, RegisterBox |
1
|
35 from pyjamas import DOM |
0
|
36 |
|
37 |
|
38 class LiberviaJsonProxy(JSONProxy): |
|
39 def __init__(self, *args, **kwargs): |
|
40 JSONProxy.__init__(self, *args, **kwargs) |
|
41 self.handler=self |
|
42 self.cb={} |
|
43 |
|
44 def call(self, method, cb, *args): |
|
45 self.cb[method] = cb |
|
46 self.callMethod(method,args) |
|
47 |
|
48 def onRemoteResponse(self, response, request_info): |
|
49 if self.cb.has_key(request_info.method): |
|
50 self.cb[request_info.method](response) |
|
51 del self.cb[request_info.method] |
|
52 |
|
53 def onRemoteError(self, code, errobj, request_info): |
|
54 if code != 0: |
|
55 Window.alert("Internal server error") |
|
56 else: |
|
57 if isinstance(errobj['message'],dict): |
|
58 Window.alert("Error %s: %s" % (errobj['message']['faultCode'], errobj['message']['faultString'])) |
|
59 else: |
|
60 Window.alert("Error: %s" % errobj['message']) |
|
61 |
|
62 class RegisterCall(LiberviaJsonProxy): |
|
63 def __init__(self): |
|
64 LiberviaJsonProxy.__init__(self, "/register_api", |
|
65 ["isRegistered","isConnected","connect"]) |
|
66 self.handler=self |
|
67 self.cb={} |
|
68 |
|
69 class BrigeCall(LiberviaJsonProxy): |
|
70 def __init__(self): |
|
71 LiberviaJsonProxy.__init__(self, "/json_api", |
|
72 ["getContacts"]) |
|
73 |
|
74 class MenuCmd: |
|
75 |
|
76 def __init__(self, object, handler): |
|
77 self._object = object |
|
78 self._handler = handler |
|
79 |
|
80 def execute(self): |
|
81 handler = getattr(self._object, self._handler) |
|
82 handler() |
|
83 |
|
84 class Menu(SimplePanel): |
|
85 |
|
86 def __init__(self): |
|
87 SimplePanel.__init__(self) |
|
88 |
|
89 menu_general = MenuBar(vertical=True) |
|
90 menu_general.addItem("Properties", MenuCmd(self, "onProperties")) |
|
91 |
|
92 menu_games = MenuBar(vertical=True) |
|
93 menu_games.addItem("Tarot", MenuCmd(self, "onTarotGame")) |
|
94 menu_games.addItem("Xiangqi", MenuCmd(self, "onXiangqiGame")) |
|
95 |
|
96 menubar = MenuBar(vertical=False) |
|
97 menubar.addItem(MenuItem("General", menu_general)) |
|
98 menubar.addItem(MenuItem("Games", True, menu_games)) |
|
99 self.add(menubar) |
|
100 |
|
101 def onProperties(self): |
|
102 Window.alert("Properties selected") |
|
103 |
|
104 def onTarotGame(self): |
|
105 Window.alert("Tarot selected") |
|
106 |
|
107 def onXiangqiGame(self): |
|
108 Window.alert("Xiangqi selected") |
|
109 |
|
110 class MagicBox(AutoCompleteTextBox): |
|
111 |
|
112 def __init__(self): |
|
113 AutoCompleteTextBox.__init__(self) |
1
|
114 |
|
115 def addKey(self, key): |
|
116 self.getCompletionItems().completions.append(key) |
|
117 |
|
118 class GroupLabel(Label): |
|
119 def __init__(self, group): |
|
120 Label.__init__(self, group) |
|
121 self.group = group |
|
122 self.setStyleName('group') |
|
123 |
|
124 class ContactLabel(Label): |
|
125 def __init__(self, jid, name=None): |
|
126 if not name: |
|
127 name=jid |
|
128 Label.__init__(self, name) |
|
129 self.jid=jid |
|
130 self.setStyleName('contact') |
|
131 |
|
132 class GroupList(VerticalPanel): |
|
133 |
|
134 def __init__(self, parent): |
|
135 VerticalPanel.__init__(self) |
|
136 self._parent = parent |
|
137 |
|
138 def add(self, group): |
|
139 _item = GroupLabel(group) |
|
140 _item.addMouseListener(self._parent) |
|
141 DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer") |
|
142 VerticalPanel.add(self, _item) |
|
143 |
|
144 class ContactList(VerticalPanel): |
|
145 |
|
146 def __init__(self): |
|
147 VerticalPanel.__init__(self) |
|
148 self.contacts=[] |
|
149 |
|
150 def __iter__(self): |
|
151 return self.contacts.__iter__() |
|
152 |
|
153 def add(self, jid, name=None): |
|
154 _item = ContactLabel(jid, name) |
|
155 DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer") |
|
156 VerticalPanel.add(self, _item) |
|
157 self.contacts.append(_item) |
0
|
158 |
|
159 class ContactPanel(SimplePanel): |
1
|
160 """Manage the contacts and groups""" |
0
|
161 |
1
|
162 def __init__(self, host): |
0
|
163 SimplePanel.__init__(self) |
1
|
164 self.host = host |
|
165 self.groups={} |
0
|
166 |
1
|
167 self.vPanel = VerticalPanel() |
|
168 _title = Label('Contacts') |
|
169 _title.setStyleName('contactTitle') |
|
170 |
|
171 self._contactList = ContactList() |
|
172 self._contactList.setStyleName('contactList') |
|
173 self._groupList = GroupList(self) |
|
174 self._groupList.setStyleName('groupList') |
|
175 |
|
176 self.vPanel.add(_title) |
|
177 self.vPanel.add(self._groupList) |
|
178 self.vPanel.add(self._contactList) |
|
179 self.add(self.vPanel) |
|
180 self.setStyleName('contactBox') |
|
181 |
|
182 def addContact(self, jid, attributes, groups): |
|
183 """Add a contact to the panel |
|
184 @param jid: jid |
|
185 @attributes: cf SàT Bridge API's newContact |
|
186 @param groups: list of groups""" |
|
187 for group in groups: |
|
188 if not self.groups.has_key(group): |
|
189 self.groups[group] = set() |
|
190 self._groupList.add(group) |
|
191 self.host.magicBox.addKey("@%s: " % group) |
|
192 self.groups[group].add(jid) |
|
193 self._contactList.add(jid) |
|
194 |
|
195 def onMouseMove(self, sender, x, y): |
|
196 pass |
|
197 |
|
198 def onMouseDown(self, sender, x, y): |
|
199 pass |
|
200 |
|
201 def onMouseUp(self, sender, x, y): |
|
202 pass |
|
203 |
|
204 def onMouseEnter(self, sender): |
|
205 if isinstance(sender, GroupLabel): |
|
206 for contact in self._contactList: |
|
207 if contact.jid in self.groups[sender.group]: |
|
208 contact.addStyleName("selected") |
|
209 |
|
210 def onMouseLeave(self, sender): |
|
211 if isinstance(sender, GroupLabel): |
|
212 for contact in self._contactList: |
|
213 if contact.jid in self.groups[sender.group]: |
|
214 contact.removeStyleName("selected") |
0
|
215 |
|
216 class MiddlePannel(HorizontalPanel): |
|
217 |
1
|
218 def __init__(self,host): |
|
219 self.host=host |
0
|
220 HorizontalPanel.__init__(self) |
1
|
221 self.add(self.host.contactPanel) |
0
|
222 |
|
223 class MainPanel(VerticalPanel): |
|
224 |
1
|
225 def __init__(self, host): |
|
226 self.host=host |
0
|
227 VerticalPanel.__init__(self) |
|
228 |
|
229 self.setHorizontalAlignment(HasAlignment.ALIGN_LEFT) |
|
230 self.setVerticalAlignment(HasAlignment.ALIGN_TOP) |
|
231 |
|
232 menu = Menu() |
1
|
233 magic_box = host.magicBox |
|
234 middle_panel = MiddlePannel(self.host) |
0
|
235 |
|
236 self.add(menu) |
|
237 self.add(magic_box) |
|
238 self.add(middle_panel) |
|
239 |
|
240 self.setCellHeight(menu, "5%") |
|
241 self.setCellHeight(magic_box, "5%") |
|
242 self.setCellVerticalAlignment(magic_box, HasAlignment.ALIGN_CENTER) |
|
243 self.setCellHorizontalAlignment(magic_box, HasAlignment.ALIGN_CENTER) |
|
244 self.setCellHeight(middle_panel, "90%") |
|
245 |
|
246 self.setWidth("100%") |
|
247 self.setHeight("100%") |
|
248 |
|
249 class SatWebFrontend: |
|
250 def onModuleLoad(self): |
1
|
251 self.magicBox = MagicBox() |
|
252 self.contactPanel = ContactPanel(self) |
|
253 self.panel = MainPanel(self) |
0
|
254 self._dialog = None |
|
255 RootPanel().add(self.panel) |
|
256 self._register = RegisterCall() |
1
|
257 self._register.call('isRegistered',self._isRegisteredCB) |
0
|
258 |
1
|
259 def _isRegisteredCB(self, registered): |
0
|
260 if not registered: |
|
261 self._dialog = RegisterBox(self.logged,centered=True) |
|
262 self._dialog.show() |
|
263 else: |
1
|
264 self._register.call('isConnected', self._isConnectedCB) |
0
|
265 |
1
|
266 def _isConnectedCB(self, connected): |
0
|
267 if not connected: |
|
268 self._register.call('connect',self.logged) |
|
269 else: |
|
270 self.logged() |
|
271 |
|
272 def logged(self): |
|
273 if self._dialog: |
|
274 self._dialog.hide() |
|
275 del self._dialog # don't work if self._dialog is None |
1
|
276 |
|
277 #it's time to fill the page |
|
278 bridge = BrigeCall() |
|
279 bridge.call('getContacts', self._getContactsCB) |
|
280 |
|
281 def _getContactsCB(self, contacts_data): |
|
282 for contact in contacts_data: |
|
283 jid, attributes, groups = contact |
|
284 self.contactPanel.addContact(jid, attributes, groups) |
0
|
285 |
|
286 |
|
287 if __name__ == '__main__': |
1
|
288 pyjd.setup("http://localhost:8080/libervia.html") |
0
|
289 app = SatWebFrontend() |
|
290 app.onModuleLoad() |
|
291 pyjd.run() |
|
292 |