1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 package ifc.sheet;
19 
20 import com.sun.star.accessibility.AccessibleRole;
21 import com.sun.star.accessibility.XAccessible;
22 import com.sun.star.accessibility.XAccessibleComponent;
23 import com.sun.star.accessibility.XAccessibleContext;
24 import com.sun.star.awt.Point;
25 import com.sun.star.awt.PosSize;
26 import com.sun.star.awt.Rectangle;
27 import com.sun.star.awt.XExtendedToolkit;
28 import com.sun.star.awt.XTopWindow;
29 import com.sun.star.awt.XWindow;
30 import com.sun.star.beans.PropertyValue;
31 import com.sun.star.frame.XModel;
32 import com.sun.star.lang.EventObject;
33 import com.sun.star.lang.XComponent;
34 import com.sun.star.lang.XMultiServiceFactory;
35 import com.sun.star.sheet.RangeSelectionEvent;
36 import com.sun.star.sheet.XRangeSelection;
37 import com.sun.star.sheet.XRangeSelectionChangeListener;
38 import com.sun.star.sheet.XRangeSelectionListener;
39 import com.sun.star.uno.UnoRuntime;
40 import java.awt.Robot;
41 import java.awt.event.InputEvent;
42 import java.io.PrintWriter;
43 import lib.MultiMethodTest;
44 import lib.Status;
45 import lib.StatusException;
46 import util.AccessibilityTools;
47 
48 /**
49  * Check the XRangeSelection interface.
50  */
51 public class _XRangeSelection extends MultiMethodTest {
52     public XRangeSelection oObj = null;
53     MyRangeSelectionListener aListener = null;
54 
55     @Override
before()56     public void before() {
57         aListener = new _XRangeSelection.MyRangeSelectionListener(log);
58         // workaround for i34499
59         XModel xModel = (XModel)tEnv.getObjRelation("FirstModel");
60         if (xModel == null)
61             throw new StatusException(Status.failed("Object relation FirstModel' not set."));
62         XWindow xWindow = xModel.getCurrentController().getFrame().getContainerWindow();
63         XTopWindow xTopWindow = UnoRuntime.queryInterface(XTopWindow.class, xWindow);
64         xTopWindow.toFront();
65         waitForEventIdle();
66     }
67 
68 
_abortRangeSelection()69     public void _abortRangeSelection() {
70         requiredMethod("removeRangeSelectionChangeListener()");
71         requiredMethod("removeRangeSelectionListener()");
72         oObj.abortRangeSelection();
73         tRes.tested("abortRangeSelection()", true);
74     }
75 
_addRangeSelectionChangeListener()76     public void _addRangeSelectionChangeListener() {
77         oObj.addRangeSelectionChangeListener(aListener);
78         tRes.tested("addRangeSelectionChangeListener()", true);
79     }
80 
_addRangeSelectionListener()81     public void _addRangeSelectionListener() {
82         oObj.addRangeSelectionListener(aListener);
83         tRes.tested("addRangeSelectionListener()", true);
84     }
85 
_removeRangeSelectionChangeListener()86     public void _removeRangeSelectionChangeListener() {
87         oObj.removeRangeSelectionChangeListener(aListener);
88         tRes.tested("removeRangeSelectionChangeListener()", true);
89     }
90 
_removeRangeSelectionListener()91     public void _removeRangeSelectionListener() {
92         oObj.removeRangeSelectionListener(aListener);
93         tRes.tested("removeRangeSelectionListener()", true);
94     }
95 
_startRangeSelection()96     public void _startRangeSelection() {
97         requiredMethod("addRangeSelectionChangeListener()");
98         requiredMethod("addRangeSelectionListener()");
99 
100         // get the sheet center
101         Point center = getSheetCenter();
102         if (center == null)
103             throw new StatusException(Status.failed("Couldn't get the sheet center."));
104 
105         PropertyValue[] props = new PropertyValue[3];
106         props[0] = new PropertyValue();
107         props[0].Name = "InitialValue";
108         props[0].Value = "B3:D5";
109         props[1] = new PropertyValue();
110         props[1].Name = "Title";
111         props[1].Value = "the title";
112         props[2] = new PropertyValue();
113         props[2].Name = "CloseOnMouseRelease";
114         props[2].Value = Boolean.FALSE;
115         oObj.startRangeSelection(props);
116         // wait for listeners
117         waitForEventIdle();
118 
119         // get closer button: move if window covers the sheet center
120         Point closer = getCloser(center);
121         if (closer == null)
122             throw new StatusException(Status.failed("Couldn't get the close Button."));
123 
124         // do something to trigger the listeners
125         clickOnSheet(center);
126         waitForEventIdle();
127 
128         // click on closer
129         clickOnSheet(closer);
130         waitForEventIdle();
131 
132         // open a new range selection
133         props[0].Value = "C4:E6";
134         oObj.startRangeSelection(props);
135         waitForEventIdle();
136         props[0].Value = "C2:E3";
137         oObj.startRangeSelection(props);
138         waitForEventIdle();
139 
140         oObj.startRangeSelection(props);
141         waitForEventIdle();
142         oObj.abortRangeSelection();
143         aListener.reset();
144         System.out.println("Listener called: " + aListener.bAbortCalled);
145 
146         tRes.tested("startRangeSelection()", aListener.listenerCalled());
147     }
148 
149     /**
150      * Determine the current top window center and return this as a point.
151      * @return a point representing the sheet center.
152      */
getSheetCenter()153     protected Point getSheetCenter() {
154         log.println("Trying to get AccessibleSpreadsheet");
155 
156         XComponent xSheetDoc = (XComponent) tEnv.getObjRelation("DOCUMENT");
157 
158         XModel xModel = UnoRuntime.queryInterface(XModel.class, xSheetDoc);
159         System.out.println("Name: " + xModel.getCurrentController().getFrame().getName());
160 
161         XWindow xWindow = AccessibilityTools.getCurrentWindow(xModel);
162         XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow);
163 
164         XAccessibleContext ctx = AccessibilityTools.getAccessibleObjectForRole(xRoot, AccessibleRole.TABLE  );
165 
166         XAccessibleComponent AccessibleSpreadsheet = UnoRuntime.queryInterface(XAccessibleComponent.class,ctx);
167 
168         log.println("Got " + util.utils.getImplName(AccessibleSpreadsheet));
169 
170         Object toolkit = null;
171 
172         try {
173             toolkit = tParam.getMSF().createInstance("com.sun.star.awt.Toolkit");
174         } catch (com.sun.star.uno.Exception e) {
175             log.println("Couldn't get toolkit");
176             e.printStackTrace(log);
177             throw new StatusException("Couldn't get toolkit", e);
178         }
179 
180         XExtendedToolkit tk = UnoRuntime.queryInterface(
181                                       XExtendedToolkit.class, toolkit);
182 
183         XTopWindow tw = null;
184 
185         int k = tk.getTopWindowCount();
186         for (int i=0;i<k;i++) {
187             try {
188                 XTopWindow tw_temp = tk.getTopWindow(i);
189                 XAccessible xacc = UnoRuntime.queryInterface(XAccessible.class,  tw_temp);
190                 if (xacc != null) {
191                     if (xacc.getAccessibleContext().getAccessibleName().indexOf("d2")>0) {
192                         tw=tw_temp;
193                     }
194                 } else {
195                     log.println("\t unknown window");
196                 }
197 
198             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
199             }
200         }
201         if (tw == null) {
202             System.out.println("No TopWindow :-(");
203             return null;
204         }
205 
206         Point point = AccessibleSpreadsheet.getLocationOnScreen();
207         Rectangle rect = AccessibleSpreadsheet.getBounds();
208         Point retPoint = new Point();
209         retPoint.X = point.X + (rect.Width / 2);
210         retPoint.Y = point.Y + (rect.Height / 2);
211         return retPoint;
212     }
213 
214     /**
215      * Get the closer button on the right top of the current window.
216      * @return A point representing the closer button.
217      */
getCloser(Point center)218     private Point getCloser(Point center) {
219         XMultiServiceFactory xMSF = tParam.getMSF();
220         Object aToolkit = null;
221         try {
222             aToolkit = xMSF.createInstance("com.sun.star.awt.Toolkit");
223         }
224         catch(com.sun.star.uno.Exception e) {
225             throw new StatusException("Could not create 'com.sun.star.awt.Toolkit'.", e);
226         }
227         XExtendedToolkit xExtendedToolkit = UnoRuntime.queryInterface(XExtendedToolkit.class, aToolkit);
228         XTopWindow tw = null;
229 
230         XAccessibleComponent xAccessibleComponent = null;
231         int k = xExtendedToolkit.getTopWindowCount();
232         for (int i=0;i<k;i++) {
233             try {
234                 XTopWindow tw_temp = xExtendedToolkit.getTopWindow(i);
235                 XAccessible xacc = UnoRuntime.queryInterface(XAccessible.class,  tw_temp);
236                 if (xacc != null) {
237                     System.out.println("Name: " + xacc.getAccessibleContext().getAccessibleName());
238                     if (xacc.getAccessibleContext().getAccessibleName().startsWith("the title")) {
239                         tw = tw_temp;
240                         XAccessibleContext xContext = xacc.getAccessibleContext();
241                         xAccessibleComponent = UnoRuntime.queryInterface(XAccessibleComponent.class, xContext);
242                         if (xAccessibleComponent == null)
243                             System.out.println("!!!! MIST !!!!");
244                         else
245                             System.out.println("########## KLAPPT ########## ");
246                     }
247                 }
248                 else {
249                     log.println("\t unknown window");
250                 }
251 
252             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
253             }
254         }
255         if (tw == null) {
256             System.out.println("No TopWindow :-(");
257             return null;
258         }
259 
260         XWindow xWindow = UnoRuntime.queryInterface(XWindow.class, tw);
261         Rectangle posSize = xWindow.getPosSize();
262 
263         // compare the center point with the dimensions of the current top window
264         boolean windowOK = false;
265         while(!windowOK) {
266             if (posSize.X <= center.X && center.X <= posSize.X + posSize.Width) {
267                 if (posSize.Y <= center.Y && center.Y <= posSize.Y +posSize.Height) {
268                     // move window out of the way
269                     posSize.X = posSize.X + 10;
270                     posSize.Y = posSize.Y +10;
271                     xWindow.setPosSize(posSize.X, posSize.Y, posSize.Width, posSize.Height, PosSize.POS);
272                 }
273                 else {
274                     windowOK = true;
275                 }
276             }
277             else {
278                 windowOK = true;
279             }
280 
281         }
282 
283         Point p = xAccessibleComponent.getLocationOnScreen();
284         Point closer = new Point();
285         closer.X = p.X + posSize.Width - 2;
286         closer.Y = p.Y + 5;
287         System.out.println("Closer: " + closer.X + "   " + closer.Y);
288         return closer;
289     }
290 
clickOnSheet(Point point)291     protected boolean clickOnSheet(Point point) {
292         log.println("Clicking in the center of the AccessibleSpreadsheet");
293 
294         try {
295             Robot rob = new Robot();
296             rob.mouseMove(point.X, point.Y);
297             rob.mousePress(InputEvent.BUTTON1_MASK);
298             waitForEventIdle();
299             rob.mouseRelease(InputEvent.BUTTON1_MASK);
300             waitForEventIdle();
301         } catch (java.awt.AWTException e) {
302             log.println("couldn't press mouse button");
303         }
304 
305         return true;
306     }
307 
308     /**
309      *
310      */
311     public static class MyRangeSelectionListener implements XRangeSelectionListener, XRangeSelectionChangeListener {
312         boolean bAbortCalled = false;
313         boolean bChangeCalled = false;
314         boolean bDoneCalled = false;
315         PrintWriter log = null;
316 
MyRangeSelectionListener(PrintWriter log)317         public MyRangeSelectionListener(PrintWriter log) {
318             this.log = log;
319         }
320 
aborted(RangeSelectionEvent rangeSelectionEvent)321         public void aborted(RangeSelectionEvent rangeSelectionEvent) {
322             log.println("Called 'aborted' with: " + rangeSelectionEvent.RangeDescriptor);
323             bAbortCalled = true;
324         }
325 
descriptorChanged(RangeSelectionEvent rangeSelectionEvent)326         public void descriptorChanged(RangeSelectionEvent rangeSelectionEvent) {
327             log.println("Called 'descriptorChanged' with: " + rangeSelectionEvent.RangeDescriptor);
328             bChangeCalled = true;
329         }
330 
done(RangeSelectionEvent rangeSelectionEvent)331         public void done(RangeSelectionEvent rangeSelectionEvent) {
332             log.println("Called 'done' with: " + rangeSelectionEvent.RangeDescriptor);
333             bDoneCalled = true;
334         }
335 
listenerCalled()336         public boolean listenerCalled() {
337             return bAbortCalled & bChangeCalled & bDoneCalled;
338         }
339 
reset()340         public void reset() {
341             bAbortCalled = false;
342             bChangeCalled = false;
343             bDoneCalled = false;
344         }
345 
346         /**
347          * ignore disposing
348          * @param eventObject The event.
349          */
disposing(EventObject eventObject)350         public void disposing(EventObject eventObject) {
351         }
352     }
353 }
354