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