xref: /trunk/main/sw/source/ui/vba/vbaview.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include "vbaview.hxx"
28 #include <vbahelper/vbahelper.hxx>
29 #include <tools/diagnose_ex.h>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
32 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
33 #include <com/sun/star/text/XText.hpp>
34 #include <com/sun/star/text/XTextTable.hpp>
35 #include <com/sun/star/table/XCellRange.hpp>
36 #include <com/sun/star/text/XTextDocument.hpp>
37 #include <com/sun/star/text/XFootnotesSupplier.hpp>
38 #include <com/sun/star/text/XEndnotesSupplier.hpp>
39 #include <com/sun/star/container/XIndexAccess.hpp>
40 #include <com/sun/star/container/XEnumerationAccess.hpp>
41 #include <com/sun/star/container/XEnumeration.hpp>
42 #include <com/sun/star/frame/XController.hpp>
43 #include <com/sun/star/lang/XServiceInfo.hpp>
44 #include <ooo/vba/word/WdSpecialPane.hpp>
45 #include <ooo/vba/word/WdViewType.hpp>
46 #include <ooo/vba/word/WdSeekView.hpp>
47 
48 #include "wordvbahelper.hxx"
49 #include "vbaheaderfooterhelper.hxx"
50 #include <view.hxx>
51 
52 using namespace ::ooo::vba;
53 using namespace ::com::sun::star;
54 
55 static const sal_Int32 DEFAULT_BODY_DISTANCE = 500;
56 
57 SwVbaView::SwVbaView( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext,
58     const uno::Reference< frame::XModel >& rModel ) throw ( uno::RuntimeException ) :
59     SwVbaView_BASE( rParent, rContext ), mxModel( rModel )
60 {
61     uno::Reference< frame::XController > xController = mxModel->getCurrentController();
62 
63     uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupp( xController, uno::UNO_QUERY_THROW );
64     mxViewCursor = xTextViewCursorSupp->getViewCursor();
65 
66     uno::Reference< view::XViewSettingsSupplier > xViewSettingSupp( xController, uno::UNO_QUERY_THROW );
67     mxViewSettings.set( xViewSettingSupp->getViewSettings(), uno::UNO_QUERY_THROW );
68 }
69 
70 SwVbaView::~SwVbaView()
71 {
72 }
73 
74 ::sal_Int32 SAL_CALL
75 SwVbaView::getSeekView() throw (css::uno::RuntimeException)
76 {
77     // FIXME: if the view cursor is in table, field, section and frame
78     // handle if the cursor is in table
79     uno::Reference< text::XText > xCurrentText = mxViewCursor->getText();
80     uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW );
81     uno::Reference< text::XTextContent > xTextContent;
82     while( xCursorProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("TextTable") ) ) >>= xTextContent )
83     {
84         xCurrentText = xTextContent->getAnchor()->getText();
85         xCursorProps.set( xCurrentText->createTextCursor(), uno::UNO_QUERY_THROW );
86     }
87     uno::Reference< lang::XServiceInfo > xServiceInfo( xCurrentText, uno::UNO_QUERY_THROW );
88     rtl::OUString aImplName = xServiceInfo->getImplementationName();
89     if( aImplName.equalsAscii("SwXBodyText") )
90     {
91         return word::WdSeekView::wdSeekMainDocument;
92     }
93     else if( aImplName.equalsAscii("SwXHeadFootText") )
94     {
95         if( HeaderFooterHelper::isHeader( mxModel, xCurrentText ) )
96         {
97             if( HeaderFooterHelper::isFirstPageHeader( mxModel, xCurrentText ) )
98                 return word::WdSeekView::wdSeekFirstPageHeader;
99             else if( HeaderFooterHelper::isEvenPagesHeader( mxModel, xCurrentText ) )
100                 return word::WdSeekView::wdSeekEvenPagesHeader;
101             else
102                 return word::WdSeekView::wdSeekPrimaryHeader;
103         }
104         else
105         {
106             if( HeaderFooterHelper::isFirstPageFooter( mxModel, xCurrentText ) )
107                 return word::WdSeekView::wdSeekFirstPageFooter;
108             else if( HeaderFooterHelper::isEvenPagesFooter( mxModel, xCurrentText ) )
109                 return word::WdSeekView::wdSeekEvenPagesFooter;
110             else
111                 return word::WdSeekView::wdSeekPrimaryFooter;
112         }
113     }
114     else if( aImplName.equalsAscii("SwXFootnote") )
115     {
116         if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Endnote") ) ) )
117             return word::WdSeekView::wdSeekEndnotes;
118         else
119             return word::WdSeekView::wdSeekFootnotes;
120     }
121 
122     return word::WdSeekView::wdSeekMainDocument;
123 }
124 
125 void SAL_CALL
126 SwVbaView::setSeekView( ::sal_Int32 _seekview ) throw (css::uno::RuntimeException)
127 {
128     // FIXME: save the current cursor position, if the cursor is in the main
129     // document, so we can jump back to this position, if the macro sets
130     // the ViewMode back to wdSeekMainDocument
131 
132     // if( _seekview == getSeekView() )
133     //    return;
134 
135     switch( _seekview )
136     {
137         case word::WdSeekView::wdSeekFirstPageFooter:
138         case word::WdSeekView::wdSeekFirstPageHeader:
139         case word::WdSeekView::wdSeekCurrentPageFooter:
140         case word::WdSeekView::wdSeekCurrentPageHeader:
141         case word::WdSeekView::wdSeekPrimaryFooter:
142         case word::WdSeekView::wdSeekPrimaryHeader:
143         case word::WdSeekView::wdSeekEvenPagesFooter:
144         case word::WdSeekView::wdSeekEvenPagesHeader:
145         {
146             // need to test
147             mxViewCursor->gotoRange( getHFTextRange( _seekview ), sal_False );
148             break;
149         }
150         case word::WdSeekView::wdSeekFootnotes:
151         {
152             uno::Reference< text::XFootnotesSupplier > xFootnotesSupp( mxModel, uno::UNO_QUERY_THROW );
153             uno::Reference< container::XIndexAccess > xFootnotes( xFootnotesSupp->getFootnotes(), uno::UNO_QUERY_THROW );
154             if( xFootnotes->getCount() > 0 )
155             {
156                 uno::Reference< text::XText > xText( xFootnotes->getByIndex(0), uno::UNO_QUERY_THROW );
157                 mxViewCursor->gotoRange( xText->getStart(), sal_False );
158             }
159             else
160             {
161                 DebugHelper::exception( SbERR_NO_ACTIVE_OBJECT, rtl::OUString() );
162             }
163             break;
164         }
165         case word::WdSeekView::wdSeekEndnotes:
166         {
167             uno::Reference< text::XEndnotesSupplier > xEndnotesSupp( mxModel, uno::UNO_QUERY_THROW );
168             uno::Reference< container::XIndexAccess > xEndnotes( xEndnotesSupp->getEndnotes(), uno::UNO_QUERY_THROW );
169             if( xEndnotes->getCount() > 0 )
170             {
171                 uno::Reference< text::XText > xText( xEndnotes->getByIndex(0), uno::UNO_QUERY_THROW );
172                 mxViewCursor->gotoRange( xText->getStart(), sal_False );
173             }
174             else
175             {
176                 DebugHelper::exception( SbERR_NO_ACTIVE_OBJECT, rtl::OUString() );
177             }
178             break;
179         }
180         case word::WdSeekView::wdSeekMainDocument:
181         {
182             uno::Reference< text::XTextDocument > xTextDocument( mxModel, uno::UNO_QUERY_THROW );
183             uno::Reference< text::XText > xText = xTextDocument->getText();
184             mxViewCursor->gotoRange( getFirstObjectPosition( xText ), sal_False );
185             break;
186         }
187     }
188 }
189 
190 ::sal_Int32 SAL_CALL
191 SwVbaView::getSplitSpecial() throw (css::uno::RuntimeException)
192 {
193     return word::WdSpecialPane::wdPaneNone;
194 }
195 
196 void SAL_CALL
197 SwVbaView::setSplitSpecial( ::sal_Int32/* _splitspecial */) throw (css::uno::RuntimeException)
198 {
199     // not support in Writer
200 }
201 
202 ::sal_Bool SAL_CALL
203 SwVbaView::getTableGridLines() throw (css::uno::RuntimeException)
204 {
205     sal_Bool bShowTableGridLine = sal_False;
206     mxViewSettings->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowTableBoundaries"))) >>= bShowTableGridLine;
207     return bShowTableGridLine;
208 }
209 
210 void SAL_CALL
211 SwVbaView::setTableGridLines( ::sal_Bool _tablegridlines ) throw (css::uno::RuntimeException)
212 {
213     mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowTableBoundaries")), uno::makeAny( _tablegridlines ) );
214 }
215 
216 ::sal_Int32 SAL_CALL
217 SwVbaView::getType() throw (css::uno::RuntimeException)
218 {
219     // FIXME: handle wdPrintPreview type
220     sal_Bool bOnlineLayout = sal_False;
221     mxViewSettings->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout"))) >>= bOnlineLayout;
222     return bOnlineLayout ? word::WdViewType::wdWebView : word::WdViewType::wdPrintView;
223 }
224 
225 void SAL_CALL
226 SwVbaView::setType( ::sal_Int32 _type ) throw (css::uno::RuntimeException)
227 {
228     // FIXME: handle wdPrintPreview type
229     switch( _type )
230     {
231         case word::WdViewType::wdPrintView:
232         case word::WdViewType::wdNormalView:
233         {
234             mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout")), uno::makeAny( sal_False ) );
235             break;
236         }
237         case word::WdViewType::wdWebView:
238         {
239             mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout")), uno::makeAny( sal_True ) );
240             break;
241         }
242         case word::WdViewType::wdPrintPreview:
243         {
244             PrintPreviewHelper( uno::Any(),word::getView( mxModel ) );
245             break;
246         }
247         default:
248             DebugHelper::exception( SbERR_NOT_IMPLEMENTED, rtl::OUString() );
249 
250     }
251 }
252 
253 uno::Reference< text::XTextRange > SwVbaView::getHFTextRange( sal_Int32 nType ) throw (uno::RuntimeException)
254 {
255     mxModel->lockControllers();
256 
257     rtl::OUString aPropIsOn;
258     rtl::OUString aPropIsShared;
259     rtl::OUString aPropBodyDistance;
260     rtl::OUString aPropText;
261 
262     switch( nType )
263     {
264         case word::WdSeekView::wdSeekCurrentPageFooter:
265         case word::WdSeekView::wdSeekFirstPageFooter:
266         case word::WdSeekView::wdSeekPrimaryFooter:
267         case word::WdSeekView::wdSeekEvenPagesFooter:
268         {
269             aPropIsOn = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterIsOn") );
270             aPropIsShared = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterIsShared") );
271             aPropBodyDistance = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterBodyDistance") );
272             aPropText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterText") );
273             break;
274         }
275         case word::WdSeekView::wdSeekCurrentPageHeader:
276         case word::WdSeekView::wdSeekFirstPageHeader:
277         case word::WdSeekView::wdSeekPrimaryHeader:
278         case word::WdSeekView::wdSeekEvenPagesHeader:
279         {
280             aPropIsOn = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderIsOn") );
281             aPropIsShared = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderIsShared") );
282             aPropBodyDistance = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderBodyDistance") );
283             aPropText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderText") );
284             break;
285         }
286     }
287 
288     uno::Reference< text::XPageCursor > xPageCursor( mxViewCursor, uno::UNO_QUERY_THROW );
289 
290     if( nType == word::WdSeekView::wdSeekFirstPageFooter
291         || nType == word::WdSeekView::wdSeekFirstPageHeader )
292     {
293         xPageCursor->jumpToFirstPage();
294     }
295 
296     uno::Reference< style::XStyle > xStyle;
297     uno::Reference< text::XText > xText;
298     switch( nType )
299     {
300         case word::WdSeekView::wdSeekPrimaryFooter:
301         case word::WdSeekView::wdSeekPrimaryHeader:
302         case word::WdSeekView::wdSeekEvenPagesFooter:
303         case word::WdSeekView::wdSeekEvenPagesHeader:
304         {
305             // The primary header is the first header of the section.
306             // If the header is not shared between odd and even pages
307             // the odd page's header is the primary header. If the
308             // first page's header is different from the rest of the
309             // document, it is NOT the primary header ( the next primary
310             // header would be on page 3 )
311             // The even pages' header is only available if the header is
312             // not shared and the current style is applied to a page with
313             // an even page number
314             uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW );
315             rtl::OUString aPageStyleName;
316             xCursorProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PageStyleName"))) >>= aPageStyleName;
317             if( aPageStyleName.equalsAscii("First Page") )
318             {
319                 // go to the beginning of where the next style is used
320                 sal_Bool hasNextPage = sal_False;
321                 xStyle = word::getCurrentPageStyle( mxModel );
322                 do
323                 {
324                     hasNextPage = xPageCursor->jumpToNextPage();
325                 }
326                 while( hasNextPage && ( xStyle == word::getCurrentPageStyle( mxModel ) ) );
327 
328                 if( !hasNextPage )
329                     DebugHelper::exception( SbERR_BAD_ACTION, rtl::OUString() );
330             }
331             break;
332         }
333         default:
334         {
335             break;
336         }
337     }
338 
339     xStyle = word::getCurrentPageStyle( mxModel );
340     uno::Reference< beans::XPropertySet > xPageProps( xStyle, uno::UNO_QUERY_THROW );
341     sal_Bool isOn = sal_False;
342     xPageProps->getPropertyValue( aPropIsOn ) >>= isOn;
343     sal_Bool isShared =  sal_False;
344     xPageProps->getPropertyValue( aPropIsShared ) >>= isShared;
345     if( !isOn )
346     {
347         xPageProps->setPropertyValue( aPropIsOn, uno::makeAny( sal_True ) );
348         xPageProps->setPropertyValue( aPropBodyDistance, uno::makeAny( DEFAULT_BODY_DISTANCE ) );
349     }
350     if( !isShared )
351     {
352         rtl::OUString aTempPropText = aPropText;
353         if( nType == word::WdSeekView::wdSeekEvenPagesFooter
354             || nType == word::WdSeekView::wdSeekEvenPagesHeader )
355         {
356             aTempPropText += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Left") );
357         }
358         else
359         {
360             aTempPropText += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Right") );
361         }
362         xText.set( xPageProps->getPropertyValue( aTempPropText), uno::UNO_QUERY_THROW );
363     }
364     else
365     {
366         if( nType == word::WdSeekView::wdSeekEvenPagesFooter
367             || nType == word::WdSeekView::wdSeekEvenPagesHeader )
368         {
369             DebugHelper::exception( SbERR_BAD_ACTION, rtl::OUString() );
370         }
371         xText.set( xPageProps->getPropertyValue( aPropText ), uno::UNO_QUERY_THROW );
372     }
373 
374     mxModel->unlockControllers();
375     if( !xText.is() )
376     {
377         DebugHelper::exception( SbERR_INTERNAL_ERROR, rtl::OUString() );
378     }
379     uno::Reference< text::XTextRange > xTextRange = getFirstObjectPosition( xText );
380     return xTextRange;
381 }
382 
383 uno::Reference< text::XTextRange > SwVbaView::getFirstObjectPosition( const uno::Reference< text::XText >& xText ) throw (uno::RuntimeException)
384 {
385     // if the first object is table, get the position of first cell
386     uno::Reference< text::XTextRange > xTextRange;
387     uno::Reference< container::XEnumerationAccess > xParaAccess( xText, uno::UNO_QUERY_THROW );
388     uno::Reference< container::XEnumeration> xParaEnum = xParaAccess->createEnumeration();
389     if( xParaEnum->hasMoreElements() )
390     {
391         uno::Reference< lang::XServiceInfo > xServiceInfo( xParaEnum->nextElement(), uno::UNO_QUERY_THROW );
392         if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextTable") ) ) )
393         {
394             uno::Reference< table::XCellRange > xCellRange( xServiceInfo, uno::UNO_QUERY_THROW );
395             uno::Reference< text::XText> xFirstCellText( xCellRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW );
396             xTextRange = xFirstCellText->getStart();
397         }
398     }
399     if( !xTextRange.is() )
400         xTextRange = xText->getStart();
401     return xTextRange;
402 }
403 
404 rtl::OUString&
405 SwVbaView::getServiceImplName()
406 {
407 	static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaView") );
408 	return sImplName;
409 }
410 
411 uno::Sequence< rtl::OUString >
412 SwVbaView::getServiceNames()
413 {
414 	static uno::Sequence< rtl::OUString > aServiceNames;
415 	if ( aServiceNames.getLength() == 0 )
416 	{
417 		aServiceNames.realloc( 1 );
418 		aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.View" ) );
419 	}
420 	return aServiceNames;
421 }
422 
423