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