summaryrefslogtreecommitdiffstats
path: root/sfx2/qa/complex/sfx2/undo/DrawingOrPresentationDocumentTest.java
blob: 37b5d0d9cd7cd88b4ebadc3ab4337b8b97e22ecc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

package complex.sfx2.undo;

import com.sun.star.awt.Rectangle;
import com.sun.star.document.XUndoManager;
import com.sun.star.document.XUndoManagerSupplier;
import com.sun.star.document.XUndoAction;
import com.sun.star.awt.Point;
import com.sun.star.awt.Size;
import com.sun.star.beans.XPropertySet;
import com.sun.star.drawing.CircleKind;
import com.sun.star.drawing.XDrawPages;
import com.sun.star.drawing.XDrawPagesSupplier;
import com.sun.star.drawing.XShape;
import com.sun.star.drawing.XShapes;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.uno.UnoRuntime;
import org.openoffice.test.tools.DocumentType;
import static org.junit.Assert.*;

/**
 * implements the {@link DocumentTest} interface on top of a drawing document
 */
public abstract class DrawingOrPresentationDocumentTest extends DocumentTestBase
{
    public DrawingOrPresentationDocumentTest( XMultiServiceFactory i_orb, final DocumentType i_docType ) throws com.sun.star.uno.Exception
    {
        super( i_orb, i_docType );
    }

    public void initializeDocument() throws com.sun.star.uno.Exception
    {
        // remove all shapes - Impress has two default shapes in a new doc; just get rid of them
        final XShapes firstPageShapes = getFirstPageShapes();
        while ( firstPageShapes.getCount() > 0 )
            firstPageShapes.remove( UnoRuntime.queryInterface( XShape.class, firstPageShapes.getByIndex( 0 ) ) );
    }

    public void doSingleModification() throws com.sun.star.uno.Exception
    {
        // add a simple centered shape to the first page
        Rectangle pagePlayground = impl_getFirstPagePlayground();
        impl_createCircleShape(
            ( pagePlayground.X + ( pagePlayground.Width - BIG_CIRCLE_SIZE ) / 2 ),
            ( pagePlayground.Y + ( pagePlayground.Height - BIG_CIRCLE_SIZE ) / 2 ),
            BIG_CIRCLE_SIZE,
            FILL_COLOR
        );
    }

    public void verifyInitialDocumentState() throws com.sun.star.uno.Exception
    {
        final XShapes firstPageShapes = getFirstPageShapes();
        assertEquals( "there should be no shapes at all", 0, firstPageShapes.getCount() );
    }

    public void verifySingleModificationDocumentState() throws com.sun.star.uno.Exception
    {
        final XShapes firstPageShapes = getFirstPageShapes();
        assertEquals( "there should be one shape, not more, not less", 1, firstPageShapes.getCount() );

        final Object shape = firstPageShapes.getByIndex(0);
        verifyShapeGeometry( shape, BIG_CIRCLE_SIZE, BIG_CIRCLE_SIZE );
        final XPropertySet shapeProps = UnoRuntime.queryInterface( XPropertySet.class, shape );
        assertEquals( "wrong circle type", CIRCLE_TYPE.getValue(), ((CircleKind)shapeProps.getPropertyValue( "CircleKind" )).getValue() );
        //assertEquals( "wrong circle fill color", FILL_COLOR, ((Integer)shapeProps.getPropertyValue( "FillColor" )).intValue() );
            // disable this particular check: A bug in the drawing layer API restores the FillColor to its
            // default value upon re-insertion. This is issue #i115080#
    }

