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 19 package complex.sfx2.undo; 20 21 import com.sun.star.awt.Rectangle; 22 import com.sun.star.document.XUndoManager; 23 import com.sun.star.document.XUndoManagerSupplier; 24 import com.sun.star.document.XUndoAction; 25 import com.sun.star.awt.Point; 26 import com.sun.star.awt.Size; 27 import com.sun.star.beans.XPropertySet; 28 import com.sun.star.drawing.CircleKind; 29 import com.sun.star.drawing.XDrawPages; 30 import com.sun.star.drawing.XDrawPagesSupplier; 31 import com.sun.star.drawing.XShape; 32 import com.sun.star.drawing.XShapes; 33 import com.sun.star.lang.XMultiServiceFactory; 34 import com.sun.star.uno.UnoRuntime; 35 import org.openoffice.test.tools.DocumentType; 36 import static org.junit.Assert.*; 37 38 /** 39 * implements the {@link DocumentTest} interface on top of a drawing document 40 */ 41 public abstract class DrawingOrPresentationDocumentTest extends DocumentTestBase 42 { DrawingOrPresentationDocumentTest( XMultiServiceFactory i_orb, final DocumentType i_docType )43 public DrawingOrPresentationDocumentTest( XMultiServiceFactory i_orb, final DocumentType i_docType ) throws com.sun.star.uno.Exception 44 { 45 super( i_orb, i_docType ); 46 } 47 initializeDocument()48 public void initializeDocument() throws com.sun.star.uno.Exception 49 { 50 // remove all shapes - Impress has two default shapes in a new doc; just get rid of them 51 final XShapes firstPageShapes = getFirstPageShapes(); 52 while ( firstPageShapes.getCount() > 0 ) 53 firstPageShapes.remove( UnoRuntime.queryInterface( XShape.class, firstPageShapes.getByIndex( 0 ) ) ); 54 } 55 doSingleModification()56 public void doSingleModification() throws com.sun.star.uno.Exception 57 { 58 // add a simple centered shape to the first page 59 Rectangle pagePlayground = impl_getFirstPagePlayground(); 60 impl_createCircleShape( 61 ( pagePlayground.X + ( pagePlayground.Width - BIG_CIRCLE_SIZE ) / 2 ), 62 ( pagePlayground.Y + ( pagePlayground.Height - BIG_CIRCLE_SIZE ) / 2 ), 63 BIG_CIRCLE_SIZE, 64 FILL_COLOR 65 ); 66 } 67 verifyInitialDocumentState()68 public void verifyInitialDocumentState() throws com.sun.star.uno.Exception 69 { 70 final XShapes firstPageShapes = getFirstPageShapes(); 71 assertEquals( "there should be no shapes at all", 0, firstPageShapes.getCount() ); 72 } 73 verifySingleModificationDocumentState()74 public void verifySingleModificationDocumentState() throws com.sun.star.uno.Exception 75 { 76 final XShapes firstPageShapes = getFirstPageShapes(); 77 assertEquals( "there should be one shape, not more, not less", 1, firstPageShapes.getCount() ); 78 79 final Object shape = firstPageShapes.getByIndex(0); 80 verifyShapeGeometry( shape, BIG_CIRCLE_SIZE, BIG_CIRCLE_SIZE ); 81 final XPropertySet shapeProps = UnoRuntime.queryInterface( XPropertySet.class, shape ); 82 assertEquals( "wrong circle type", CIRCLE_TYPE.getValue(), ((CircleKind)shapeProps.getPropertyValue( "CircleKind" )).getValue() ); 83 //assertEquals( "wrong circle fill color", FILL_COLOR, ((Integer)shapeProps.getPropertyValue( "FillColor" )).intValue() ); 84 // disable this particular check: A bug in the drawing layer API restores the FillColor to its 85 // default value upon re-insertion. This is issue #i115080# 86 } 87 doMultipleModifications()88 public int doMultipleModifications() throws com.sun.star.uno.Exception 89 { 90 // add a simple centered shape to the first page 91 Rectangle pagePlayground = impl_getFirstPagePlayground(); 92 impl_createCircleShape( 93 pagePlayground.X, 94 pagePlayground.Y, 95 SMALL_CIRCLE_SIZE, 96 ALTERNATE_FILL_COLOR 97 ); 98 impl_createCircleShape( 99 pagePlayground.X + pagePlayground.Width - SMALL_CIRCLE_SIZE, 100 pagePlayground.Y, 101 SMALL_CIRCLE_SIZE, 102 ALTERNATE_FILL_COLOR 103 ); 104 impl_createCircleShape( 105 pagePlayground.X, 106 pagePlayground.Y + pagePlayground.Height - SMALL_CIRCLE_SIZE, 107 SMALL_CIRCLE_SIZE, 108 ALTERNATE_FILL_COLOR 109 ); 110 impl_createCircleShape( 111 pagePlayground.X + pagePlayground.Width - SMALL_CIRCLE_SIZE, 112 pagePlayground.Y + pagePlayground.Height - SMALL_CIRCLE_SIZE, 113 SMALL_CIRCLE_SIZE, 114 ALTERNATE_FILL_COLOR 115 ); 116 return 4; 117 } 118 impl_createCircleShape( final int i_x, final int i_y, final int i_size, final int i_color )119 private void impl_createCircleShape( final int i_x, final int i_y, final int i_size, final int i_color ) throws com.sun.star.uno.Exception 120 { 121 final XPropertySet shapeProps = getDocument().createInstance( "com.sun.star.drawing.EllipseShape", XPropertySet.class ); 122 shapeProps.setPropertyValue( "CircleKind", CIRCLE_TYPE ); 123 shapeProps.setPropertyValue( "FillColor", i_color ); 124 125 final XShape shape = UnoRuntime.queryInterface( XShape.class, shapeProps ); 126 final Size shapeSize = new Size( i_size, i_size ); 127 shape.setSize( shapeSize ); 128 final Point shapePos = new Point( i_x, i_y ); 129 shape.setPosition( shapePos ); 130 131 final XShapes pageShapes = UnoRuntime.queryInterface( XShapes.class, getFirstPageShapes() ); 132 pageShapes.add( shape ); 133 134 // Sadly, Draw/Impress currently do not create Undo actions for programmatic changes to the document. 135 // Which renders the test here slightly useless ... unless we fake the Undo actions ourself. 136 final XUndoManagerSupplier suppUndoManager = UnoRuntime.queryInterface( XUndoManagerSupplier.class, getDocument().getDocument() ); 137 final XUndoManager undoManager = suppUndoManager.getUndoManager(); 138 undoManager.addUndoAction( new ShapeInsertionUndoAction( shape, pageShapes ) ); 139 } 140 impl_getFirstPagePlayground()141 private Rectangle impl_getFirstPagePlayground() throws com.sun.star.uno.Exception 142 { 143 final XShapes firstPageShapes = getFirstPageShapes(); 144 final XPropertySet firstPageProps = UnoRuntime.queryInterface( XPropertySet.class, firstPageShapes ); 145 final int pageWidth = ((Integer)firstPageProps.getPropertyValue( "Width" )).intValue(); 146 final int pageHeight = ((Integer)firstPageProps.getPropertyValue( "Height" )).intValue(); 147 final int borderLeft = ((Integer)firstPageProps.getPropertyValue( "BorderLeft" )).intValue(); 148 final int borderTop = ((Integer)firstPageProps.getPropertyValue( "BorderTop" )).intValue(); 149 final int borderRight = ((Integer)firstPageProps.getPropertyValue( "BorderRight" )).intValue(); 150 final int borderBottom = ((Integer)firstPageProps.getPropertyValue( "BorderBottom" )).intValue(); 151 return new Rectangle( borderLeft, borderTop, pageWidth - borderLeft - borderRight, pageHeight - borderTop - borderBottom ); 152 } 153 154 /** 155 * returns the XShapes interface of the first page of our drawing document 156 */ getFirstPageShapes()157 private XShapes getFirstPageShapes() throws com.sun.star.uno.Exception 158 { 159 final XDrawPagesSupplier suppPages = UnoRuntime.queryInterface( XDrawPagesSupplier.class, getDocument().getDocument() ); 160 final XDrawPages pages = suppPages.getDrawPages(); 161 return UnoRuntime.queryInterface( XShapes.class, pages.getByIndex( 0 ) ); 162 } 163 164 /** 165 * verifies the given shape has the given size 166 */ verifyShapeGeometry( final Object i_shapeObject, final int i_expectedWidth, final int i_expectedHeight )167 private void verifyShapeGeometry( final Object i_shapeObject, final int i_expectedWidth, final int i_expectedHeight ) 168 { 169 final XShape shape = UnoRuntime.queryInterface( XShape.class, i_shapeObject ); 170 final Size shapeSize = shape.getSize(); 171 assertEquals( "unexpected shape width", i_expectedWidth, shapeSize.Width ); 172 assertEquals( "unexpected shape height", i_expectedHeight, shapeSize.Height ); 173 } 174 175 private static class ShapeInsertionUndoAction implements XUndoAction 176 { ShapeInsertionUndoAction( final XShape i_shape, final XShapes i_shapeCollection )177 ShapeInsertionUndoAction( final XShape i_shape, final XShapes i_shapeCollection ) 178 { 179 m_shape = i_shape; 180 m_shapeCollection = i_shapeCollection; 181 } 182 getTitle()183 public String getTitle() 184 { 185 return "insert shape"; 186 } 187 undo()188 public void undo() 189 { 190 m_shapeCollection.remove( m_shape ); 191 } 192 redo()193 public void redo() 194 { 195 m_shapeCollection.add( m_shape ); 196 } 197 198 private final XShape m_shape; 199 private final XShapes m_shapeCollection; 200 } 201 202 private static CircleKind CIRCLE_TYPE = CircleKind.FULL; 203 private static int FILL_COLOR = 0xCC2244; 204 private static int ALTERNATE_FILL_COLOR = 0x44CC22; 205 private static int BIG_CIRCLE_SIZE = 5000; 206 private static int SMALL_CIRCLE_SIZE = 2000; 207 } 208