xref: /trunk/main/sfx2/qa/complex/sfx2/undo/DrawingOrPresentationDocumentTest.java (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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