Mercurial > libervia-web
view browser_side/panels.py @ 19:e8e3704eb97f
Added basic chat panel
- the chat panel show history, timestamp, and nickname (pretty similar to primitivus and wix chat window)
- JID has be rewritten to work with pyjamas, and is now in browser_side directory
- a widget can now be selected: the message send in uniBox will be sent to it if there is no explicit target prefix ("@something")
- a basic status panel is added under the uniBox, but not used yet
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 16 Apr 2011 01:46:01 +0200 |
parents | 795d144fc1d2 |
children | 8f4b1a8914c3 |
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.VerticalPanel import VerticalPanel from pyjamas.ui.HorizontalPanel import HorizontalPanel from pyjamas.ui.ScrollPanel import ScrollPanel from pyjamas.ui.HTMLPanel import HTMLPanel from pyjamas.ui.Grid import Grid from pyjamas.ui.MenuBar import MenuBar from pyjamas.ui.MenuItem import MenuItem from pyjamas.ui.Label import Label from pyjamas.ui.DropWidget import DropWidget from pyjamas.ui.ClickListener import ClickHandler from pyjamas.ui import HasAlignment from pyjamas import Window from pyjamas import DOM from pyjamas.dnd import makeDraggable from pyjamas.ui.DragWidget import DragWidget, DragContainer from jid import JID from datetime import datetime from time import time 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 DropCell(DropWidget): """Cell in the middle grid which replace itself with the dropped widget on DnD""" def __init__(self): DropWidget.__init__(self) def onDragEnter(self, event): print "drag enter" self.addStyleName('dragover') DOM.eventPreventDefault(event) def onDragLeave(self, event): print "drag leave" self.removeStyleName('dragover') def onDragOver(self, event): DOM.eventPreventDefault(event) def _getCellAndRow(self, grid, event): """Return cell and row index where the event is occuring""" cell = grid.getEventTargetCell(event) row = DOM.getParent(cell) return (row.rowIndex, cell.cellIndex) def onDrop(self, event): print "Empty Panel: onDrop" dt = event.dataTransfer #'text', 'text/plain', and 'Text' are equivalent. try: item = dt.getData("text/plain") item_type = dt.getData("type") print "message: %s" % item print "type: %s" % item_type except: print "no message found" item=' ' item_type = None DOM.eventPreventDefault(event) if item_type=="GROUP": _new_panel = MicroblogPanel(self.host, item) _new_panel.setAcceptedGroup(item) elif item_type=="CONTACT": _contact = JID(item) _new_panel = ChatPanel(self.host, _contact) _new_panel.historyPrint() elif item_type=="CONTACT_TITLE": _new_panel = MicroblogPanel(self.host, accept_all=True) self.host.mpanels.remove(self) self.host.mpanels.append(_new_panel) print "DEBUG" grid = self.getParent() row_idx, cell_idx = self._getCellAndRow(grid, event) self.removeFromParent() if self.host.selected == self: self.host.select(None) grid.setWidget(row_idx, cell_idx, _new_panel) #FIXME: delete object ? Check the right way with pyjamas class EmptyPanel(DropCell, SimplePanel): """Empty dropable panel""" def __init__(self, host): SimplePanel.__init__(self) self.host = host _panel = HTMLPanel(" ") self.add(_panel) self.setHeight('100%') DropCell.__init__(self) class MicroblogEntry(SimplePanel): def __init__(self, body, author, timestamp): SimplePanel.__init__(self) _datetime = datetime.fromtimestamp(timestamp) panel = HTMLPanel("<div class='mb_entry_header'><span class='mb_entry_author'>%(author)s</span> on <span class='mb_entry_timestamp'>%(timestamp)s</span></div><div class='mb_entry_body'>%(body)s</div>" % {"author": author, "timestamp": _datetime, "body": body} ) panel.setStyleName('microblogEntry') self.add(panel) class MicroblogPanel(DropCell, ScrollPanel): def __init__(self,host, title=' ', accept_all=False): """Panel used to show microblog @param title: title of the panel @param accept_all: if true, show every message, without filtering jids""" self.host = host self.accept_all = accept_all title=title.replace('<','<').replace('>','>') self.accepted_groups = [] _class = ['mb_panel_header'] if title == ' ': _class.append('empty_header') ScrollPanel.__init__(self) self.vpanel = VerticalPanel() self.vpanel.add(HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title))) self.vpanel.setWidth('100%') self.setHeight('100%') self.setStyleName('microblogPanel') self.add(self.vpanel) DropCell.__init__(self) def addEntry(self, text, author=None, timestamp=None): """Add an entry to the panel @param text: main text of the entry @param author: who wrote the entry @param date: when the entry was written""" _entry = MicroblogEntry(text, author, timestamp) self.vpanel.insert(_entry,1) def setAcceptedGroup(self, group): """Set the group which can be displayed in this panel @param group: string of the group, or list of string """ if isinstance(group, list): self.accepted_groups.extend(group) else: self.accepted_groups.append(group) def isJidAccepted(self, jid): """Tell if a jid is actepted and show in this panel @param jid: jid @return: True if the jid is accepted""" if self.accept_all: return True for group in self.accepted_groups: if self.host.contactPanel.isContactInGroup(group, jid): return True return False class StatusPanel(HTMLPanel): def __init__(self, status=''): self.status = status HTMLPanel.__init__(self, self.__getContent()) def __getContent(self): return "<span class='status'>%(status)s</span>" % {'status':self.status} def changeStatus(self, new_status): self.status = new_status self.setHTML(self.__getContent()) class ChatText(HTMLPanel): def __init__(self, timestamp, nick, mymess, msg): _date = datetime.fromtimestamp(float(timestamp or time())) print "DEBUG" print timestamp print time() print _date _msg_class = ["chat_text_msg"] if mymess: _msg_class.append("chat_text_mymess") HTMLPanel.__init__(self, "<span class='chat_text_timestamp'>%(timestamp)s</span> <span class='chat_text_nick'>%(nick)s</span> <span class='%(msg_class)s'>%(msg)s</span>" % {"timestamp": _date.strftime("%H:%M"), "nick": "[%s]" % nick, "msg_class": ' '.join(_msg_class), "msg": msg} ) self.setStyleName('chatText') class ChatPanel(DropCell, ClickHandler, ScrollPanel): def __init__(self, host, target, type='one2one'): """Panel used for conversation (one 2 one or group chat) @param host: SatWebFrontend instance @param target: entity (JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room) @param type: one2one for simple conversation, group for MUC""" self.host = host if not target: print "ERROR: Empty target !" return self.target = target title="%s" % target.bare title.replace('<','<').replace('>','>') _class = ['mb_panel_header'] ScrollPanel.__init__(self) self.content = VerticalPanel() self.content.add(HTMLPanel("<div class='%s'>%s</div>" % (','.join(_class),title))) self.content.setWidth('100%') self.setHeight('100%') self.setStyleName('chatPanel') self.add(self.content) DropCell.__init__(self) ClickHandler.__init__(self) self.addClickListener(self) def onClick(self, sender, event): self.host.select(self) def setUserNick(self, nick): """Set the nick of the user, usefull for e.g. change the color of the user""" self.nick = nick def historyPrint(self, size=20): """Print the initial history""" def getHistoryCB(history): stamps=history.keys() stamps.sort() for stamp in stamps: self.printMessage(history[stamp][0], history[stamp][1], stamp) self.host.bridge.call('getHistory', getHistoryCB, self.host.whoami.bare, str(self.target), 20) def printMessage(self, from_jid, msg, timestamp=None): """Print message in chat window. Must be implemented by child class""" _jid=JID(from_jid) nick = _jid.node mymess = _jid.bare == self.host.whoami.bare #mymess = True if message comes from local user """if msg.startswith('/me '): self.printInfo('* %s %s' % (nick, msg[4:]),type='me') return""" self.content.add(ChatText(timestamp, nick, mymess, msg)) class MiddlePannel(HorizontalPanel): def __init__(self, host): self.host=host HorizontalPanel.__init__(self) self._left = self.host.contactPanel self._right = Grid(1,3) self._right.setWidth('100%') self._right.setHeight('100%') self.add(self._left) self.setCellWidth(self._left, "15%") self.add(self._right) self.setCellWidth(self._right, "85%") self.setHeight('100%') def changePanel(self, idx, panel): print "panel:",panel print "idx:",idx self._right.setWidget(0,idx,panel) 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() uni_box = host.uniBox status = host.statusPanel self.middle_panel = MiddlePannel(self.host) self.middle_panel.setWidth('100%') self.add(menu) self.add(uni_box) self.add(status) self.add(self.middle_panel) self.setCellHeight(menu, "5%") self.setCellHeight(uni_box, "5%") self.setCellVerticalAlignment(uni_box, HasAlignment.ALIGN_CENTER) self.setCellHorizontalAlignment(uni_box, HasAlignment.ALIGN_CENTER) self.setCellHeight(self.middle_panel, "90%") self.setCellWidth(self.middle_panel, "100%") self.setWidth("100%") self.setHeight("100%")