1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package complex.XUserInputInterception; 25 26 import com.sun.star.accessibility.AccessibleRole; 27 import com.sun.star.accessibility.XAccessible; 28 import com.sun.star.accessibility.XAccessibleComponent; 29 import com.sun.star.accessibility.XAccessibleContext; 30 import com.sun.star.awt.KeyEvent; 31 import com.sun.star.awt.MouseEvent; 32 import com.sun.star.awt.Point; 33 import com.sun.star.awt.Rectangle; 34 import com.sun.star.awt.XKeyHandler; 35 import com.sun.star.awt.XMouseClickHandler; 36 import com.sun.star.awt.XUserInputInterception; 37 import com.sun.star.awt.XWindow; 38 import com.sun.star.chart.XChartDocument; 39 import com.sun.star.frame.*; 40 import com.sun.star.lang.*; 41 import com.sun.star.lang.EventObject; 42 import com.sun.star.sheet.XSpreadsheetDocument; 43 import com.sun.star.text.XTextDocument; 44 import com.sun.star.uno.UnoRuntime; 45 import com.sun.star.uno.XInterface; 46 import com.sun.star.util.*; 47 import java.awt.Robot; 48 import java.awt.event.InputEvent; 49 50 import util.AccessibilityTools; 51 import util.SOfficeFactory; 52 53 // ---------- junit imports ----------------- 54 import org.junit.After; 55 import org.junit.AfterClass; 56 import org.junit.Before; 57 import org.junit.BeforeClass; 58 import org.junit.Test; 59 import org.openoffice.test.OfficeConnection; 60 import static org.junit.Assert.*; 61 // ------------------------------------------ 62 //----------------------------------------------- 63 /** 64 * This <CODE>ComplexTest</CODE> checks the interface 65 * <CODE>XUserInputInterception</CODE>. Therefore it creates a document, 66 * adds a mouse and a key listener onto the interface and fire the 67 * correspond events. If all listener works as expected the test resluts in 68 * <CODE>OK</CODE> status. 69 * @short Check the interface XUserInputIntercaption 70 * @descr checks is a simple way the interface XUserInputInteraction 71 */ 72 public class EventTest { 73 //------------------------------------------- 74 // some const 75 76 //------------------------------------------- 77 // member 78 79 /** points to the global uno service manager. */ 80 private XMultiServiceFactory m_xMSF = null; 81 82 /** indicates if the mousePressed event was called*/ 83 private boolean m_mousePressed = false; 84 /** indicates if the mouseReleased event was called*/ 85 private boolean m_mouseReleased = false; 86 87 /** indicates if the mousePressed event was called*/ 88 private boolean m_keyPressed = false; 89 /** indicates if the mouseReleased event was called*/ 90 private boolean m_keyReleased = false; 91 92 /** points to a global StarOffice factory */ 93 private SOfficeFactory m_SOF = null; 94 95 /** 96 * define the miliseconds to wait until a <CODE>EventTrigger</CODE> thread should 97 * be finished with its work 98 */ 99 final int m_threadWait = 3000; 100 101 //------------------------------------------- 102 // test environment 103 104 //------------------------------------------- 105 /** 106 * The test methods are: 107 * <ul> 108 * <li><CODE>checkTextDocument</CODE></LI> 109 * <li><CODE>checkCalcDocument</CODE></LI> 110 * <li><CODE>checkDrawDocument</CODE></LI> 111 * <li><CODE>checkImpressDocument</CODE></LI> 112 * <li><CODE>checkChartDocument</CODE></LI> 113 * <li><CODE>checkMathDocument</CODE></li> 114 * </ul> 115 * @short A function to tell the framework, 116 * which test functions are available. 117 * @return All test methods. 118 * @todo Think about selection of tests from outside ... 119 */ 120 // public String[] getTestMethodNames() { 121 // return new String[] 122 // { "checkTextDocument", 123 // "checkCalcDocument", 124 // "checkDrawDocument", 125 // "checkImpressDocument", 126 // "checkChartDocument", 127 // "checkMathDocument", 128 // }; 129 // } 130 131 //------------------------------------------- 132 /** 133 * creates the mebmer <CODE>m_xMSF</CODE> and <CODE>m_SOF</CODE> 134 * @short Create the environment for following tests. 135 * @descr create an empty test frame, where we can load 136 * different components inside. 137 */ 138 @Before public void before() { 139 // get uno service manager from global test environment 140 m_xMSF = getMSF(); 141 142 // create frame instance 143 try { 144 // get a soffice factory object 145 m_SOF = SOfficeFactory.getFactory(getMSF()); 146 147 } catch(java.lang.Throwable ex) { 148 fail("Could not create the XUserInputInterception instance."); 149 } 150 } 151 152 //------------------------------------------- 153 /** 154 * closes the document 155 * @short close the document. 156 * @param xDoc the document to close 157 */ 158 public void closeDoc(XInterface xDoc) { 159 XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xDoc); 160 try { 161 xClose.close(false); 162 } catch(com.sun.star.util.CloseVetoException exVeto) { 163 System.out.println("document couldn't be closed successfully."); 164 } 165 } 166 167 /** 168 * creates a text document and check the <CODE>XMouseClickHandler</CODE> and 169 * <CODE>XKeyHandler</CODE> 170 * @see com.sun.star.awt.XKeyHandler 171 * @see com.sun.star.awt.XMouseClickHandler 172 */ 173 @Test public void checkTextDocument(){ 174 175 XTextDocument xDoc = null; 176 177 try{ 178 xDoc = m_SOF.createTextDoc("WriterTest"); 179 } catch (com.sun.star.uno.Exception e){ 180 fail("Could not create a text document: " +e.toString()); 181 } 182 183 checkListener(xDoc); 184 185 closeDoc(xDoc); 186 } 187 188 /** 189 * creates an impress document and check the <CODE>XMouseClickHandler</CODE> and 190 * <CODE>XKeyHandler</CODE> 191 * @see com.sun.star.awt.XKeyHandler 192 * @see com.sun.star.awt.XMouseClickHandler 193 */ 194 @Test public void checkImpressDocument(){ 195 196 XComponent xDoc = null; 197 198 try{ 199 xDoc = m_SOF.createImpressDoc("ImpressTest"); 200 } catch (com.sun.star.uno.Exception e){ 201 fail("Could not create an impress document: " +e.toString()); 202 } 203 204 checkListener(xDoc); 205 206 closeDoc(xDoc); 207 } 208 209 /** 210 * creates a chart document and check the <CODE>XMouseClickHandler</CODE> and 211 * <CODE>XKeyHandler</CODE> 212 * @see com.sun.star.awt.XKeyHandler 213 * @see com.sun.star.awt.XMouseClickHandler 214 */ 215 // TODO! 216 // @Test public void checkChartDocument(){ 217 // 218 // XChartDocument xDoc = null; 219 // 220 // try{ 221 // xDoc = m_SOF.createChartDoc("ChartTest"); 222 // } catch (com.sun.star.uno.Exception e){ 223 // fail("Could not create a chart document: " +e.toString()); 224 // } 225 // 226 // checkListener(xDoc); 227 // 228 // closeDoc(xDoc); 229 // } 230 231 /** 232 * creates a math document and check the <CODE>XMouseClickHandler</CODE> and 233 * <CODE>XKeyHandler</CODE> 234 * @see com.sun.star.awt.XKeyHandler 235 * @see com.sun.star.awt.XMouseClickHandler 236 */ 237 @Test public void checkMathDocument(){ 238 239 XComponent xDoc = null; 240 241 try{ 242 xDoc = m_SOF.createMathDoc("MathTest"); 243 } catch (com.sun.star.uno.Exception e){ 244 fail("Could not create a math document: " +e.toString()); 245 } 246 247 checkListener(xDoc); 248 249 closeDoc(xDoc); 250 } 251 252 /** 253 * creates a draw document and check the <CODE>XMouseClickHandler</CODE> and 254 * <CODE>XKeyHandler</CODE> 255 * @see com.sun.star.awt.XKeyHandler 256 * @see com.sun.star.awt.XMouseClickHandler 257 */ 258 @Test public void checkDrawDocument(){ 259 260 XComponent xDoc = null; 261 262 try{ 263 xDoc = m_SOF.createDrawDoc("DrawTest"); 264 } catch (com.sun.star.uno.Exception e){ 265 fail("Could not create a draw document: " +e.toString()); 266 } 267 268 checkListener(xDoc); 269 270 closeDoc(xDoc); 271 } 272 273 /** 274 * creates a calc document and check the <CODE>XMouseClickHandler</CODE> and 275 * <CODE>XKeyHandler</CODE> 276 * @see com.sun.star.awt.XKeyHandler 277 * @see com.sun.star.awt.XMouseClickHandler 278 */ 279 @Test public void checkCalcDocument(){ 280 281 XSpreadsheetDocument xDoc = null; 282 283 try{ 284 xDoc = m_SOF.createCalcDoc("CalcTest"); 285 } catch (com.sun.star.uno.Exception e){ 286 fail("Could not create a calc document: " +e.toString()); 287 } 288 289 checkListener(xDoc); 290 closeDoc(xDoc); 291 } 292 293 /** 294 * This is the central test method. It is called by ceck[DOCTYPE]Document. It 295 * creates the <CODE>XUserInputInterception</CODE> from the document and call the 296 * <CODE>checkMouseListener</CODE> test and the <CODE>checkKeyListener</CODE> test 297 * @param xDoc the document to test 298 */ 299 private void checkListener(XInterface xDoc){ 300 301 XModel xModel = UnoRuntime.queryInterface(XModel.class, xDoc); 302 303 XUserInputInterception xUII = getUII(xModel); 304 305 checkMouseListener(xUII, xModel); 306 checkKeyListener(xUII, xModel); 307 } 308 309 /** 310 * Creates a <CODE>MyKeyHandler</CODE> and adds it to the 311 * <CODE>XUserInputInterception</CODE>. Then an <CODE>EventTrigger</CODE> thread 312 * was created and started. 313 * Has <CODE>OK</CODE> if the members <CODE>m_keyPressed</CODE> and 314 * <CODE>m_keyReleased</CODE> are <CODE>TRUE</CODE> 315 * @param xUII the XUserInputInterception 316 * @param xModel the XModel of a document 317 * @see EventTest.MyKeyHandler 318 * @see EventTest.EventTrigger 319 */ 320 private void checkKeyListener(XUserInputInterception xUII, XModel xModel) { 321 m_keyPressed = false; 322 m_keyReleased = false; 323 324 MyKeyHandler keyListener = new MyKeyHandler(); 325 326 xUII.addKeyHandler(keyListener); 327 328 System.out.println("starting thread to check the key listener..."); 329 EventTrigger et = new EventTrigger(xModel, EventTriggerType.KEY_TEXT_INTO_DOC); 330 331 et.run(); 332 333 util.utils.shortWait(m_threadWait); 334 System.out.println("key listener thread should be finished."); 335 336 assertTrue("key event does not work!", m_keyPressed && m_keyReleased); 337 xUII.removeKeyHandler(keyListener); 338 339 } 340 341 /** 342 * Creates a <CODE>MyMouseClickHandler</CODE> and adds it to the 343 * <CODE>XUserInputInterception</CODE>. Then an <CODE>EventTrigger</CODE> thread 344 * was created and started. 345 * Has <CODE>OK</CODE> if the members <CODE>m_mousePressed</CODE> and 346 * <CODE>m_mouseReleased</CODE> are <CODE>TRUE</CODE> 347 * @param xUII the XUserInputInterception 348 * @param xModel the XModel of a document 349 * @see EventTest.MyMouseClickHander 350 * @see EventTest.EventTrigger 351 */ 352 353 private void checkMouseListener(XUserInputInterception xUII, XModel xModel) { 354 355 m_mousePressed = false; 356 m_mouseReleased = false; 357 358 MyMouseClickHandler mouseListener = new MyMouseClickHandler(); 359 360 xUII.addMouseClickHandler(mouseListener); 361 362 System.out.println("starting thread to check the mouse listener..."); 363 EventTrigger et = new EventTrigger(xModel, EventTriggerType.MOUSE_KLICK_INTO_DOC); 364 365 et.run(); 366 367 util.utils.shortWait(m_threadWait); 368 System.out.println("mouse listener thread should be finished."); 369 370 assertTrue("mouse event does not work!", m_mousePressed && m_mouseReleased); 371 xUII.removeMouseClickHandler(mouseListener); 372 } 373 374 /** 375 * returns the <CODE>XUserInputInterception</CODE> from the <CODE>XMdoel</CODE> 376 * @param xModel the XModel of a document 377 * @return the <CODE>XUserInputInterception</CODE> of the document 378 */ 379 private XUserInputInterception getUII(XModel xModel){ 380 381 XController xController = xModel.getCurrentController(); 382 383 XUserInputInterception xUII = UnoRuntime.queryInterface(XUserInputInterception.class, xController); 384 if (xUII == null) { 385 fail("could not get XUserInputInterception from XContoller"); 386 } 387 return xUII; 388 } 389 390 /** 391 * Listener which added and its method must be called 392 * on <code>keyPressed</code> and <code>keyReleased</code> call. 393 */ 394 public class MyKeyHandler implements XKeyHandler { 395 /** 396 * This event sets the member <code>m_keyPressed</coed> to 397 * <code>true</code> 398 * @param oEvent The key event informs about the pressed key. 399 * @return returns <CODE>TRUE</CODE> in erery case 400 */ 401 public boolean keyPressed( KeyEvent oEvent ){ 402 System.out.println("XKeyHandler: keyPressed-Event"); 403 m_keyPressed = true; 404 return true; 405 } 406 /** 407 * This event sets the member <code>m_keyReleased</coed> to 408 * <code>true</code> 409 * @param oEvent The key event informs about the pressed key. 410 * @return returns <CODE>TRUE</CODE> in erery case 411 */ 412 public boolean keyReleased( KeyEvent oEvent ){ 413 System.out.println("XKeyHandler: keyReleased-Event"); 414 m_keyReleased = true; 415 return true; 416 } 417 /** 418 * This event does nothing usefull 419 * @param oEvent refers to the object that fired the event. 420 */ 421 public void disposing( EventObject oEvent ){ 422 System.out.println("XKeyHandler: disposing-Event"); 423 } 424 } 425 426 /** 427 * Listener which added and its method must be called 428 * on <code>mousePressed</code> and <code>mouseReleased</code> call. 429 */ 430 public class MyMouseClickHandler implements XMouseClickHandler { 431 /** 432 * This event sets the member <code>m_mousePressed</coed> to 433 * <code>true</code> 434 * @param oEvent The mouse event informs about the kind of mouse event. 435 * @return returns <CODE>TRUE</CODE> in erery case 436 */ 437 public boolean mousePressed( MouseEvent oEvent ){ 438 System.out.println("XMouseClickHandler: mousePressed-Event"); 439 m_mousePressed = true; 440 return true; 441 } 442 /** 443 * This event sets the member <code>m_mouseReleased</coed> to 444 * <code>true</code> 445 * @param oEvent The mouse event informs about the kind of mouse event. 446 * @return returns <CODE>TRUE</CODE> in erery case 447 */ 448 public boolean mouseReleased( MouseEvent oEvent ){ 449 System.out.println("XMouseClickHandler: mouseReleased-Event"); 450 m_mouseReleased = true; 451 return true; 452 } 453 /** 454 * This event does nothing usefull 455 * @param oEvent refers to the object that fired the event. 456 */ 457 public void disposing( EventObject oEvent ){ 458 System.out.println("XMouseClickHandler: disposing-Event"); 459 } 460 }; 461 462 /** 463 * To check the events this class is a thread which click a mouse button and 464 * press a key with the <CODE>Robot</CODE> class 465 * @see java.awt.Robot 466 */ 467 private class EventTrigger extends Thread{ 468 469 /** 470 * represents a <CODE>AccessibilityTools</CODE> 471 */ 472 private final AccessibilityTools at = new AccessibilityTools(); 473 /** 474 * represents an <CODE>EventType</CODE> 475 * @see EventTest.EventTriggerType 476 */ 477 private int eventType = 0; 478 /** 479 * represents a <CODE>XModel</CODE> of a document 480 */ 481 private XModel xModel = null; 482 483 /** 484 * Creates an instacne of this class. The parameter <CODE>eType</CODE> represents 485 * the kind of event wich will be triggert at <CODE>run()</CODE> 486 * @param model the model of a document 487 * @param eType the kind of event which should be trigger 488 */ 489 public EventTrigger(XModel model, int eType) 490 { 491 this.xModel = model; 492 this.eventType = eType; 493 } 494 495 /** 496 * Triggers the event wich is represented by <CODE>eventType</CODE> 497 * The scenarios are: 498 * <ul> 499 * <li>EventTest.EventTriggerType.MOUSE_KLICK_INTO_DOC 500 * which calls 501 * <li><CODE>clickIntoDoc</CODE></LI> 502 * </LI> 503 * <li>EventTest.EventTriggerType.KEY_TEXT_INTO_DOC 504 * which calls 505 * <li><CODE>clickIntodoc</CODE></LI> 506 * <li><CODE>keyIntoDoc</CODE></LI> 507 * </LI> 508 * </UL> 509 */ 510 public void run(){ 511 512 switch (this.eventType){ 513 514 case EventTriggerType.MOUSE_KLICK_INTO_DOC: 515 clickIntoDoc(); 516 break; 517 case EventTriggerType.KEY_TEXT_INTO_DOC: 518 clickIntoDoc(); 519 keyIntoDoc(); 520 break; 521 522 } 523 } 524 /** 525 * This method cklicks into the middel of a document. It uses Accessibility 526 * to get the document and query for its position and its range to calculate 527 * the middle. This values was used for <CODE>Robot</CODE> Class. This 528 * Robot class is able to move the mouse and to cklick a mouse button 529 * @see java.awt.Robot 530 */ 531 private void clickIntoDoc(){ 532 try{ 533 // get the position and the range of a scroll bar 534 535 XWindow xWindow = at.getCurrentWindow( 536 getMSF(), 537 xModel); 538 539 XAccessible xRoot = at.getAccessibleObject(xWindow); 540 541 542 543 XAccessibleContext xPanel = at.getAccessibleObjectForRole(xRoot, AccessibleRole.PANEL); 544 XAccessibleComponent xPanelCont = UnoRuntime.queryInterface(XAccessibleComponent.class, xPanel); 545 546 // the position of the panel 547 Point point = xPanelCont.getLocationOnScreen(); 548 549 // the range of the panel 550 Rectangle rect = xPanelCont.getBounds(); 551 552 try { 553 Robot rob = new Robot(); 554 int x = point.X + (rect.Width / 2); 555 int y = point.Y + (rect.Height / 2); 556 System.out.println("try to klick into the middle of the document"); 557 rob.mouseMove(x, y); 558 rob.mousePress(InputEvent.BUTTON1_MASK); 559 rob.mouseRelease(InputEvent.BUTTON1_MASK); 560 } catch (java.awt.AWTException e) { 561 System.out.println("couldn't press mouse button"); 562 } 563 } catch (java.lang.Exception e){ 564 System.out.println("could not click into the scroll bar: " + e.toString()); 565 } 566 } 567 568 /** 569 * This method press the "A" key. Therefore it uses the <CODE>Robot</CODE> 570 * class. 571 * @see java.awt.Robot 572 */ 573 private void keyIntoDoc(){ 574 try { 575 Robot rob = new Robot(); 576 System.out.println("try to press 'A'"); 577 rob.keyPress(java.awt.event.KeyEvent.VK_A); 578 rob.keyRelease(java.awt.event.KeyEvent.VK_A); 579 } catch (java.awt.AWTException e) { 580 System.out.println("couldn't press key"); 581 } 582 583 } 584 } 585 586 /** This interface represents all possible actions which could be used 587 * in the <CODE>EventTrigger</CODE> class. 588 * @see EventTest.EventTrigger 589 */ 590 private interface EventTriggerType{ 591 592 /** klick the mouse into the scroll bar*/ 593 final public static int MOUSE_KLICK_INTO_DOC = 1; 594 595 /** write some text into a spread sheet*/ 596 final public static int KEY_TEXT_INTO_DOC = 2; 597 } 598 599 600 601 602 private XMultiServiceFactory getMSF() 603 { 604 final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); 605 return xMSF1; 606 } 607 608 // setup and close connections 609 @BeforeClass public static void setUpConnection() throws Exception { 610 System.out.println("setUpConnection()"); 611 connection.setUp(); 612 } 613 614 @AfterClass public static void tearDownConnection() 615 throws InterruptedException, com.sun.star.uno.Exception 616 { 617 System.out.println("tearDownConnection()"); 618 connection.tearDown(); 619 } 620 621 private static final OfficeConnection connection = new OfficeConnection(); 622 623 } 624