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