# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.

import pgm, gobject
from pgm.graph.group import Group
from pgm.graph.image import Image
from pgm.graph.text import Text
from pgm.widgets.button import Button
from pgm.timing.implicit import AnimatedObject

class PopupButton(Button):
    """
    This is a simple button that shows two different states with different
    images.

    @ivar selected_image:   the Image that gets shown, when the button is
                            selected
    @type selected_image:   L{pgm.graph.image.Image}

    @ivar unselected_image: the Image that gets shown, when the button is not
                            selected
    @type unselected_image: L{pgm.graph.image.Image}
    """
    
    def __init__(self):
        super(PopupButton, self).__init__()
        self.selected_image = Image()
        self.add(self.selected_image)
        self._ani_selected_image = AnimatedObject(self.selected_image)

        self.selected_image.visible = True
        self.selected_image.opacity = 0
        self.selected_image.bg_color = (0,0,0,0)
        self.selected_image.connect('clicked', self.clicked)

        self.unselected_image = Image()
        self.add(self.unselected_image)
        self._ani_unselected_image = AnimatedObject(self.unselected_image)

        self.unselected_image.visible = True
        self.unselected_image.opacity = 255
        self.unselected_image.bg_color = (0,0,0,0)
        self.unselected_image.connect('clicked', self.clicked)
    
        animation_settings = {'duration' : 250}

        # set the animation settings
        self._ani_unselected_image.setup_next_animations(**animation_settings)
        self._ani_selected_image.setup_next_animations(**animation_settings)

    def focus__set(self, focus):
        if focus:
            self._ani_unselected_image.opacity = 0
            self._ani_selected_image.opacity = 255
        else:
            self._ani_unselected_image.opacity = 255
            self._ani_selected_image.opacity = 0

        super(PopupButton, self).focus__set(focus)

class Popup(Group):
    """
    This is a simple PopUp-Image. It has a Background-Image, a
    Text and a List of L{Button}s.
    """

    def __init__(self):
        Group.__init__(self)

        # set up the basics
        self.text = Text()
        self.text.bg_color = (0, 0, 0, 0)
        self.text.font_color = (255, 0, 0, 255)
        self.background = Image()
        self.add(self.background)
        self.add(self.text)

        self._buttons = []
        self._cbs = []
        self._idx = -1
        self.txt_top_offset = 0.1
        self.btn_bottom_offset = 0.1
        self.btn_top_offset = 0.6
        self.left_offset = 0.1
        self.right_offset = 0.1
        self.lines = 0

    def append_button(self, btn):
        assert type(btn), Button
        #btn.visible = True
        self.add(btn)
        btn.connect('focus', self._got_focus)
        self._buttons.append( btn )
        self._update_focus()
        if self.visible:
            self._regenerate()

    def _got_focus(self, btn, value):
        if not value:
            return

        for button in self._buttons:
            if btn is button:
                continue
            
            button.focus = False

    def trigger(self):
        if not self._idx >= 0 or len(self._buttons) == 0:
            return
        btn = self._buttons[self._idx]
        btn.clicked(btn, 0,0,0,pgm.BUTTON_LEFT,0)
        
    def pop(self, idx=-1):
        btn = self._buttons.pop(idx)
        self.remove(btn)
        self._update_focus()
        self._regenerate()
        return btn, cbs, args

    def size__set(self, size):
        self.background.size = size
        self._regenerate()

    def size__get(self):
        return self.background.size

    def width__set(self, width):
        self.background.width = width
        self._regenerate()

    def width__get(self):
        return self.background.width
 
    def height__set(self, height):
        self.background.height = height
        self._regenerate()

    def height__get(self):
        return self.background.height

    def next(self):
        new_idx = self._idx +1
        if new_idx >= len(self._buttons):
            return

        self._buttons[self._idx].focus = False
        self._idx = new_idx
        self._update_focus()

    def prev(self):
        new_idx = self._idx -1
        if new_idx < 0:
            return

        self._buttons[self._idx].focus = False
        self._idx = new_idx
        self._update_focus()

    def _update_focus(self):
        if len(self._buttons):
            if self._idx == -1:
                self._idx = 0
            elif self._idx >= len(self._buttons):
                self._idx = len(self._buttons) -1 
            self._buttons[self._idx].focus = True

    def visible__set(self, value):
        old_val = self.visible
        super(Popup, self).visible__set(value)

        if value and not old_val:
            # we should regenerate, because we got visible
            self._regenerate()

    def _regenerate(self):
        self.background.visible = True

        # GLOBAL calculation

        # calculte the relative offsets to real values:
        left_offset = self.background.width * self.left_offset
        right_offset = self.background.width * self.right_offset

        top_offset = self.background.height * self.txt_top_offset
        btn_top_offset = self.background.height * self.btn_top_offset
        bottom_offset  = self.background.height * self.btn_bottom_offset

        # the width of the writeable text
        width =  self.background.width - left_offset - right_offset

        self.text.position = (left_offset, top_offset, 0)
        if self.lines and self.lines > 0:
            # space for known number of lines
            self.text.font_height = (btn_top_offset - top_offset) / self.lines
        self.text.size = (width, btn_top_offset - top_offset)
        self.text.visible = True

        # the height for the space of the buttons
        height = self.background.height - btn_top_offset - bottom_offset

        # the number of buttons
        numb = len(self._buttons)

        # calculate the size for each button
        square_size = min(height, (width / (numb+1)))

        # calculate the space between the buttons
        space = (width - (numb * square_size)) / (numb +1 )

        # calculate the offset to the top
        top = btn_top_offset + height / 2 - square_size / 2

        # calculate the first gap to the left
        cur_w = left_offset + space

        for btn in self._buttons:
            # resize every button
            btn.size = (square_size, square_size)
            # set the position in line
            btn.position = (cur_w, top, 0)
            # visibility would be great :D     
            btn.visible = True
            # calculate the next position from the left
            cur_w += square_size + space
            btn.visible = True


 
        
