comparison src/browser/sat_browser/contact_list.py @ 647:e0021d571eef frontends_multi_profiles

browser side: moved ContactBox, ContactsPanel, ContactLabeland ContactMenuBar to base_widget/base_panels so they can be reused outside of contact_list module
author Goffi <goffi@goffi.org>
date Thu, 26 Feb 2015 13:10:46 +0100
parents f5145881723a
children 6d3142b782c3
comparison
equal deleted inserted replaced
646:9972a24592b0 647:e0021d571eef
24 from pyjamas.ui.SimplePanel import SimplePanel 24 from pyjamas.ui.SimplePanel import SimplePanel
25 from pyjamas.ui.ScrollPanel import ScrollPanel 25 from pyjamas.ui.ScrollPanel import ScrollPanel
26 from pyjamas.ui.VerticalPanel import VerticalPanel 26 from pyjamas.ui.VerticalPanel import VerticalPanel
27 from pyjamas.ui.ClickListener import ClickHandler 27 from pyjamas.ui.ClickListener import ClickHandler
28 from pyjamas.ui.Label import Label 28 from pyjamas.ui.Label import Label
29 from pyjamas.ui.HTML import HTML
30 from pyjamas.ui.Image import Image
31 from pyjamas import Window 29 from pyjamas import Window
32 from pyjamas import DOM 30 from pyjamas import DOM
33 from __pyjamas__ import doc 31 from __pyjamas__ import doc
34 32
35 from sat_frontends.tools import jid
36 from constants import Const as C 33 from constants import Const as C
37 import base_widget 34 import base_widget
38 import html_tools 35 import base_panels
36 import blog
39 import chat 37 import chat
40 import blog
41
42 38
43 unicode = str # XXX: pyjama doesn't manage unicode 39 unicode = str # XXX: pyjama doesn't manage unicode
44 40
45 41
46 def buildPresenceStyle(presence, base_style=None): 42 def buildPresenceStyle(presence, base_style=None):
88 ClickHandler.__init__(self) 84 ClickHandler.__init__(self)
89 self.addClickListener(self) 85 self.addClickListener(self)
90 86
91 def onClick(self, sender): 87 def onClick(self, sender):
92 self.host.displayWidget(blog.MicroblogPanel, self.group) 88 self.host.displayWidget(blog.MicroblogPanel, self.group)
93
94
95 class ContactLabel(HTML):
96 """Display a contact in HTML, selecting best display (jid/nick/etc)"""
97
98 def __init__(self, host, jid_):
99 # TODO: add a listener for nick changes
100 HTML.__init__(self)
101 self.host = host
102 self.jid = jid_.bare
103 self.nick = self.host.contact_lists[C.PROF_KEY_NONE].getCache(self.jid, "nick")
104 self.alert = False
105 self.refresh()
106 self.setStyleName('contactLabel')
107
108 def refresh(self):
109 alert_html = "<strong>(*)</strong>&nbsp;" if self.alert else ""
110 contact_html = html_tools.html_sanitize(self.nick or unicode(self.jid))
111 html = "%(alert)s%(contact)s" % {'alert': alert_html,
112 'contact': contact_html}
113 self.setHTML(html)
114
115 def updateNick(self, new_nick):
116 """Change the current nick
117
118 @param new_nick(unicode): new nick to use
119 """
120 self.nick = new_nick
121 self.refresh()
122
123 def setAlert(self, alert):
124 """Show a visual indicator
125
126 @param alert: True if alert must be shown
127 """
128 self.alert = alert
129 self.refresh()
130
131
132 class ContactMenuBar(base_widget.WidgetMenuBar):
133
134 def onBrowserEvent(self, event):
135 base_widget.WidgetMenuBar.onBrowserEvent(self, event)
136 event.stopPropagation() # prevent opening the chat dialog
137
138 @classmethod
139 def getCategoryHTML(cls, menu_name_i18n, type_):
140 return '<img src="%s"/>' % C.DEFAULT_AVATAR_URL
141
142 def setUrl(self, url):
143 """Set the URL of the contact avatar."""
144 self.items[0].setHTML('<img src="%s" />' % url)
145
146
147 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel):
148
149 def __init__(self, parent, jid_):
150 """
151 @param parent (ContactPanel): ContactPanel hosting this box
152 @param jid_ (jid.JID): contact JID
153 """
154 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle')
155 ClickHandler.__init__(self)
156 base_widget.DragLabel.__init__(self, jid_, "CONTACT", parent.host)
157 self.jid = jid_.bare
158 self.label = ContactLabel(parent.host, self.jid)
159 self.avatar = ContactMenuBar(self, parent.host) if parent.handle_menu else Image()
160 self.updateAvatar(parent.host.getAvatarURL(self.jid))
161 self.add(self.avatar)
162 self.add(self.label)
163 self.addClickListener(self)
164
165 def addMenus(self, menu_bar):
166 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)})
167 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)})
168
169 def setAlert(self, alert):
170 """Show a visual indicator
171
172 @param alert: True if alert indicator show be shown"""
173 self.label.setAlert(alert)
174
175 def updateAvatar(self, url):
176 """Update the avatar.
177
178 @param url (unicode): image url
179 """
180 self.avatar.setUrl(url)
181
182 def updateNick(self, new_nick):
183 """Update the nickname.
184
185 @param new_nick (unicode): new nickname to use
186 """
187 self.label.updateNick(new_nick)
188
189 def onClick(self, sender):
190 try:
191 self.parent.onClick(self.jid)
192 except AttributeError:
193 pass
194 else:
195 self.setAlert(False)
196 89
197 90
198 class GroupPanel(VerticalPanel): 91 class GroupPanel(VerticalPanel):
199 92
200 def __init__(self, parent): 93 def __init__(self, parent):
238 131
239 def getGroups(self): 132 def getGroups(self):
240 return self._groups 133 return self._groups
241 134
242 135
243 class BaseContactsPanel(VerticalPanel): 136 class ContactsPanel(base_panels.ContactsPanel):
244 """ContactList graphic representation
245
246 Special features like popup menu panel or changing the contact states must be done in a sub-class.
247 """
248
249 def __init__(self, parent, handle_click=True, handle_menu=True):
250 """@param on_click (callable): click callback (used if ContactBox is created)
251 @param handle_menu (bool): if True, bind a popup menu to the avatar (used if ContactBox is created)
252 """ # FIXME
253 VerticalPanel.__init__(self)
254 self._parent = parent
255 self.host = parent.host
256 self._contacts = {} # entity jid to ContactBox map
257 self.click_listener = None
258 self.handle_menu = handle_menu
259
260 if handle_click:
261 def cb(contact_jid):
262 self.host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE)
263 self.onClick = cb
264
265 def display(self, jids):
266 """Display a contact in the list.
267
268 @param jids (list[jid.JID]): jids to display (the order is kept)
269 @param name (unicode): optional name of the contact
270 """
271 # FIXME: we do a full clear and add boxes after, we should only remove recently hidden boxes and add new ones, and re-order
272 current = [box.jid for box in self.children if isinstance(box, ContactBox)]
273 if current == jids:
274 # the display doesn't change
275 return
276 self.clear()
277 for jid_ in jids:
278 assert isinstance(jid_, jid.JID)
279 box = self.getContactBox(jid_)
280 VerticalPanel.append(self, box)
281
282 def isContactPresent(self, contact_jid):
283 """Return True if a contact is present in the panel"""
284 return contact_jid in self._contacts
285
286 def getContacts(self):
287 return self._contacts
288
289 def getContactBox(self, contact_jid):
290 """get the Contactbox of a contact
291
292 if the Contactbox doesn't exists, it will be created
293 @param contact_jid (jid.JID): the contact
294 @return: ContactBox instance
295 """
296 try:
297 return self._contacts[contact_jid.bare]
298 except KeyError:
299 box = ContactBox(self, contact_jid)
300 self._contacts[contact_jid.bare] = box
301 return box
302
303 def updateAvatar(self, jid_, url):
304 """Update the avatar of the given contact
305
306 @param jid_ (jid.JID): contact jid
307 @param url (unicode): image url
308 """
309 try:
310 self.getContactBox(jid_).updateAvatar(url)
311 except TypeError:
312 pass
313
314 def updateNick(self, jid_, new_nick):
315 """Update the avatar of the given contact
316
317 @param jid_ (jid.JID): contact jid
318 @param new_nick (unicode): new nick of the contact
319 """
320 try:
321 self.getContactBox(jid_).updateNick(new_nick)
322 except TypeError:
323 pass
324
325
326 class ContactsPanel(BaseContactsPanel):
327 """The contact list that is displayed on the left side.""" 137 """The contact list that is displayed on the left side."""
328 138
329 def __init__(self, parent): 139 def __init__(self, parent):
330 BaseContactsPanel.__init__(self, parent, handle_click=True, handle_menu=True) 140 def on_click(contact_jid):
141 self.host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE)
142 base_panels.ContactsPanel.__init__(self, parent, on_click=on_click, handle_menu=True)
331 143
332 def setState(self, jid_, type_, state): 144 def setState(self, jid_, type_, state):
333 """Change the appearance of the contact, according to the state 145 """Change the appearance of the contact, according to the state
334 146
335 @param jid_ (jid.JID): jid.JID which need to change state 147 @param jid_ (jid.JID): jid.JID which need to change state