view libervia.py @ 1:0a7c685faa53

ContactPanel: first draft
author Goffi <goffi@goffi.org>
date Mon, 31 Jan 2011 20:31:25 +0100
parents 140cec48224a
children 669c531a857e
line wrap: on
line source

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Libervia: a Salut à Toi frontend
Copyright (C) 2011  Jérôme Poisson (goffi@goffi.org)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

import pyjd # this is dummy in pyjs
from pyjamas.ui.SimplePanel import SimplePanel
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.Label import Label
from pyjamas.ui import HasAlignment
from pyjamas.ui.MenuBar import MenuBar
from pyjamas.ui.MenuItem import MenuItem
from pyjamas import Window
from pyjamas.ui.AutoComplete import AutoCompleteTextBox
from pyjamas.JSONService import JSONProxy
from register import RegisterPanel, RegisterBox
from pyjamas import DOM


class LiberviaJsonProxy(JSONProxy):
    def __init__(self, *args, **kwargs):
        JSONProxy.__init__(self, *args, **kwargs)
        self.handler=self
        self.cb={}

    def call(self, method, cb, *args):
        self.cb[method] = cb
        self.callMethod(method,args)

    def onRemoteResponse(self, response, request_info):
        if self.cb.has_key(request_info.method):
            self.cb[request_info.method](response)
            del self.cb[request_info.method]
        
    def onRemoteError(self, code, errobj, request_info):
        if code != 0:
            Window.alert("Internal server error")
        else:
            if isinstance(errobj['message'],dict):
                Window.alert("Error %s: %s" % (errobj['message']['faultCode'], errobj['message']['faultString']))
            else:
                Window.alert("Error: %s" % errobj['message'])

class RegisterCall(LiberviaJsonProxy):
    def __init__(self):
        LiberviaJsonProxy.__init__(self, "/register_api",
                        ["isRegistered","isConnected","connect"])
        self.handler=self
        self.cb={}

class BrigeCall(LiberviaJsonProxy):
    def __init__(self):
        LiberviaJsonProxy.__init__(self, "/json_api",
                        ["getContacts"])

class MenuCmd:

    def __init__(self, object, handler):
        self._object  = object
        self._handler = handler

    def execute(self):
        handler = getattr(self._object, self._handler)
        handler()

class Menu(SimplePanel):

    def __init__(self):
        SimplePanel.__init__(self)

        menu_general = MenuBar(vertical=True)
        menu_general.addItem("Properties", MenuCmd(self, "onProperties"))

        menu_games = MenuBar(vertical=True)
        menu_games.addItem("Tarot", MenuCmd(self, "onTarotGame"))
        menu_games.addItem("Xiangqi", MenuCmd(self, "onXiangqiGame"))

        menubar = MenuBar(vertical=False)
        menubar.addItem(MenuItem("General", menu_general))
        menubar.addItem(MenuItem("Games", True, menu_games))
        self.add(menubar)

    def onProperties(self):
        Window.alert("Properties selected")

    def onTarotGame(self):
        Window.alert("Tarot selected")

    def onXiangqiGame(self):
        Window.alert("Xiangqi selected")

class MagicBox(AutoCompleteTextBox):

    def __init__(self):
        AutoCompleteTextBox.__init__(self)

    def addKey(self, key):
        self.getCompletionItems().completions.append(key)

class GroupLabel(Label):
    def __init__(self, group):
        Label.__init__(self, group)
        self.group = group
        self.setStyleName('group')

class ContactLabel(Label):
    def __init__(self, jid, name=None):
        if not name:
            name=jid
        Label.__init__(self, name)
        self.jid=jid
        self.setStyleName('contact')

class GroupList(VerticalPanel):

    def __init__(self, parent):
        VerticalPanel.__init__(self)
        self._parent = parent

    def add(self, group):
        _item = GroupLabel(group)
        _item.addMouseListener(self._parent)
        DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer")
        VerticalPanel.add(self, _item)
    
class ContactList(VerticalPanel):

    def __init__(self):
        VerticalPanel.__init__(self)
        self.contacts=[]

    def __iter__(self):
        return self.contacts.__iter__()
    
    def add(self, jid, name=None):
        _item = ContactLabel(jid, name)
        DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer")
        VerticalPanel.add(self, _item)
        self.contacts.append(_item)

