initial import of ussd-pad
[ussd-widget] / ussd-pad / src / opt / ussd-pad / ui / Window.py
diff --git a/ussd-pad/src/opt/ussd-pad/ui/Window.py b/ussd-pad/src/opt/ussd-pad/ui/Window.py
new file mode 100644 (file)
index 0000000..99a2f73
--- /dev/null
@@ -0,0 +1,397 @@
+from Widget import Widget
+from ui import try_rgba
+from Pixmap import Pixmap
+from Widget import Widget
+from utils.MiniXML import MiniXML
+import platforms
+from theme import theme
+
+import gtk
+import os
+
+
+class Window(Widget):
+    """
+    Base class for windows.
+    """
+
+    TYPE_TOPLEVEL = 0
+    TYPE_DIALOG = 1
+
+
+    EVENT_CLOSED = "event-closed"
+    
+
+    def __init__(self, win_type):
+        """
+        Creates a new window.
+        
+        @param win_type: type of window
+        """
+    
+        self.__type = win_type
+        self.__size = (0, 0)
+        self.__fixed = None
+    
+        Widget.__init__(self)
+    
+        if (self.__type == self.TYPE_TOPLEVEL):
+            if (platforms.PLATFORM in (platforms.MAEMO5, platforms.MER)):
+                import hildon
+                self.__window = hildon.StackableWindow()
+
+            elif (platforms.PLATFORM == platforms.MAEMO4):
+                import hildon
+                self.__window = hildon.Window()
+                self.__window.fullscreen()
+                
+            else:
+                self.__window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+                self.__window.set_default_size(800, 480)
+            
+        elif (self.__type == self.TYPE_DIALOG):
+            self.__window = gtk.Dialog()
+
+        self.__window.connect("configure-event", self.__on_configure)
+        self.__window.connect("expose-event", self.__on_expose)
+        self.__window.connect("button-press-event", self.__on_button_pressed)
+        self.__window.connect("button-release-event", self.__on_button_released)
+        self.__window.connect("motion-notify-event", self.__on_motion)
+        self.__window.connect("key-press-event", self.__on_key_pressed)
+        self.__window.connect("key-release-event", self.__on_key_released)
+        self.__window.connect("delete-event", self.__on_close_window)
+
+        
+        self.__window.set_events(gtk.gdk.BUTTON_PRESS_MASK |
+                                 gtk.gdk.BUTTON_RELEASE_MASK |
+                                 gtk.gdk.POINTER_MOTION_MASK |
+                                 gtk.gdk.POINTER_MOTION_HINT_MASK |
+                                 gtk.gdk.KEY_PRESS_MASK |
+                                 gtk.gdk.KEY_RELEASE_MASK)
+
+
+        self.set_visible(False)
+        try_rgba(self.__window)
+        self.__window.set_app_paintable(True)
+        self.__window.realize()
+
+        if (platforms.PLATFORM == platforms.MAEMO5):
+            self.__set_portrait_property("_HILDON_PORTRAIT_MODE_SUPPORT", 1)
+
+        """
+        if (platforms.PLATFORM in (platforms.MAEMO5, platforms.MER)):
+            # we need to notify Maemo5 that we want to use the volume keys
+            self.__window.window.property_change("_HILDON_ZOOM_KEY_ATOM",
+                                                 "XA_INTEGER", 32,
+                                                 gtk.gdk.PROP_MODE_REPLACE,
+                                                 [1])                
+        """
+
+        self.__fixed = gtk.Fixed()
+        self.__fixed.show()
+
+        if (self.__type == self.TYPE_TOPLEVEL):
+            self.__window.add(self.__fixed)
+        else:
+            self.__window.vbox.add(self.__fixed)
+        
+        self.__screen = None
+
+        """
+        # hide mouse cursor
+        if (hide_cursor):
+            pbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 8, 8)
+            pbuf.fill(0x00000000)
+            csr = gtk.gdk.Cursor(gtk.gdk.display_get_default(), pbuf, 0, 0)
+            self.__window.window.set_cursor(csr)
+            del pbuf
+        #end if
+        """
+                
+        self.set_window(self)
+
+
+    def get_gtk_window(self):
+        """
+        Returns the associated GtkWindow of this window.
+        
+        @return: GtkWindow object
+        """
+    
+        return self.__window
+
+
+    def __check_window_size(self):
+
+        if (self.__size != self.__window.get_size()):
+            w, h = self.__window.get_size()
+            self.__screen = Pixmap(self.__window.window)
+            self.set_screen(self.__screen)
+            self.__size = (w, h)
+            
+            Widget.set_size(self, w, h)
+            for c in self.get_children():
+                c.set_size(w, h)
+
+            self.render()
+
+
+    def __on_configure(self, src, ev):
+
+        self.__check_window_size()
+
+
+    def __on_expose(self, src, ev):
+    
+        if (self.__screen):
+            x, y, w, h = ev.area
+            self.__screen.restore(x, y, w, h)
+
+
+    def __on_close_window(self, src, ev):
+        
+        self.send_event(self.EVENT_CLOSED)
+        return True
+        
+
+    def __on_button_pressed(self, src, ev):
+
+        px, py = src.get_pointer()
+        self._handle_event(self.EVENT_BUTTON_PRESS, px, py)
+        return True
+
+        
+    def __on_button_released(self, src, ev):
+
+        px, py = src.get_pointer()
+        self._handle_event(self.EVENT_BUTTON_RELEASE, px, py)
+        return True
+        
+        
+    def __on_motion(self, src, ev):
+
+        px, py = src.get_pointer()
+        self._handle_event(self.EVENT_MOTION, px, py)
+        return True
+
+
+    def __on_key_pressed(self, src, ev):
+    
+        keyval = ev.keyval
+        c = gtk.gdk.keyval_to_unicode(keyval)
+        if (c > 31):
+            key = unichr(c)
+        else:
+            key = gtk.gdk.keyval_name(keyval)
+
+        self.send_event(self.EVENT_KEY_PRESSED, key)
+        
+        # kill queued events
+        if (key in ["Up", "Down", "Left", "Right"]):
+            while (True):
+                e = gtk.gdk.event_get()
+                if (not e): break
+
+        return True
+
+
+    def __on_key_released(self, src, ev):
+
+        keyval = ev.keyval
+        c = gtk.gdk.keyval_to_unicode(keyval)
+        if (c > 31):
+            key = unichr(c)
+        else:
+            key = gtk.gdk.keyval_name(keyval)
+
+        self.send_event(self.EVENT_KEY_RELEASED, key)
+                
+        return True
+
+
+    def connect_closed(self, cb, *args):
+    
+        self._connect(self.EVENT_CLOSED, cb, *args)
+
+
+    def get_pos(self):
+    
+        return self.__window.window.get_position()
+        
+        
+    def get_screen_pos(self):
+    
+        return (0, 0)
+
+
+    def set_pos(self, x, y):
+    
+        Widget.set_pos(self, 0, 0)
+        #self.__window.move(x, y)
+        
+        
+    def set_size(self, w, h):
+    
+        Widget.set_size(self, w, h)
+        #self.__window.set_size_request(w, h)
+        self.__window.resize(w, h)
+
+
+    def get_size(self):
+
+        w, h = self.__window.get_size()
+        return (w, h)
+
+
+    def _visibility_changed(self):
+    
+        if (self.is_visible()):
+            self.__window.show()
+            self.render()
+        else:
+            self.__window.hide()
+
+
+
+    def put(self, child, x, y):
+    
+        if (not self.__fixed):
+            self.__fixed = gtk.Fixed()
+            self.__fixed.show()
+            self.__window.add(self.__fixed)
+    
+        self.__fixed.put(child, x, y)
+        
+        
+    def move(self, child, x, y):
+        assert self.__fixed
+        
+        self.__fixed.move(child, x, y)
+        
+        
+    def present(self):
+    
+        self.__window.present()
+
+
+    def iconify(self):
+    
+        self.__window.iconify()
+
+
+    def set_fullscreen(self, v):
+    
+        if (v):
+            self.__window.fullscreen()
+        else:
+            self.__window.unfullscreen()
+
+
+    def set_title(self, title):
+    
+        self.__window.set_title(title)
+
+
+    def __set_portrait_property(self, prop, value):
+
+        self.__window.window.property_change(prop, "CARDINAL", 32,
+                                             gtk.gdk.PROP_MODE_REPLACE,
+                                             [value])
+    
+    
+    def set_portrait_mode(self, v):
+        """
+        Switches between landscape and portrait mode on supported platforms.
+        @since: 2009.09
+        """
+        
+        if (platforms.PLATFORM == platforms.MAEMO5):
+            if (v):
+                self.__set_portrait_property("_HILDON_PORTRAIT_MODE_SUPPORT", 1)
+                self.__set_portrait_property("_HILDON_PORTRAIT_MODE_REQUEST", 1)
+            else:
+                self.__set_portrait_property("_HILDON_PORTRAIT_MODE_SUPPORT", 1)
+                self.__set_portrait_property("_HILDON_PORTRAIT_MODE_REQUEST", 0)
+
+        elif (platforms.PLATFORM == platforms.MAEMO4):
+            if (v):
+                os.system("xrandr -o left")
+            else:
+                os.system("xrandr -o normal")
+
+        #end if
+
+
+    def set_menu_xml(self, xml, bindings):
+        """
+        Sets the window menu from a XML description.
+        @since 2009.11.19
+        
+        @param xml: XML description of the menu
+        @param bindings: dictionary mapping XML node IDs to callback handlers
+        """
+    
+        if (platforms.PLATFORM != platforms.MAEMO5): return
+        import hildon
+
+        dom = MiniXML(xml).get_dom()        
+        menu = hildon.AppMenu()
+        
+        for node in dom.get_children():
+            name = node.get_name()
+            if (name == "item"):
+                item_id = node.get_attr("id")
+                item_label = node.get_attr("label")
+                callback = bindings.get(item_id)
+
+                btn = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
+                btn.set_label(item_label)
+                if (callback):
+                    btn.connect("clicked",
+                                lambda x, cb:cb(), callback)
+                menu.append(btn)
+
+            elif (name == "choice"):
+                choice_id = node.get_attr("id")
+                choice_selected = int(node.get_attr("selected") or "0")
+                callback = bindings.get(choice_id)
+                group = None
+                buttons = []
+                cnt = 0
+                for option in node.get_children():
+                    item_label = option.get_attr("label")
+                    item_icon = option.get_attr("icon")
+                    
+                    btn = hildon.GtkRadioButton(gtk.HILDON_SIZE_AUTO, group)
+                    btn.set_mode(False)
+                    
+                    if (item_label):
+                        btn.set_label(item_label)
+                    if (item_icon):
+                        img = gtk.Image()
+                        img.set_from_pixbuf(getattr(theme, item_icon))
+                        btn.set_image(img)
+
+                    if (cnt == choice_selected):
+                        btn.set_active(True)
+
+                    menu.add_filter(btn)
+                    group = btn
+                    buttons.append(btn)
+                    cnt += 1
+                #end for
+                
+                cnt = 0
+                for btn in buttons:
+                    if (callback):
+                        btn.connect("clicked",
+                                    lambda x, i, cb:cb(i), cnt, callback)
+                    cnt += 1
+                #end for
+            #end if
+        #end for
+
+        menu.show_all()            
+        self.__window.set_app_menu(menu)
+