1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19 #include "vbaview.hxx"
20 #include <vbahelper/vbahelper.hxx>
21 #include <basic/sberrors.hxx>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
24 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
25 #include <com/sun/star/text/XText.hpp>
26 #include <com/sun/star/text/XTextDocument.hpp>
27 #include <com/sun/star/text/XFootnotesSupplier.hpp>
28 #include <com/sun/star/text/XEndnotesSupplier.hpp>
29 #include <com/sun/star/text/XPageCursor.hpp>
30 #include <com/sun/star/container/XIndexAccess.hpp>
31 #include <com/sun/star/frame/XController.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <ooo/vba/word/WdSpecialPane.hpp>
34 #include <ooo/vba/word/WdViewType.hpp>
35 #include <ooo/vba/word/WdSeekView.hpp>
36
37 #include "wordvbahelper.hxx"
38 #include "vbaheaderfooterhelper.hxx"
39 #include <view.hxx>
40
41 using namespace ::ooo::vba;
42 using namespace ::com::sun::star;
43
44 const sal_Int32 DEFAULT_BODY_DISTANCE = 500;
45
SwVbaView(const uno::Reference<ooo::vba::XHelperInterface> & rParent,const uno::Reference<uno::XComponentContext> & rContext,const uno::Reference<frame::XModel> & rModel)46 SwVbaView::SwVbaView( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext,
47 const uno::Reference< frame::XModel >& rModel ) :
48 SwVbaView_BASE( rParent, rContext ), mxModel( rModel )
49 {
50 uno::Reference< frame::XController > xController = mxModel->getCurrentController();
51
52 uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupp( xController, uno::UNO_QUERY_THROW );
53 mxViewCursor = xTextViewCursorSupp->getViewCursor();
54
55 uno::Reference< view::XViewSettingsSupplier > xViewSettingSupp( xController, uno::UNO_QUERY_THROW );
56 mxViewSettings.set( xViewSettingSupp->getViewSettings(), uno::UNO_SET_THROW );
57 }
58
~SwVbaView()59 SwVbaView::~SwVbaView()
60 {
61 }
62
63 ::sal_Int32 SAL_CALL
getSeekView()64 SwVbaView::getSeekView()
65 {
66 // FIXME: if the view cursor is in table, field, section and frame
67 // handle if the cursor is in table
68 uno::Reference< text::XText > xCurrentText = mxViewCursor->getText();
69 uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW );
70 uno::Reference< text::XTextContent > xTextContent;
71 while( xCursorProps->getPropertyValue("TextTable") >>= xTextContent )
72 {
73 xCurrentText = xTextContent->getAnchor()->getText();
74 xCursorProps.set( xCurrentText->createTextCursor(), uno::UNO_QUERY_THROW );
75 }
76 uno::Reference< lang::XServiceInfo > xServiceInfo( xCurrentText, uno::UNO_QUERY_THROW );
77 OUString aImplName = xServiceInfo->getImplementationName();
78 if ( aImplName == "SwXBodyText" )
79 {
80 return word::WdSeekView::wdSeekMainDocument;
81 }
82 else if ( aImplName == "SwXHeadFootText" )
83 {
84 if( HeaderFooterHelper::isHeader( mxModel ) )
85 {
86 if( HeaderFooterHelper::isFirstPageHeader( mxModel ) )
87 return word::WdSeekView::wdSeekFirstPageHeader;
88 else if( HeaderFooterHelper::isEvenPagesHeader( mxModel ) )
89 return word::WdSeekView::wdSeekEvenPagesHeader;
90 else
91 return word::WdSeekView::wdSeekPrimaryHeader;
92 }
93 else
94 {
95 if( HeaderFooterHelper::isFirstPageFooter( mxModel ) )
96 return word::WdSeekView::wdSeekFirstPageFooter;
97 else if( HeaderFooterHelper::isEvenPagesFooter( mxModel ) )
98 return word::WdSeekView::wdSeekEvenPagesFooter;
99 else
100 return word::WdSeekView::wdSeekPrimaryFooter;
101 }
102 }
103 else if ( aImplName == "SwXFootnote" )
104 {
105 if( xServiceInfo->supportsService("com.sun.star.text.Endnote") )
106 return word::WdSeekView::wdSeekEndnotes;
107 else
108 return word::WdSeekView::wdSeekFootnotes;
109 }
110
111 return word::WdSeekView::wdSeekMainDocument;
112 }
113
114 void SAL_CALL
setSeekView(::sal_Int32 _seekview)115 SwVbaView::setSeekView( ::sal_Int32 _seekview )
116 {
117 // FIXME: save the current cursor position, if the cursor is in the main
118 // document, so we can jump back to this position, if the macro sets
119 // the ViewMode back to wdSeekMainDocument
120
121 word::gotoSelectedObjectAnchor( mxModel );
122 switch( _seekview )
123 {
124 case word::WdSeekView::wdSeekFirstPageFooter:
125 case word::WdSeekView::wdSeekFirstPageHeader:
126 case word::WdSeekView::wdSeekCurrentPageFooter:
127 case word::WdSeekView::wdSeekCurrentPageHeader:
128 case word::WdSeekView::wdSeekPrimaryFooter:
129 case word::WdSeekView::wdSeekPrimaryHeader:
130 case word::WdSeekView::wdSeekEvenPagesFooter:
131 case word::WdSeekView::wdSeekEvenPagesHeader:
132 {
133 // need to test
134 mxViewCursor->gotoRange( getHFTextRange( _seekview ), false );
135 break;
136 }
137 case word::WdSeekView::wdSeekFootnotes:
138 {
139 uno::Reference< text::XFootnotesSupplier > xFootnotesSupp( mxModel, uno::UNO_QUERY_THROW );
140 uno::Reference< container::XIndexAccess > xFootnotes( xFootnotesSupp->getFootnotes(), uno::UNO_SET_THROW );
141 if( xFootnotes->getCount() > 0 )
142 {
143 uno::Reference< text::XText > xText( xFootnotes->getByIndex(0), uno::UNO_QUERY_THROW );
144 mxViewCursor->gotoRange( xText->getStart(), false );
145 }
146 else
147 {
148 DebugHelper::runtimeexception( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
149 }
150 break;
151 }
152 case word::WdSeekView::wdSeekEndnotes:
153 {
154 uno::Reference< text::XEndnotesSupplier > xEndnotesSupp( mxModel, uno::UNO_QUERY_THROW );
155 uno::Reference< container::XIndexAccess > xEndnotes( xEndnotesSupp->getEndnotes(), uno::UNO_SET_THROW );
156 if( xEndnotes->getCount() > 0 )
157 {
158 uno::Reference< text::XText > xText( xEndnotes->getByIndex(0), uno::UNO_QUERY_THROW );
159 mxViewCursor->gotoRange( xText->getStart(), false );
160 }
161 else
162 {
163 DebugHelper::runtimeexception( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
164 }
165 break;
166 }
167 case word::WdSeekView::wdSeekMainDocument:
168 {
169 uno::Reference< text::XTextDocument > xTextDocument( mxModel, uno::UNO_QUERY_THROW );
170 uno::Reference< text::XText > xText = xTextDocument->getText();
171 mxViewCursor->gotoRange( word::getFirstObjectPosition( xText ), false );
172 break;
173 }
174 }
175 }
176
177 ::sal_Int32 SAL_CALL
getSplitSpecial()178 SwVbaView::getSplitSpecial()
179 {
180 return word::WdSpecialPane::wdPaneNone;
181 }
182
183 void SAL_CALL
setSplitSpecial(::sal_Int32)184 SwVbaView::setSplitSpecial( ::sal_Int32/* _splitspecial */)
185 {
186 // not support in Writer
187 }
188
189 sal_Bool SAL_CALL
getTableGridLines()190 SwVbaView::getTableGridLines()
191 {
192 bool bShowTableGridLine = false;
193 mxViewSettings->getPropertyValue("ShowTableBoundaries") >>= bShowTableGridLine;
194 return bShowTableGridLine;
195 }
196
197 void SAL_CALL
setTableGridLines(sal_Bool _tablegridlines)198 SwVbaView::setTableGridLines( sal_Bool _tablegridlines )
199 {
200 mxViewSettings->setPropertyValue("ShowTableBoundaries", uno::makeAny( _tablegridlines ) );
201 }
202
203 ::sal_Int32 SAL_CALL
getType()204 SwVbaView::getType()
205 {
206 // FIXME: handle wdPrintPreview type
207 bool bOnlineLayout = false;
208 mxViewSettings->getPropertyValue("ShowOnlineLayout") >>= bOnlineLayout;
209 return bOnlineLayout ? word::WdViewType::wdWebView : word::WdViewType::wdPrintView;
210 }
211
212 void SAL_CALL
setType(::sal_Int32 _type)213 SwVbaView::setType( ::sal_Int32 _type )
214 {
215 // FIXME: handle wdPrintPreview type
216 switch( _type )
217 {
218 case word::WdViewType::wdPrintView:
219 case word::WdViewType::wdNormalView:
220 {
221 mxViewSettings->setPropertyValue("ShowOnlineLayout", uno::makeAny( false ) );
222 break;
223 }
224 case word::WdViewType::wdWebView:
225 {
226 mxViewSettings->setPropertyValue("ShowOnlineLayout", uno::makeAny( true ) );
227 break;
228 }
229 case word::WdViewType::wdPrintPreview:
230 {
231 PrintPreviewHelper( uno::Any(),word::getView( mxModel ) );
232 break;
233 }
234 default:
235 DebugHelper::runtimeexception( ERRCODE_BASIC_NOT_IMPLEMENTED );
236
237 }
238 }
239
getHFTextRange(sal_Int32 nType)240 uno::Reference< text::XTextRange > SwVbaView::getHFTextRange( sal_Int32 nType )
241 {
242 mxModel->lockControllers();
243
244 OUString aPropIsOn;
245 OUString aPropIsShared;
246 OUString aPropBodyDistance;
247 OUString aPropText;
248
249 switch( nType )
250 {
251 case word::WdSeekView::wdSeekCurrentPageFooter:
252 case word::WdSeekView::wdSeekFirstPageFooter:
253 case word::WdSeekView::wdSeekPrimaryFooter:
254 case word::WdSeekView::wdSeekEvenPagesFooter:
255 {
256 aPropIsOn = "FooterIsOn";
257 aPropIsShared = "FooterIsShared";
258 aPropBodyDistance = "FooterBodyDistance";
259 aPropText = "FooterText";
260 break;
261 }
262 case word::WdSeekView::wdSeekCurrentPageHeader:
263 case word::WdSeekView::wdSeekFirstPageHeader:
264 case word::WdSeekView::wdSeekPrimaryHeader:
265 case word::WdSeekView::wdSeekEvenPagesHeader:
266 {
267 aPropIsOn = "HeaderIsOn";
268 aPropIsShared = "HeaderIsShared";
269 aPropBodyDistance = "HeaderBodyDistance";
270 aPropText = "HeaderText";
271 break;
272 }
273 }
274
275 uno::Reference< text::XPageCursor > xPageCursor( mxViewCursor, uno::UNO_QUERY_THROW );
276
277 if( nType == word::WdSeekView::wdSeekFirstPageFooter
278 || nType == word::WdSeekView::wdSeekFirstPageHeader )
279 {
280 xPageCursor->jumpToFirstPage();
281 }
282
283 uno::Reference< style::XStyle > xStyle;
284 uno::Reference< text::XText > xText;
285 switch( nType )
286 {
287 case word::WdSeekView::wdSeekPrimaryFooter:
288 case word::WdSeekView::wdSeekPrimaryHeader:
289 case word::WdSeekView::wdSeekEvenPagesFooter:
290 case word::WdSeekView::wdSeekEvenPagesHeader:
291 {
292 // The primary header is the first header of the section.
293 // If the header is not shared between odd and even pages
294 // the odd page's header is the primary header. If the
295 // first page's header is different from the rest of the
296 // document, it is NOT the primary header ( the next primary
297 // header would be on page 3 )
298 // The even pages' header is only available if the header is
299 // not shared and the current style is applied to a page with
300 // an even page number
301 uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW );
302 OUString aPageStyleName;
303 xCursorProps->getPropertyValue("PageStyleName") >>= aPageStyleName;
304 if ( aPageStyleName == "First Page" )
305 {
306 // go to the beginning of where the next style is used
307 bool hasNextPage = false;
308 xStyle = word::getCurrentPageStyle( mxModel );
309 do
310 {
311 hasNextPage = xPageCursor->jumpToNextPage();
312 }
313 while( hasNextPage && ( xStyle == word::getCurrentPageStyle( mxModel ) ) );
314
315 if( !hasNextPage )
316 DebugHelper::basicexception( ERRCODE_BASIC_BAD_ACTION, {} );
317 }
318 break;
319 }
320 default:
321 {
322 break;
323 }
324 }
325
326 xStyle = word::getCurrentPageStyle( mxModel );
327 uno::Reference< beans::XPropertySet > xPageProps( xStyle, uno::UNO_QUERY_THROW );
328 bool isOn = false;
329 xPageProps->getPropertyValue( aPropIsOn ) >>= isOn;
330 bool isShared = false;
331 xPageProps->getPropertyValue( aPropIsShared ) >>= isShared;
332 if( !isOn )
333 {
334 xPageProps->setPropertyValue( aPropIsOn, uno::makeAny( true ) );
335 xPageProps->setPropertyValue( aPropBodyDistance, uno::makeAny( DEFAULT_BODY_DISTANCE ) );
336 }
337 if( !isShared )
338 {
339 OUString aTempPropText = aPropText;
340 if( nType == word::WdSeekView::wdSeekEvenPagesFooter
341 || nType == word::WdSeekView::wdSeekEvenPagesHeader )
342 {
343 aTempPropText += "Left";
344 }
345 else
346 {
347 aTempPropText += "Right";
348 }
349 xText.set( xPageProps->getPropertyValue( aTempPropText), uno::UNO_QUERY_THROW );
350 }
351 else
352 {
353 if( nType == word::WdSeekView::wdSeekEvenPagesFooter
354 || nType == word::WdSeekView::wdSeekEvenPagesHeader )
355 {
356 DebugHelper::basicexception( ERRCODE_BASIC_BAD_ACTION, {} );
357 }
358 xText.set( xPageProps->getPropertyValue( aPropText ), uno::UNO_QUERY_THROW );
359 }
360
361 mxModel->unlockControllers();
362 if( !xText.is() )
363 {
364 DebugHelper::basicexception( ERRCODE_BASIC_INTERNAL_ERROR, {} );
365 }
366 uno::Reference< text::XTextRange > xTextRange = word::getFirstObjectPosition( xText );
367 return xTextRange;
368 }
369
370 OUString
getServiceImplName()371 SwVbaView::getServiceImplName()
372 {
373 return "SwVbaView";
374 }
375
376 uno::Sequence< OUString >
getServiceNames()377 SwVbaView::getServiceNames()
378 {
379 static uno::Sequence< OUString > const aServiceNames
380 {
381 "ooo.vba.word.View"
382 };
383 return aServiceNames;
384 }
385
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
387