if __name__ == "__main__":
    
    def on_delete(viewport, event):
        pgm.main_quit()

    def deed(widget):
        widget.visible = not widget.visible

    ysel =  'theme/yes_selected.png'
    yunsel = 'theme/yes.png'

    nsel =  'theme/no_selected.png'
    nunsel = 'theme/no.png'

    def on_key_press(viewport, event, widget):
        if event.type == pgm.KEY_PRESS:
            # quit on q or ESC
            if event.keyval in (pgm.keysyms.q, pgm.keysyms.Escape):
                pgm.main_quit()
            elif event.keyval == pgm.keysyms.Right:
                widget.next()
            elif event.keyval == pgm.keysyms.Left:
                widget.prev()
            elif event.keyval == pgm.keysyms.Return:
                widget.trigger()
            elif event.keyval is pgm.keysyms.y:
                btn = PopupButton()
                btn.unselected_image.set_from_file(yunsel)
                btn.selected_image.set_from_file(ysel)
                widget.append_button(btn, deed, widget)
            elif event.keyval is pgm.keysyms.n:
                btn = PopupButton()
                btn.unselected_image.set_from_file(nunsel)
                btn.selected_image.set_from_file(nsel)
                widget.append_button(btn, deed, widget)

            elif event.keyval is pgm.keysyms.minus:
                widget.pop()

            elif event.keyval == pgm.keysyms.Up:
                widget.background.width += 0.2

            elif event.keyval == pgm.keysyms.Down:
                widget.background.width -= 0.2

            elif event.keyval == pgm.keysyms.p:
                widget.lines += 1
                print widget.lines

            elif event.keyval == pgm.keysyms.o:
                widget.lines -= 1
                print widget.lines

    # OpenGL viewport creation
    factory = pgm.ViewportFactory('opengl')
    gl = factory.create()
    gl.title = 'Popup Widget'

    # Canvas and image drawable creation
    canvas = pgm.Canvas()
    
    # Bind the canvas to the OpenGL viewport
    gl.set_canvas(canvas)
    gl.show()

    test_text = "A new Version of Elisa is available.\n" \
                "Do you want to upgrade?"

    def printer(widget, x,y,z, button, time, value):
        print value

    pop = Popup()
    pop.background.bg_color = (0, 0, 0, 0)
    pop.background.set_from_file("theme/bg_popup.png")
    pop.background.layout = pgm.IMAGE_FILLED
    pop.text.label = test_text
    pop.text.fg_color = 255, 255, 255, 255
    # add the buttons
    ybtn = PopupButton()
    ybtn.selected_image.set_from_file(ysel)
    ybtn.unselected_image.set_from_file(yunsel)
    ybtn.connect('clicked', printer, 'yes')
    pop.append_button(ybtn)

    nbtn = PopupButton()
    nbtn.selected_image.set_from_file(nsel)
    nbtn.unselected_image.set_from_file(nunsel)
    nbtn.connect('clicked', printer, 'no')
    pop.append_button(nbtn)

    pop.canvas = canvas
    pop.visible = True
    pop.lines = 3

    pop.position = (.5, .5, 0)
    pop.width = 3.
    pop.height = 1.5


    # Let's start a mainloop
    gl.connect('key-press-event', on_key_press, pop)
    gl.connect('delete-event', on_delete)
    pgm.main()   
