# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

# prepare Python environment - Add the path of this class

# pyUNO program itself
import uno
import unohelper

# UNO GUI toolkit
from com.sun.star.awt.WindowClass import TOP
from com.sun.star.awt.PushButtonType import STANDARD as standard
from com.sun.star.awt.TextAlign import LEFT as left

# used UNO listeners
from com.sun.star.awt import XActionListener

class MsgBox(unohelper.Base):
    """Inspect UNO object, link to sdk and recursive calls"""

    def __init__(self, aContext):
        """acontext : a Valid UNO context
        """

        self.VERSION = '0.1'
        self.ctx = aContext
        self.smgr = aContext.ServiceManager
        # UI Dialog object
        self.dialog=None
        # List of opened Listeners
        self.lst_listeners={}
        #UI parameters
        self.ButtonSize = 50
        self.boxSize = 200
        self.lineHeight = 10
        self.fromBroxSize = False
        self.numberOfLines = -1

        self.Buttons = []
        self.Response = ''

        return

    #####################################################
    #                 GUI definition                    #
    #####################################################
    def _createBox(self):
        """Create the Box"""

        # computes parameters of the message dialog
        if self.numberOfLines == -1:
            #calculate
            numberOfLines = len(self.message.split(chr(10)))
        else:
            numberOfLines = self.numberOfLines

        numberOfButtons = len(self.Buttons)
        self.ButtonSpace = self.ButtonSize/2
        if self.fromBroxSize:
            # button size is calculated from boxsize
            size = (2 * self.boxSize) / (3 * numberOfButtons + 1)
            self.ButtonSize = size
            self.ButtonSpace = self.ButtonSize/2
        else:
            # boxsize is calculated from buttonsize
            self.boxSize = numberOfButtons * (self.ButtonSize +
                                            self.ButtonSpace) + self.ButtonSpace

        # create the dialog model and set the properties
        dialog_model = self.smgr.createInstanceWithContext(
                                    'com.sun.star.awt.UnoControlDialogModel',
                                    self.ctx)
        dialog_model.PositionX = 50
        dialog_model.Step = 1
        dialog_model.TabIndex = 7
        dialog_model.Width = self.boxSize#numberOfButtons * (self.ButtonSize +
                             #               self.ButtonSpace) + 25
        dialog_model.Height = 10 + self.lineHeight * numberOfLines + 10 + 12  + 10
        dialog_model.PositionY = 63
        dialog_model.Sizeable = True
        dialog_model.Closeable = False

        dialog = self.smgr.createInstanceWithContext(
                'com.sun.star.awt.UnoControlDialog', self.ctx)

        # label Label0
        label = dialog_model.createInstance(
                'com.sun.star.awt.UnoControlFixedTextModel')
        label.PositionX =  10
        label.TabIndex = 9
        label.Width = dialog_model.Width - label.PositionX
        label.Height = self.lineHeight* numberOfLines
        label.PositionY = 10
        label.Align = left
        label.MultiLine = True
        label.Label = self.message
        dialog_model.insertByName('Label0', label)

        nb = 0
        for buttonName in self.Buttons:
            nb +=1
            button = dialog_model.createInstance(
                                    'com.sun.star.awt.UnoControlButtonModel')
            button.PositionX = nb * self.ButtonSpace + (nb-1)* self.ButtonSize
            button.TabIndex = 8
            button.Height = 12
            button.Width = self.ButtonSize
            button.PositionY = 10 + label.Height + 10
            button.PushButtonType = standard
            if nb == 1:
                button.DefaultButton = True
            else:
                button.DefaultButton = False
            button.Label = buttonName
            dialog_model.insertByName('Btn' + str(nb), button )

        if not dialog.getModel():
            dialog.setModel(dialog_model)

        # UNO toolkit definition
        toolkit = self.smgr.createInstanceWithContext('com.sun.star.awt.Toolkit', self.ctx)
        a_rect = uno.createUnoStruct( 'com.sun.star.awt.Rectangle' )
        a_rect.X = 50
        dialog.setTitle ( self.title )
        a_rect.Width = 270
        a_rect.Height = 261
        a_rect.Y = 63
        win_descriptor = uno.createUnoStruct('com.sun.star.awt.WindowDescriptor')
        win_descriptor.Type = TOP
        win_descriptor.ParentIndex = -1
        win_descriptor.Bounds = a_rect
        peer = toolkit.createWindow( win_descriptor )
        dialog.createPeer( toolkit, peer )

        return dialog

    def _addListeners(self):
        """Add listeners to dialog"""
        nb = 0
        for buttonName in self.Buttons:
            nb +=1
            a_control = self.dialog.getControl('Btn'+str(nb))
            the_listener = ButtonListener(self)
            a_control.addActionListener(the_listener)
            self.lst_listeners['Btn'+str(nb)] = the_listener
        return

    def _removeListeners(self):
        """ remove listeners on exiting"""
        nb = 0
        for buttonName in self.Buttons:
            nb +=1
            a_control = self.dialog.getControl('Btn'+str(nb))
            a_control.removeActionListener(self.lst_listeners['Btn'+str(nb)])
        return

    def show(self, message, decoration, title):
        self.message = message
        self.decoration = decoration
        self.title = title
        # Create GUI
        self.dialog = self._createBox()
        self._addListeners()
        #execute the dialog --> blocking call
        self.dialog.execute()
        #end --> release listeners and dispose dialog
        self._removeListeners()
        self.dialog.dispose()
        return self.Response

    def addButton(self, caption):
        self.Buttons.append(caption)
        return

    def renderFromBoxSize(self, size = 150):
        self.boxSize = size
        self.fromBroxSize = True
        return

    def renderFromButtonSize(self, size = 50):
        self.ButtonSize = size
        self.fromBroxSize = False
        return

class ButtonListener(unohelper.Base, XActionListener):
    """Stops the MessageBox, sets the button label as returned value"""
    def __init__(self, caller):
        self.caller = caller

    def disposing(self, eventObject):
        pass

    def actionPerformed(self, actionEvent):
        button = actionEvent.Source
        self.caller.Response = button.Model.Label
        self.caller.dialog.endExecute()
        return

### TEST
if __name__ == '__main__':
    # get the uno component context from the PyUNO runtime
    localContext = uno.getComponentContext()

    # create the UnoUrlResolver
    resolver = localContext.ServiceManager.createInstanceWithContext(
                    "com.sun.star.bridge.UnoUrlResolver", localContext )

    # connect to the running office
    # LibO has to be launched in listen mode as
    # ./soffice "--accept=socket,host=localhost,port=2002;urp;"
    ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
    myBox = MsgBox(ctx)
    myBox.addButton("Yes")
    myBox.addButton("No")
    myBox.addButton("May be")
    myBox.renderFromBoxSize(150)
    myBox.numberOflines = 2

    print(myBox.show("A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message A very long message " + chr(10)+chr(10)+"Do you agree ?",0,"Dialog title"))

    myBox = MsgBox(ctx)
    myBox.addButton("oK")
    myBox.renderFromButtonSize()
    myBox.numberOflines = 2

    print(myBox.show("A small message",0,"Dialog title"))

# vim: set shiftwidth=4 softtabstop=4 expandtab:
