comparison browser_side/panels.py @ 279:2d6bd975a72d

browser_side: set your own presence status and display those of others
author souliane <souliane@mailoo.org>
date Sat, 23 Nov 2013 14:46:03 +0100
parents aebb96bfa8d1
children ae3ec654836d
comparison
equal deleted inserted replaced
278:4517978a2e7e 279:2d6bd975a72d
35 from pyjamas.ui.StackPanel import StackPanel 35 from pyjamas.ui.StackPanel import StackPanel
36 from pyjamas.ui.ClickListener import ClickHandler 36 from pyjamas.ui.ClickListener import ClickHandler
37 from pyjamas.ui.KeyboardListener import KEY_ENTER, KEY_UP, KEY_DOWN 37 from pyjamas.ui.KeyboardListener import KEY_ENTER, KEY_UP, KEY_DOWN
38 from pyjamas.ui.Event import BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT 38 from pyjamas.ui.Event import BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT
39 from pyjamas.ui.MouseListener import MouseHandler 39 from pyjamas.ui.MouseListener import MouseHandler
40 from pyjamas.ui.ListBox import ListBox
40 from pyjamas.Timer import Timer 41 from pyjamas.Timer import Timer
41 from pyjamas import DOM 42 from pyjamas import DOM
42 from card_game import CardPanel 43 from card_game import CardPanel
43 from radiocol import RadioColPanel 44 from radiocol import RadioColPanel
44 from menu import Menu 45 from menu import Menu
45 from jid import JID 46 from jid import JID
46 from tools import html_sanitize, addURLToText, inlineRoot 47 from tools import html_sanitize, addURLToText, inlineRoot, setPresenceStyle
47 from datetime import datetime 48 from datetime import datetime
48 from time import time 49 from time import time
49 import dialog 50 import dialog
50 import base_widget 51 import base_widget
51 from richtext import RichTextEditor 52 from richtext import RichTextEditor
52 from plugin_xep_0085 import ChatStateMachine 53 from plugin_xep_0085 import ChatStateMachine
53 from pyjamas import Window 54 from pyjamas import Window
54 from __pyjamas__ import doc 55 from __pyjamas__ import doc
55 from sat_frontends.tools.games import SYMBOLS 56 from sat_frontends.tools.games import SYMBOLS
57 from sat_frontends import constants
58 from pyjamas.ui.ContextMenuPopupPanel import ContextMenuPopupPanel
59
60
61 const = constants.Const # to directly import 'const' doesn't work
56 62
57 63
58 class UniBoxPanel(HorizontalPanel): 64 class UniBoxPanel(HorizontalPanel):
59 """Panel containing the UniBox""" 65 """Panel containing the UniBox"""
60 66
585 if self.host.contact_panel.isContactInGroup(group, jid): 591 if self.host.contact_panel.isContactInGroup(group, jid):
586 return True 592 return True
587 return False 593 return False
588 594
589 595
590 class StatusPanel(HTMLPanel, ClickHandler): 596 class StatusPanel(HTMLPanel):
591 def __init__(self, host, status=''): 597 def __init__(self, host, status=''):
592 self.host = host 598 self.host = host
593 self.status = status or '&nbsp;' 599 self.status = status or '&nbsp;'
594 HTMLPanel.__init__(self, self.__getContent()) 600 HTMLPanel.__init__(self, self.__getContent())
595 self.setStyleName('statusPanel') 601 self.setStyleName('statusPanel')
596 ClickHandler.__init__(self)
597 self.addClickListener(self)
598 602
599 def __getContent(self): 603 def __getContent(self):
600 return "<span class='status'>%(status)s</span>" % {'status': html_sanitize(self.status)} 604 return "<span class='status'>%(status)s</span>" % {'status': html_sanitize(self.status)}
601 605
602 def changeStatus(self, new_status): 606 def changeStatus(self, new_status):
603 self.status = new_status or '&nbsp;' 607 self.status = new_status or '&nbsp;'
604 self.setHTML(self.__getContent()) 608 self.setHTML(self.__getContent())
609
610
611 class PresenceStatusPanel(HorizontalPanel, ClickHandler):
612
613 def __init__(self, host, presence="", status=""):
614 self.host = host
615 HorizontalPanel.__init__(self, Width='100%')
616 self.presence_button = Label(u"◉")
617 self.presence_button.setStyleName("presence-button")
618 self.status_panel = StatusPanel(host, status=status)
619 self.setPresence(presence)
620 entries = {}
621 for value in const.PRESENCE.keys():
622 entries.update({const.PRESENCE[value]: {"value": value}})
623
624 def callback(sender, key):
625 self.setPresence(entries[key]["value"]) # order matters
626 self.host.send([("STATUS", None)], self.status_panel.status)
627
628 self.presence_list = PopupMenuPanel(entries, callback=callback, style={"menu": "gwt-ListBox"})
629 self.presence_list.registerClickSender(self.presence_button)
630
631 panel = HorizontalPanel()
632 panel.add(self.presence_button)
633 panel.add(self.status_panel)
634 panel.setStyleName("marginAuto")
635 self.add(panel)
636
637 ClickHandler.__init__(self)
638 self.addClickListener(self)
639
640 def getPresence(self):
641 return self.presence
642
643 def setPresence(self, presence):
644 status = self.status_panel.status
645 if not status.strip() or status == "&nbsp;" or status == const.PRESENCE[self.presence]:
646 self.changeStatus(const.PRESENCE[presence])
647 self.presence = presence
648 setPresenceStyle(self.presence_button, self.presence)
649
650 def changeStatus(self, new_status):
651 self.status_panel.changeStatus(new_status)
605 652
606 def onClick(self, sender): 653 def onClick(self, sender):
607 # As status is the default target of uniBar, we don't want to select anything if click on it 654 # As status is the default target of uniBar, we don't want to select anything if click on it
608 self.host.setSelected(None) 655 self.host.setSelected(None)
609 656
976 """This implementation of a popup menu (context menu) allow you to assign 1023 """This implementation of a popup menu (context menu) allow you to assign
977 two special methods which are common to all the items, in order to hide 1024 two special methods which are common to all the items, in order to hide
978 certain items and also easily define their callbacks. The menu can be 1025 certain items and also easily define their callbacks. The menu can be
979 bound to any of the mouse button (left, middle, right). 1026 bound to any of the mouse button (left, middle, right).
980 """ 1027 """
981 def __init__(self, entries, hide=None, callback=None, vertical=True, item_style="popupMenuItem", menu_style=None, **kwargs): 1028 def __init__(self, entries, hide=None, callback=None, vertical=True, style={}, **kwargs):
982 """ 1029 """
983 @param entries: a dict of dicts, where each sub-dict is representing 1030 @param entries: a dict of dicts, where each sub-dict is representing
984 one menu item: the sub-dict key can be used as the item text and 1031 one menu item: the sub-dict key can be used as the item text and
985 description, but optional "title" and "desc" entries would be used 1032 description, but optional "title" and "desc" entries would be used
986 if they exists. The sub-dicts may be extended later to do 1033 if they exists. The sub-dicts may be extended later to do
987 more complicated stuff or overwrite the common methods. 1034 more complicated stuff or overwrite the common methods.
988 @param hide: function with 2 args: widget, key as string and 1035 @param hide: function with 2 args: widget, key as string and
989 returns True if that item should be hidden from the context menu. 1036 returns True if that item should be hidden from the context menu.
990 @param callback: function with 2 args: widget, key as string 1037 @param callback: function with 2 args: sender, key as string
991 @param vertical: True or False, to set the direction 1038 @param vertical: True or False, to set the direction
992 @param item_style: alternative CSS class for the menu items 1039 @param item_style: alternative CSS class for the menu items
993 @param menu_style: supplementary CSS class for the sender widget 1040 @param menu_style: supplementary CSS class for the sender widget
994 """ 1041 """
995 PopupPanel.__init__(self, autoHide=True, **kwargs) 1042 PopupPanel.__init__(self, autoHide=True, **kwargs)
996 self._entries = entries 1043 self._entries = entries
997 self._hide = hide 1044 self._hide = hide
998 self._callback = callback 1045 self._callback = callback
999 self.vertical = vertical 1046 self.vertical = vertical
1000 self.item_style = item_style 1047 self.style = {"selected": None, "menu": "recipientTypeMenu", "item": "popupMenuItem"}
1001 self.menu_style = menu_style 1048 self.style.update(style)
1002 self._senders = {} 1049 self._senders = {}
1003 1050
1004 def _show(self, sender): 1051 def _show(self, sender):
1005 """Popup the menu relative to this sender's position. 1052 """Popup the menu relative to this sender's position.
1006 @param sender: the widget that has been clicked 1053 @param sender: the widget that has been clicked
1007 """ 1054 """
1008 menu = VerticalPanel() if self.vertical is True else HorizontalPanel() 1055 menu = VerticalPanel() if self.vertical is True else HorizontalPanel()
1009 menu.setStyleName("recipientTypeMenu") 1056 menu.setStyleName(self.style["menu"])
1010 1057
1011 def button_cb(item): 1058 def button_cb(item):
1012 """You can not put that method in the loop and rely 1059 """You can not put that method in the loop and rely
1013 on _key, because it is overwritten by each step. 1060 on _key, because it is overwritten by each step.
1014 You can rely on item.key instead, which is copied 1061 You can rely on item.key instead, which is copied
1024 if self._hide is not None and self._hide(sender=sender, key=_key) is True: 1071 if self._hide is not None and self._hide(sender=sender, key=_key) is True:
1025 continue 1072 continue
1026 title = entry["title"] if "title" in entry.keys() else _key 1073 title = entry["title"] if "title" in entry.keys() else _key
1027 item = Button(title, button_cb) 1074 item = Button(title, button_cb)
1028 item.key = _key 1075 item.key = _key
1029 item.setStyleName(self.item_style) 1076 item.setStyleName(self.style["item"])
1030 item.setTitle(entry["desc"] if "desc" in entry.keys() else title) 1077 item.setTitle(entry["desc"] if "desc" in entry.keys() else title)
1031 menu.add(item) 1078 menu.add(item)
1032 if len(menu.getChildren()) == 0: 1079 if len(menu.getChildren()) == 0:
1033 return 1080 return
1034 self.add(menu) 1081 self.add(menu)
1038 else: 1085 else:
1039 x = sender.getAbsoluteLeft() 1086 x = sender.getAbsoluteLeft()
1040 y = sender.getAbsoluteTop() + sender.getOffsetHeight() 1087 y = sender.getAbsoluteTop() + sender.getOffsetHeight()
1041 self.setPopupPosition(x, y) 1088 self.setPopupPosition(x, y)
1042 self.show() 1089 self.show()
1043 if self.menu_style: 1090 if self.style["selected"]:
1044 sender.addStyleDependentName(self.menu_style) 1091 sender.addStyleDependentName(self.style["selected"])
1045 1092
1046 def _onHide(popup): 1093 def _onHide(popup):
1047 if hasattr(self, "menu_style") and self.menu_style is not None: 1094 if self.style["selected"]:
1048 sender.removeStyleDependentName(self.menu_style) 1095 sender.removeStyleDependentName(self.style["selected"])
1049 return PopupPanel.onHideImpl(self, popup) 1096 return PopupPanel.onHideImpl(self, popup)
1050 1097
1051 self.onHideImpl = _onHide 1098 self.onHideImpl = _onHide
1052 1099
1053 def registerClickSender(self, sender, button=BUTTON_LEFT): 1100 def registerClickSender(self, sender, button=BUTTON_LEFT):