class ContactPanel(SimplePanel):
    """Manage the contacts and groups"""
    
    def __init__(self, host):
        SimplePanel.__init__(self)
        self.host = host
        self.groups={}

        self.vPanel = VerticalPanel()
        _title = Label('Contacts')
        _title.setStyleName('contactTitle')

        self._contactList = ContactList()
        self._contactList.setStyleName('contactList')
        self._groupList = GroupList(self)
        self._groupList.setStyleName('groupList')
        
        self.vPanel.add(_title)
        self.vPanel.add(self._groupList)
        self.vPanel.add(self._contactList)
        self.add(self.vPanel)
        self.setStyleName('contactBox')

    def addContact(self, jid, attributes, groups):
        """Add a contact to the panel
        @param jid: jid
        @attributes: cf SàT Bridge API's newContact
        @param groups: list of groups"""
        for group in groups:
            if not self.groups.has_key(group):
                self.groups[group] = set()
                self._groupList.add(group)
                self.host.magicBox.addKey("@%s: " % group)
            self.groups[group].add(jid)
        self._contactList.add(jid)

    def onMouseMove(self, sender, x, y):
        pass
        
    def onMouseDown(self, sender, x, y):
        pass

    def onMouseUp(self, sender, x, y):
        pass

    def onMouseEnter(self, sender):
        if isinstance(sender, GroupLabel):
            for contact in self._contactList:
                if contact.jid in self.groups[sender.group]:
                    contact.addStyleName("selected")
    
    def onMouseLeave(self, sender):
        if isinstance(sender, GroupLabel):
            for contact in self._contactList:
                if contact.jid in self.groups[sender.group]:
                    contact.removeStyleName("selected")

class MiddlePannel(HorizontalPanel):
    
    def __init__(self,host):
        self.host=host
        HorizontalPanel.__init__(self)
        self.add(self.host.contactPanel)

class MainPanel(VerticalPanel):

    def __init__(self, host):
        self.host=host
        VerticalPanel.__init__(self)

        self.setHorizontalAlignment(HasAlignment.ALIGN_LEFT)
        self.setVerticalAlignment(HasAlignment.ALIGN_TOP)

        menu = Menu()
        magic_box = host.magicBox
        middle_panel = MiddlePannel(self.host)

        self.add(menu)
        self.add(magic_box)
        self.add(middle_panel)
        
        self.setCellHeight(menu, "5%")
        self.setCellHeight(magic_box, "5%")
        self.setCellVerticalAlignment(magic_box, HasAlignment.ALIGN_CENTER)
        self.setCellHorizontalAlignment(magic_box, HasAlignment.ALIGN_CENTER)
        self.setCellHeight(middle_panel, "90%")

        self.setWidth("100%")
        self.setHeight("100%")

class SatWebFrontend:
    def onModuleLoad(self):
        self.magicBox = MagicBox()
        self.contactPanel = ContactPanel(self)
        self.panel = MainPanel(self)
        self._dialog = None
        RootPanel().add(self.panel)
        self._register = RegisterCall()
        self._register.call('isRegistered',self._isRegisteredCB)

    def _isRegisteredCB(self, registered):
        if not registered:
            self._dialog = RegisterBox(self.logged,centered=True)
            self._dialog.show()
        else:
            self._register.call('isConnected', self._isConnectedCB)

    def _isConnectedCB(self, connected):
        if not connected:
            self._register.call('connect',self.logged)
        else:
            self.logged()

    def logged(self):
        if self._dialog:
            self._dialog.hide()
            del self._dialog # don't work if self._dialog is None
        
        #it's time to fill the page
        bridge = BrigeCall()
        bridge.call('getContacts', self._getContactsCB)

    def _getContactsCB(self, contacts_data):
        for contact in contacts_data:
            jid, attributes, groups = contact
            self.contactPanel.addContact(jid, attributes, groups)


if __name__ == '__main__':
    pyjd.setup("http://localhost:8080/libervia.html")
    app = SatWebFrontend()
    app.onModuleLoad()
    pyjd.run()