# HG changeset patch # User Goffi # Date 1424952646 -3600 # Node ID e0021d571eef4893f612a331e25ab7150c4d6fe6 # Parent 9972a24592b010fb5f2893b42a66dad6e5f8d940 browser side: moved ContactBox, ContactsPanel, ContactLabeland ContactMenuBar to base_widget/base_panels so they can be reused outside of contact_list module diff -r 9972a24592b0 -r e0021d571eef src/browser/sat_browser/base_panels.py --- a/src/browser/sat_browser/base_panels.py Wed Feb 25 19:44:10 2015 +0100 +++ b/src/browser/sat_browser/base_panels.py Thu Feb 26 13:10:46 2015 +0100 @@ -22,6 +22,7 @@ log = getLogger(__name__) from sat.core.i18n import _ from sat_frontends.tools import strings +from sat_frontends.tools import jid from pyjamas.ui.AbsolutePanel import AbsolutePanel from pyjamas.ui.VerticalPanel import VerticalPanel @@ -39,9 +40,11 @@ from pyjamas import DOM import html_tools +import base_widget from constants import Const as C + class Occupant(HTML): """Occupant of a MUC room""" @@ -84,6 +87,90 @@ self.setHTML("%s%s%s" % (html_tools.html_sanitize(self.nick), special, state)) +class ContactsPanel(VerticalPanel): + """ContactList graphic representation + + Special features like popup menu panel or changing the contact states must be done in a sub-class. + """ + + def __init__(self, parent, on_click=None, handle_menu=True): + """ + @param on_click (callable): click callback (used if ContactBox is created) + @param handle_menu (bool): if True, bind a popup menu to the avatar (used if ContactBox is created) + """ # FIXME + VerticalPanel.__init__(self) + self._parent = parent + self.host = parent.host + self._contacts = {} # entity jid to ContactBox map + self.click_listener = None + self.handle_menu = handle_menu + + if on_click is not None: + self.onClick = on_click + + def display(self, jids): + """Display a contact in the list. + + @param jids (list[jid.JID]): jids to display (the order is kept) + @param name (unicode): optional name of the contact + """ + # FIXME: we do a full clear and add boxes after, we should only remove recently hidden boxes and add new ones, and re-order + current = [box.jid for box in self.children if isinstance(box, base_widget.ContactBox)] + if current == jids: + # the display doesn't change + return + self.clear() + for jid_ in jids: + assert isinstance(jid_, jid.JID) + box = self.getContactBox(jid_) + VerticalPanel.append(self, box) + + def isContactPresent(self, contact_jid): + """Return True if a contact is present in the panel""" + return contact_jid in self._contacts + + def getContacts(self): + return self._contacts + + def getContactBox(self, contact_jid): + """get the Contactbox of a contact + + if the Contactbox doesn't exists, it will be created + @param contact_jid (jid.JID): the contact + @return: ContactBox instance + """ + try: + return self._contacts[contact_jid.bare] + except KeyError: + box = base_widget.ContactBox(self, contact_jid) + self._contacts[contact_jid.bare] = box + return box + + def updateAvatar(self, jid_, url): + """Update the avatar of the given contact + + @param jid_ (jid.JID): contact jid + @param url (unicode): image url + """ + try: + self.getContactBox(jid_).updateAvatar(url) + except TypeError: + pass + + def updateNick(self, jid_, new_nick): + """Update the avatar of the given contact + + @param jid_ (jid.JID): contact jid + @param new_nick (unicode): new nick of the contact + """ + try: + self.getContactBox(jid_).updateNick(new_nick) + except TypeError: + pass + + + +# FIXME: must be removed and ContactsPanel must be used instead class OccupantsList(AbsolutePanel): """Panel user to show occupants of a room""" diff -r 9972a24592b0 -r e0021d571eef src/browser/sat_browser/base_widget.py --- a/src/browser/sat_browser/base_widget.py Wed Feb 25 19:44:10 2015 +0100 +++ b/src/browser/sat_browser/base_widget.py Thu Feb 26 13:10:46 2015 +0100 @@ -34,6 +34,7 @@ from pyjamas.ui.HTMLPanel import HTMLPanel from pyjamas.ui.Label import Label from pyjamas.ui.HTML import HTML +from pyjamas.ui.Image import Image from pyjamas.ui.Button import Button from pyjamas.ui.Widget import Widget from pyjamas.ui.DragWidget import DragWidget @@ -42,11 +43,15 @@ from pyjamas.ui import HasAlignment from pyjamas import DOM from pyjamas import Window +from constants import Const as C from __pyjamas__ import doc import dialog import base_menu +import html_tools + +unicode = str # XXX: pyjama doesn't manage unicode class NoLiberviaWidgetException(Exception): @@ -892,3 +897,106 @@ self.remove(panel) widgets_count = self.getWidgetCount() self.selectTab(widget_index if widget_index < widgets_count else widgets_count - 1) + + +class ContactLabel(HTML): + """Display a contact in HTML, selecting best display (jid/nick/etc)""" + + def __init__(self, host, jid_): + # TODO: add a listener for nick changes + HTML.__init__(self) + self.host = host + self.jid = jid_.bare + self.nick = self.host.contact_lists[C.PROF_KEY_NONE].getCache(self.jid, "nick") + self.alert = False + self.refresh() + self.setStyleName('contactLabel') + + def refresh(self): + alert_html = "(*) " if self.alert else "" + contact_html = html_tools.html_sanitize(self.nick or unicode(self.jid)) + html = "%(alert)s%(contact)s" % {'alert': alert_html, + 'contact': contact_html} + self.setHTML(html) + + def updateNick(self, new_nick): + """Change the current nick + + @param new_nick(unicode): new nick to use + """ + self.nick = new_nick + self.refresh() + + def setAlert(self, alert): + """Show a visual indicator + + @param alert: True if alert must be shown + """ + self.alert = alert + self.refresh() + + +class ContactMenuBar(WidgetMenuBar): + + def onBrowserEvent(self, event): + WidgetMenuBar.onBrowserEvent(self, event) + event.stopPropagation() # prevent opening the chat dialog + + @classmethod + def getCategoryHTML(cls, menu_name_i18n, type_): + return '' % C.DEFAULT_AVATAR_URL + + def setUrl(self, url): + """Set the URL of the contact avatar.""" + self.items[0].setHTML('' % url) + + +class ContactBox(VerticalPanel, ClickHandler, DragLabel): + + def __init__(self, parent, jid_): + """ + @param parent (ContactPanel): ContactPanel hosting this box + @param jid_ (jid.JID): contact JID + """ + VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') + ClickHandler.__init__(self) + DragLabel.__init__(self, jid_, "CONTACT", parent.host) + self.jid = jid_.bare + self.label = ContactLabel(parent.host, self.jid) + self.avatar = ContactMenuBar(self, parent.host) if parent.handle_menu else Image() + self.updateAvatar(parent.host.getAvatarURL(self.jid)) + self.add(self.avatar) + self.add(self.label) + self.addClickListener(self) + + def addMenus(self, menu_bar): + menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) + menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) + + def setAlert(self, alert): + """Show a visual indicator + + @param alert: True if alert indicator show be shown""" + self.label.setAlert(alert) + + def updateAvatar(self, url): + """Update the avatar. + + @param url (unicode): image url + """ + self.avatar.setUrl(url) + + def updateNick(self, new_nick): + """Update the nickname. + + @param new_nick (unicode): new nickname to use + """ + self.label.updateNick(new_nick) + + def onClick(self, sender): + try: + self.parent.onClick(self.jid) + except AttributeError: + pass + else: + self.setAlert(False) diff -r 9972a24592b0 -r e0021d571eef src/browser/sat_browser/contact_group.py --- a/src/browser/sat_browser/contact_group.py Wed Feb 25 19:44:10 2015 +0100 +++ b/src/browser/sat_browser/contact_group.py Thu Feb 26 13:10:46 2015 +0100 @@ -29,6 +29,7 @@ import dialog import list_manager import contact_list +import base_panels unicode = str # FIXME: pyjamas workaround @@ -185,7 +186,7 @@ """Add the contact list to the DockPanel.""" self.toggle = Button("", self.toggleContacts) self.toggle.addStyleName("toggleAssignedContacts") - self.contacts = contact_list.BaseContactsPanel(self.host) + self.contacts = base_panels.ContactsPanel(self.host) for contact in self.all_contacts: self.contacts.add(contact) contact_panel = VerticalPanel() diff -r 9972a24592b0 -r e0021d571eef src/browser/sat_browser/contact_list.py --- a/src/browser/sat_browser/contact_list.py Wed Feb 25 19:44:10 2015 +0100 +++ b/src/browser/sat_browser/contact_list.py Thu Feb 26 13:10:46 2015 +0100 @@ -26,19 +26,15 @@ from pyjamas.ui.VerticalPanel import VerticalPanel from pyjamas.ui.ClickListener import ClickHandler from pyjamas.ui.Label import Label -from pyjamas.ui.HTML import HTML -from pyjamas.ui.Image import Image from pyjamas import Window from pyjamas import DOM from __pyjamas__ import doc -from sat_frontends.tools import jid from constants import Const as C import base_widget -import html_tools +import base_panels +import blog import chat -import blog - unicode = str # XXX: pyjama doesn't manage unicode @@ -92,109 +88,6 @@ self.host.displayWidget(blog.MicroblogPanel, self.group) -class ContactLabel(HTML): - """Display a contact in HTML, selecting best display (jid/nick/etc)""" - - def __init__(self, host, jid_): - # TODO: add a listener for nick changes - HTML.__init__(self) - self.host = host - self.jid = jid_.bare - self.nick = self.host.contact_lists[C.PROF_KEY_NONE].getCache(self.jid, "nick") - self.alert = False - self.refresh() - self.setStyleName('contactLabel') - - def refresh(self): - alert_html = "(*) " if self.alert else "" - contact_html = html_tools.html_sanitize(self.nick or unicode(self.jid)) - html = "%(alert)s%(contact)s" % {'alert': alert_html, - 'contact': contact_html} - self.setHTML(html) - - def updateNick(self, new_nick): - """Change the current nick - - @param new_nick(unicode): new nick to use - """ - self.nick = new_nick - self.refresh() - - def setAlert(self, alert): - """Show a visual indicator - - @param alert: True if alert must be shown - """ - self.alert = alert - self.refresh() - - -class ContactMenuBar(base_widget.WidgetMenuBar): - - def onBrowserEvent(self, event): - base_widget.WidgetMenuBar.onBrowserEvent(self, event) - event.stopPropagation() # prevent opening the chat dialog - - @classmethod - def getCategoryHTML(cls, menu_name_i18n, type_): - return '' % C.DEFAULT_AVATAR_URL - - def setUrl(self, url): - """Set the URL of the contact avatar.""" - self.items[0].setHTML('' % url) - - -class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): - - def __init__(self, parent, jid_): - """ - @param parent (ContactPanel): ContactPanel hosting this box - @param jid_ (jid.JID): contact JID - """ - VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') - ClickHandler.__init__(self) - base_widget.DragLabel.__init__(self, jid_, "CONTACT", parent.host) - self.jid = jid_.bare - self.label = ContactLabel(parent.host, self.jid) - self.avatar = ContactMenuBar(self, parent.host) if parent.handle_menu else Image() - self.updateAvatar(parent.host.getAvatarURL(self.jid)) - self.add(self.avatar) - self.add(self.label) - self.addClickListener(self) - - def addMenus(self, menu_bar): - menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) - menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) - - def setAlert(self, alert): - """Show a visual indicator - - @param alert: True if alert indicator show be shown""" - self.label.setAlert(alert) - - def updateAvatar(self, url): - """Update the avatar. - - @param url (unicode): image url - """ - self.avatar.setUrl(url) - - def updateNick(self, new_nick): - """Update the nickname. - - @param new_nick (unicode): new nickname to use - """ - self.label.updateNick(new_nick) - - def onClick(self, sender): - try: - self.parent.onClick(self.jid) - except AttributeError: - pass - else: - self.setAlert(False) - - class GroupPanel(VerticalPanel): def __init__(self, parent): @@ -240,94 +133,13 @@ return self._groups -class BaseContactsPanel(VerticalPanel): - """ContactList graphic representation - - Special features like popup menu panel or changing the contact states must be done in a sub-class. - """ - - def __init__(self, parent, handle_click=True, handle_menu=True): - """@param on_click (callable): click callback (used if ContactBox is created) - @param handle_menu (bool): if True, bind a popup menu to the avatar (used if ContactBox is created) - """ # FIXME - VerticalPanel.__init__(self) - self._parent = parent - self.host = parent.host - self._contacts = {} # entity jid to ContactBox map - self.click_listener = None - self.handle_menu = handle_menu - - if handle_click: - def cb(contact_jid): - self.host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) - self.onClick = cb - - def display(self, jids): - """Display a contact in the list. - - @param jids (list[jid.JID]): jids to display (the order is kept) - @param name (unicode): optional name of the contact - """ - # FIXME: we do a full clear and add boxes after, we should only remove recently hidden boxes and add new ones, and re-order - current = [box.jid for box in self.children if isinstance(box, ContactBox)] - if current == jids: - # the display doesn't change - return - self.clear() - for jid_ in jids: - assert isinstance(jid_, jid.JID) - box = self.getContactBox(jid_) - VerticalPanel.append(self, box) - - def isContactPresent(self, contact_jid): - """Return True if a contact is present in the panel""" - return contact_jid in self._contacts - - def getContacts(self): - return self._contacts - - def getContactBox(self, contact_jid): - """get the Contactbox of a contact - - if the Contactbox doesn't exists, it will be created - @param contact_jid (jid.JID): the contact - @return: ContactBox instance - """ - try: - return self._contacts[contact_jid.bare] - except KeyError: - box = ContactBox(self, contact_jid) - self._contacts[contact_jid.bare] = box - return box - - def updateAvatar(self, jid_, url): - """Update the avatar of the given contact - - @param jid_ (jid.JID): contact jid - @param url (unicode): image url - """ - try: - self.getContactBox(jid_).updateAvatar(url) - except TypeError: - pass - - def updateNick(self, jid_, new_nick): - """Update the avatar of the given contact - - @param jid_ (jid.JID): contact jid - @param new_nick (unicode): new nick of the contact - """ - try: - self.getContactBox(jid_).updateNick(new_nick) - except TypeError: - pass - - -class ContactsPanel(BaseContactsPanel): +class ContactsPanel(base_panels.ContactsPanel): """The contact list that is displayed on the left side.""" def __init__(self, parent): - BaseContactsPanel.__init__(self, parent, handle_click=True, handle_menu=True) + def on_click(contact_jid): + self.host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) + base_panels.ContactsPanel.__init__(self, parent, on_click=on_click, handle_menu=True) def setState(self, jid_, type_, state): """Change the appearance of the contact, according to the state