1# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
2#
3# This file is part of the LibreOffice project.
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http://mozilla.org/MPL/2.0/.
8#
9
10# prepare Python environment - Add the path of this class
11from os import path
12from sys import modules
13from sys import path as syspath
14
15# pyUNO program itself
16import uno, unohelper
17
18# UNO GUI toolkit
19from com.sun.star.awt.WindowClass import TOP, SIMPLE
20from com.sun.star.awt.PushButtonType import STANDARD as standard
21from com.sun.star.awt.PushButtonType import OK as ok
22from com.sun.star.awt.PushButtonType import CANCEL as cancel
23from com.sun.star.awt.PushButtonType import HELP as help
24from com.sun.star.awt.TextAlign import CENTER as center
25from com.sun.star.awt.TextAlign import LEFT as left
26from com.sun.star.awt.TextAlign import RIGHT as right
27
28# used UNO listeners
29from com.sun.star.awt import XActionListener
30
31class MsgBox(unohelper.Base):
32    """Inspect UNO object, link to sdk and recursive calls"""
33
34    def __init__(self, aContext):
35        """acontext : a Valid UNO context
36        """
37
38        self.VERSION = '0.1'
39        self.ctx = aContext
40        self.smgr = aContext.ServiceManager
41        # UI Dialog object
42        self.dialog=None
43        # List of opened Listeners
44        self.lst_listeners={}
45        #UI parameters
46        self.ButtonSize = 50
47        self.boxSize = 200
48        self.lineHeight = 10
49        self.fromBroxSize = False
50        self.numberOfLines = -1
51
52        self.Buttons = []
53        self.Response = ''
54
55        return
56
57    #####################################################
58    #                 GUI definition                    #
59    #####################################################
60    def _createBox(self):
61        """Create the Box"""
62
63        # computes parameters of the message dialog
64        if self.numberOfLines == -1:
65            #calculate
66            numberOfLines = len(self.message.split(chr(10)))
67        else:
68            numberOfLines = self.numberOfLines
69
70        numberOfButtons = len(self.Buttons)
71        self.ButtonSpace = self.ButtonSize/2
72        if self.fromBroxSize:
73            # button size is calculated from boxsize
74            size = (2 * self.boxSize) / (3 * numberOfButtons + 1)
75            self.ButtonSize = size
76            self.ButtonSpace = self.ButtonSize/2
77        else:
78            # boxsize is calculated from buttonsize
79            self.boxSize = numberOfButtons * (self.ButtonSize +
80                                            self.ButtonSpace) + self.ButtonSpace
81
82        # create the dialog model and set the properties
83        dialog_model = self.smgr.createInstanceWithContext(
84                                    'com.sun.star.awt.UnoControlDialogModel',
85                                    self.ctx)
86        dialog_model.PositionX = 50
87        dialog_model.Step = 1
88        dialog_model.TabIndex = 7
89        dialog_model.Width = self.boxSize#numberOfButtons * (self.ButtonSize +
90                             #               self.ButtonSpace) + 25
91        dialog_model.Height = 10 + self.lineHeight * numberOfLines + 10 + 12  + 10
92        dialog_model.PositionY = 63
93        dialog_model.Sizeable = True
94        dialog_model.Closeable = False
95
96        dialog = self.smgr.createInstanceWithContext(
97                'com.sun.star.awt.UnoControlDialog', self.ctx)
98
99        # label Label0
100        label = dialog_model.createInstance(
101                'com.sun.star.awt.UnoControlFixedTextModel')
102        label.PositionX =  10
103        label.TabIndex = 9
104        label.Width = dialog_model.Width - label.PositionX
105        label.Height = self.lineHeight* numberOfLines
106        label.PositionY = 10
107        label.Align = left
108        label.MultiLine = True
109        label.Label = self.message
110        dialog_model.insertByName('Label0', label)
111
112        nb = 0
113        for buttonName in self.Buttons:
114            nb +=1
115            button = dialog_model.createInstance(
116                                    'com.sun.star.awt.UnoControlButtonModel')
117            button.PositionX = nb * self.ButtonSpace + (nb-1)* self.ButtonSize
118            button.TabIndex = 8
119            button.Height = 12
120            button.Width = self.ButtonSize
121            button.PositionY = 10 + label.Height + 10
122            button.PushButtonType = standard
123            if nb == 1:
124                button.DefaultButton = True
125            else:
126                button.DefaultButton = False
127            button.Label = buttonName
128            dialog_model.insertByName('Btn' + str(nb), button )
129
130        if not dialog.getModel():
131            dialog.setModel(dialog_model)
132
133        # UNO toolkit definition
134        toolkit = self.smgr.createInstanceWithContext('com.sun.star.awt.Toolkit', self.ctx)
135        a_rect = uno.createUnoStruct( 'com.sun.star.awt.Rectangle' )
136        a_rect.X = 50
137        dialog.setTitle ( self.title )
138        a_rect.Width = 270
139        a_rect.Height = 261
140        a_rect.Y = 63
141        win_descriptor = uno.createUnoStruct('com.sun.star.awt.WindowDescriptor')
142        win_descriptor.Type = TOP
143        win_descriptor.ParentIndex = -1
144        win_descriptor.Bounds = a_rect
145        peer = toolkit.createWindow( win_descriptor )
146        dialog.createPeer( toolkit, peer )
147
148        return dialog
149
150    def _addListeners(self):
151        """Add listeners to dialog"""
152        nb = 0
153        for buttonName in self.Buttons:
154            nb +=1
155            a_control = self.dialog.getControl('Btn'+str(nb))
156            the_listener = ButtonListener(self)
157            a_control.addActionListener(the_listener)
158            self.lst_listeners['Btn'+str(nb)] = the_listener
159        return
160
161    def _removeListeners(self):
162        """ remove listeners on exiting"""
163        nb = 0
164        for buttonName in self.Buttons:
165            nb +=1
166            a_control = self.dialog.getControl('Btn'+str(nb))
167            a_control.removeActionListener(self.lst_listeners['Btn'+str(nb)])
168        return
169
170    def show(self, message, decoration, title):
171        self.message = message
172        self.decoration = decoration
173        self.title = title
174        # Create GUI
175        self.dialog = self._createBox()
176        self._addListeners()
177        #execute the dialog --> blocking call
178        self.dialog.execute()
179        #end --> release listeners and dispose dialog
180        self._removeListeners()
181        self.dialog.dispose()
182        return self.Response
183
184    def addButton(self, caption):
185        self.Buttons.append(caption)
186        return
187
188    def renderFromBoxSize(self, size = 150):
189        self.boxSize = size
190        self.fromBroxSize = True
191        return
192
193    def renderFromButtonSize(self, size = 50):
194        self.ButtonSize = size
195        self.fromBroxSize = False
196        return
197
198class ButtonListener(unohelper.Base, XActionListener):
199    """Stops the MessageBox, sets the button label as returned value"""
200    def __init__(self, caller):
201        self.caller = caller
202
203    def disposing(self, eventObject):
204        pass
205
206    def actionPerformed(self, actionEvent):
207        button = actionEvent.Source
208        self.caller.Response = button.Model.Label
209        self.caller.dialog.endExecute()
210        return
211
212### TEST
213if __name__ == '__main__':
214    # get the uno component context from the PyUNO runtime
215    localContext = uno.getComponentContext()
216
217    # create the UnoUrlResolver
218    resolver = localContext.ServiceManager.createInstanceWithContext(
219                    "com.sun.star.bridge.UnoUrlResolver", localContext )
220
221    # connect to the running office
222    # LibO has to be launched in listen mode as
223    # ./soffice "--accept=socket,host=localhost,port=2002;urp;"
224    ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
225    myBox = MsgBox(ctx)
226    myBox.addButton("Yes")
227    myBox.addButton("No")
228    myBox.addButton("May be")
229    myBox.renderFromBoxSize(150)
230    myBox.numberOflines = 2
231
232    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"))
233
234    myBox = MsgBox(ctx)
235    myBox.addButton("oK")
236    myBox.renderFromButtonSize()
237    myBox.numberOflines = 2
238
239    print(myBox.show("A small message",0,"Dialog title"))
240
241# vim: set shiftwidth=4 softtabstop=4 expandtab:
242