    public int doMultipleModifications() throws com.sun.star.uno.Exception
    {
        // add a simple centered shape to the first page
        Rectangle pagePlayground = impl_getFirstPagePlayground();
        impl_createCircleShape(
            pagePlayground.X,
            pagePlayground.Y,
            SMALL_CIRCLE_SIZE,
            ALTERNATE_FILL_COLOR
        );
        impl_createCircleShape(
            pagePlayground.X + pagePlayground.Width - SMALL_CIRCLE_SIZE,
            pagePlayground.Y,
            SMALL_CIRCLE_SIZE,
            ALTERNATE_FILL_COLOR
        );
        impl_createCircleShape(
            pagePlayground.X,
            pagePlayground.Y + pagePlayground.Height - SMALL_CIRCLE_SIZE,
            SMALL_CIRCLE_SIZE,
            ALTERNATE_FILL_COLOR
        );
        impl_createCircleShape(
            pagePlayground.X + pagePlayground.Width - SMALL_CIRCLE_SIZE,
            pagePlayground.Y + pagePlayground.Height - SMALL_CIRCLE_SIZE,
            SMALL_CIRCLE_SIZE,
            ALTERNATE_FILL_COLOR
        );
        return 4;
    }

    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
    {
        final XPropertySet shapeProps = getDocument().createInstance( "com.sun.star.drawing.EllipseShape", XPropertySet.class );
        shapeProps.setPropertyValue( "CircleKind", CIRCLE_TYPE );
        shapeProps.setPropertyValue( "FillColor", i_color );

        final XShape shape = UnoRuntime.queryInterface( XShape.class, shapeProps );
        final Size shapeSize = new Size( i_size, i_size );
        shape.setSize( shapeSize );
        final Point shapePos = new Point( i_x, i_y );
        shape.setPosition( shapePos );

        final XShapes pageShapes = UnoRuntime.queryInterface( XShapes.class, getFirstPageShapes() );
        pageShapes.add( shape );

        // Sadly, Draw/Impress currently do not create Undo actions for programmatic changes to the document.
        // Which renders the test here slightly useless ... unless we fake the Undo actions ourself.
        final XUndoManagerSupplier suppUndoManager = UnoRuntime.queryInterface( XUndoManagerSupplier.class, getDocument().getDocument() );
        final XUndoManager undoManager = suppUndoManager.getUndoManager();
        undoManager.addUndoAction( new ShapeInsertionUndoAction( shape, pageShapes ) );
    }

    private Rectangle impl_getFirstPagePlayground() throws com.sun.star.uno.Exception
    {
        final XShapes firstPageShapes = getFirstPageShapes();
        final XPropertySet firstPageProps = UnoRuntime.queryInterface( XPropertySet.class, firstPageShapes );
        final int pageWidth = ((Integer)firstPageProps.getPropertyValue( "Width" )).intValue();
        final int pageHeight = ((Integer)firstPageProps.getPropertyValue( "Height" )).intValue();
        final int borderLeft = ((Integer)firstPageProps.getPropertyValue( "BorderLeft" )).intValue();
        final int borderTop = ((Integer)firstPageProps.getPropertyValue( "BorderTop" )).intValue();
        final int borderRight = ((Integer)firstPageProps.getPropertyValue( "BorderRight" )).intValue();
        final int borderBottom = ((Integer)firstPageProps.getPropertyValue( "BorderBottom" )).intValue();
        return new Rectangle( borderLeft, borderTop, pageWidth - borderLeft - borderRight, pageHeight - borderTop - borderBottom );
    }

    /**
     * returns the XShapes interface of the first page of our drawing document
     */
    private XShapes getFirstPageShapes() throws com.sun.star.uno.Exception
    {
        final XDrawPagesSupplier suppPages = UnoRuntime.queryInterface( XDrawPagesSupplier.class, getDocument().getDocument() );
        final XDrawPages pages = suppPages.getDrawPages();
        return UnoRuntime.queryInterface( XShapes.class, pages.getByIndex( 0 ) );
    }

    /**
     * verifies the given shape has the given size
     */
    private void verifyShapeGeometry( final Object i_shapeObject, final int i_expectedWidth, final int i_expectedHeight )
    {
        final XShape shape = UnoRuntime.queryInterface( XShape.class, i_shapeObject );
        final Size shapeSize = shape.getSize();
        assertEquals( "unexpected shape width", i_expectedWidth, shapeSize.Width );
        assertEquals( "unexpected shape height", i_expectedHeight, shapeSize.Height );
    }

    private static class ShapeInsertionUndoAction implements XUndoAction
    {
        ShapeInsertionUndoAction( final XShape i_shape, final XShapes i_shapeCollection )
        {
            m_shape = i_shape;
            m_shapeCollection = i_shapeCollection;
        }

        public String getTitle()
        {
            return "insert shape";
        }

        public void undo()
        {
            m_shapeCollection.remove( m_shape );
        }

        public void redo()
        {
            m_shapeCollection.add( m_shape );
        }

        private final XShape m_shape;
        private final XShapes m_shapeCollection;
    }

    private static CircleKind   CIRCLE_TYPE = CircleKind.FULL;
    private static int          FILL_COLOR = 0xCC2244;
    private static int          ALTERNATE_FILL_COLOR = 0x44CC22;
    private static int          BIG_CIRCLE_SIZE = 5000;
    private static int          SMALL_CIRCLE_SIZE = 2000;
}